1
0
Fork 0

Cherry pick v1.7 into master

This commit is contained in:
Ludovic Fernandez 2018-11-19 16:40:03 +01:00 committed by Traefiker Bot
parent a09dfa3ce1
commit b6498cdcbc
73 changed files with 6573 additions and 186 deletions

View file

@ -154,10 +154,19 @@ func FinishTime(t time.Time) FinishOption {
}
}
// WithError adds the given error to the span before marking it as finished. If it is
// nil it will be disregarded.
// WithError marks the span as having had an error. It uses the information from
// err to set tags such as the error message, error type and stack trace.
func WithError(err error) FinishOption {
return func(cfg *ddtrace.FinishConfig) {
cfg.Error = err
}
}
// NoDebugStack prevents any error presented using the WithError finishing option
// from generating a stack trace. This is useful in situations where errors are frequent
// and performance is critical.
func NoDebugStack() FinishOption {
return func(cfg *ddtrace.FinishConfig) {
cfg.NoDebugStack = true
}
}

View file

@ -81,7 +81,7 @@ func (s *span) SetTag(key string, value interface{}) {
return
}
if key == ext.Error {
s.setTagError(value)
s.setTagError(value, true)
return
}
if v, ok := value.(string); ok {
@ -99,7 +99,10 @@ func (s *span) SetTag(key string, value interface{}) {
// setTagError sets the error tag. It accounts for various valid scenarios.
// This method is not safe for concurrent use.
func (s *span) setTagError(value interface{}) {
func (s *span) setTagError(value interface{}, debugStack bool) {
if s.finished {
return
}
switch v := value.(type) {
case bool:
// bool value as per Opentracing spec.
@ -114,7 +117,9 @@ func (s *span) setTagError(value interface{}) {
s.Error = 1
s.Meta[ext.ErrorMsg] = v.Error()
s.Meta[ext.ErrorType] = reflect.TypeOf(v).String()
s.Meta[ext.ErrorStack] = string(debug.Stack())
if debugStack {
s.Meta[ext.ErrorStack] = string(debug.Stack())
}
case nil:
// no error
s.Error = 0
@ -166,7 +171,9 @@ func (s *span) Finish(opts ...ddtrace.FinishOption) {
t = cfg.FinishTime.UnixNano()
}
if cfg.Error != nil {
s.SetTag(ext.Error, cfg.Error)
s.Lock()
s.setTagError(cfg.Error, !cfg.NoDebugStack)
s.Unlock()
}
s.finish(t)
}

View file

@ -63,7 +63,7 @@ func (z *span) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Meta == nil && zb0002 > 0 {
z.Meta = make(map[string]string, zb0002)
} else if len(z.Meta) > 0 {
for key, _ := range z.Meta {
for key := range z.Meta {
delete(z.Meta, key)
}
}
@ -90,7 +90,7 @@ func (z *span) DecodeMsg(dc *msgp.Reader) (err error) {
if z.Metrics == nil && zb0003 > 0 {
z.Metrics = make(map[string]float64, zb0003)
} else if len(z.Metrics) > 0 {
for key, _ := range z.Metrics {
for key := range z.Metrics {
delete(z.Metrics, key)
}
}

View file

@ -17,8 +17,7 @@ var _ TextMapReader = (*HTTPHeadersCarrier)(nil)
// Set implements TextMapWriter.
func (c HTTPHeadersCarrier) Set(key, val string) {
h := http.Header(c)
h.Add(key, val)
http.Header(c).Set(key, val)
}
// ForeachKey implements TextMapReader.
@ -166,12 +165,12 @@ func (p *propagator) extractTextMap(reader TextMapReader) (ddtrace.SpanContext,
key := strings.ToLower(k)
switch key {
case p.cfg.TraceHeader:
ctx.traceID, err = strconv.ParseUint(v, 10, 64)
ctx.traceID, err = parseUint64(v)
if err != nil {
return ErrSpanContextCorrupted
}
case p.cfg.ParentHeader:
ctx.spanID, err = strconv.ParseUint(v, 10, 64)
ctx.spanID, err = parseUint64(v)
if err != nil {
return ErrSpanContextCorrupted
}

View file

@ -64,9 +64,7 @@ func Start(opts ...StartOption) {
if internal.Testing {
return // mock tracer active
}
t := internal.GetGlobalTracer()
internal.SetGlobalTracer(newTracer(opts...))
t.Stop()
}
// Stop stops the started tracer. Subsequent calls are valid but become no-op.
@ -302,16 +300,10 @@ func (t *tracer) flushTraces() {
log.Printf("Sending payload: size: %d traces: %d\n", size, count)
}
err := t.config.transport.send(t.payload)
if err != nil && size > payloadMaxLimit {
// we couldn't send the payload and it is getting too big to be
// accepted by the agent, we have to drop it.
t.payload.reset()
if err != nil {
t.pushError(&dataLossError{context: err, count: count})
}
if err == nil {
// send succeeded
t.payload.reset()
}
t.payload.reset()
}
// flushErrors will process log messages that were queued

View file

@ -10,7 +10,9 @@ import (
"time"
)
var tracerVersion = "v1.0"
// TODO(gbbr): find a more effective way to keep this up to date,
// e.g. via `go generate`
var tracerVersion = "v1.5.0"
const (
defaultHostname = "localhost"
@ -57,16 +59,8 @@ func newHTTPTransport(addr string) *httpTransport {
"Datadog-Meta-Tracer-Version": tracerVersion,
"Content-Type": "application/msgpack",
}
host, port, _ := net.SplitHostPort(addr)
if host == "" {
host = defaultHostname
}
if port == "" {
port = defaultPort
}
addr = fmt.Sprintf("%s:%s", host, port)
return &httpTransport{
traceURL: fmt.Sprintf("http://%s/v0.3/traces", addr),
traceURL: fmt.Sprintf("http://%s/v0.3/traces", resolveAddr(addr)),
client: &http.Client{
// We copy the transport to avoid using the default one, as it might be
// augmented with tracing and we don't want these calls to be recorded.
@ -118,3 +112,20 @@ func (t *httpTransport) send(p *payload) error {
}
return nil
}
// resolveAddr resolves the given agent address and fills in any missing host
// and port using the defaults.
func resolveAddr(addr string) string {
host, port, err := net.SplitHostPort(addr)
if err != nil {
// no port in addr
host = addr
}
if host == "" {
host = defaultHostname
}
if port == "" {
port = defaultPort
}
return fmt.Sprintf("%s:%s", host, port)
}

View file

@ -1,5 +1,10 @@
package tracer
import (
"strconv"
"strings"
)
// toFloat64 attempts to convert value into a float64. If it succeeds it returns
// the value and true, otherwise 0 and false.
func toFloat64(value interface{}) (f float64, ok bool) {
@ -30,3 +35,16 @@ func toFloat64(value interface{}) (f float64, ok bool) {
return 0, false
}
}
// parseUint64 parses a uint64 from either an unsigned 64 bit base-10 string
// or a signed 64 bit base-10 string representing an unsigned integer
func parseUint64(str string) (uint64, error) {
if strings.HasPrefix(str, "-") {
id, err := strconv.ParseInt(str, 10, 64)
if err != nil {
return 0, err
}
return uint64(id), nil
}
return strconv.ParseUint(str, 10, 64)
}