diff --git a/tracing/impl/stackdriver_tracer.go b/tracing/impl/stackdriver_tracer.go index 56cc579e0c9dbcda7e9d95ad05b911e670d124f6..9f785a0467be00bc3fdb96b6f9ed98602c2c571e 100644 --- a/tracing/impl/stackdriver_tracer.go +++ b/tracing/impl/stackdriver_tracer.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "fmt" "io" + "math" "reflect" "strconv" "time" @@ -155,24 +156,33 @@ func (span *adapterSpan) SetOperationName(operationName string) opentracing.Span } func castToAttribute(key string, value any) []trace.Attribute { + // Scalar types + switch v := reflect.ValueOf(value); v.Kind() { + case reflect.Bool: + return []trace.Attribute{trace.BoolAttribute(key, v.Bool())} + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return []trace.Attribute{trace.Int64Attribute(key, v.Int())} + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if v.Uint() > math.MaxInt64 { + return newStringAttribute(key, strconv.FormatUint(v.Uint(), 10)) + } + return []trace.Attribute{trace.Int64Attribute(key, int64(v.Uint()))} + case reflect.Float32, reflect.Float64: + return []trace.Attribute{trace.Float64Attribute(key, v.Float())} + case reflect.String: + return newStringAttribute(key, v.String()) + } + + // Interfaces switch v := value.(type) { - case bool: - return []trace.Attribute{trace.BoolAttribute(key, v)} - case int, int8, int16, int32, int64: - return []trace.Attribute{trace.Int64Attribute(key, reflect.ValueOf(v).Int())} - case uint, uint8, uint16, uint32, uint64: - return []trace.Attribute{trace.Int64Attribute(key, int64(reflect.ValueOf(v).Uint()))} - case float32, float64: - return []trace.Attribute{trace.Float64Attribute(key, reflect.ValueOf(v).Float())} - case string: - return newStringAttribute(key, v) case fmt.Stringer: return newStringAttribute(key, v.String()) - default: - return []trace.Attribute{ - trace.StringAttribute(key, fmt.Sprint(value)), - trace.StringAttribute(key+".error", fmt.Sprintf("unknown type: %T", value)), - } + } + + // Fall-back: fmt.Sprint formatting + return []trace.Attribute{ + trace.StringAttribute(key, fmt.Sprint(value)), + trace.StringAttribute(key+".error", fmt.Sprintf("unknown type: %T", value)), } } @@ -209,10 +219,7 @@ func chunkString(s string, chunkSize int) []string { } var strs []string for i := 0; i*chunkSize < len(s); i++ { - end := (i + 1) * chunkSize - if end > len(s) { - end = len(s) - } + end := min((i+1)*chunkSize, len(s)) strs = append(strs, s[i*chunkSize:end]) } return strs diff --git a/tracing/impl/stackdriver_tracer_test.go b/tracing/impl/stackdriver_tracer_test.go index 66fff0835f059570bbfeace6559a17fcb7a4aec9..b17afa01ecc7b55b6e41073d36b15617d456fb91 100644 --- a/tracing/impl/stackdriver_tracer_test.go +++ b/tracing/impl/stackdriver_tracer_test.go @@ -4,14 +4,17 @@ package impl import ( "fmt" + "math" "net/url" "reflect" + "strconv" "strings" "testing" "time" "contrib.go.opencensus.io/exporter/stackdriver" "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -53,6 +56,20 @@ func TestOcSpanAdapterCastToAttribute(t *testing.T) { value: 42, want: []trace.Attribute{trace.Int64Attribute("foo", 42)}, }, + { + name: "small unsigned integer", + key: "foo", + value: uint(4211), + want: []trace.Attribute{trace.Int64Attribute("foo", 4211)}, + }, + { + name: "unsigned integer exceeding int64 range", + key: "foo", + value: uint64(math.MaxInt64 + math.MaxInt32), + want: []trace.Attribute{ + trace.StringAttribute("foo", strconv.FormatUint(math.MaxInt64+math.MaxInt32, 10)), + }, + }, { name: "42.1", key: "foo", @@ -135,13 +152,21 @@ func TestOcSpanAdapterCastToAttribute(t *testing.T) { }, { name: "net.url type", - key: "foo", + key: "http.url", value: func() *url.URL { u, _ := url.Parse("https://example.com") return u }(), want: []trace.Attribute{ - trace.StringAttribute("foo", "https://example.com"), + trace.StringAttribute("http.url", "https://example.com"), + }, + }, + { + name: "span.kind", + key: "span.kind", + value: ext.SpanKindRPCServerEnum, + want: []trace.Attribute{ + trace.StringAttribute("span.kind", "server"), }, }, }