Skip to content

Commit

Permalink
map unrecognized k,v where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
lucix-aws committed Sep 3, 2024
1 parent 941c904 commit 99644da
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 29 deletions.
47 changes: 25 additions & 22 deletions tracing/smithy-otel-tracing/adapt.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package smithyoteltracing

import (
"context"
"fmt"

"github.com/aws/smithy-go"
"github.com/aws/smithy-go/tracing"
Expand Down Expand Up @@ -104,9 +105,7 @@ func (s *span) AddEvent(name string, opts ...tracing.EventOption) {
}

func (s *span) SetProperty(k, v any) {
if kv, ok := toOTELKeyValue(k, v); ok {
s.otel.SetAttributes(kv)
}
s.otel.SetAttributes(toOTELKeyValue(k, v))
}

func (s *span) SetStatus(status tracing.SpanStatus) {
Expand Down Expand Up @@ -143,44 +142,48 @@ func toOTELSpanStatus(v tracing.SpanStatus) otelcodes.Code {
}
}

func toOTELKeyValue(k, v any) (otelattribute.KeyValue, bool) {
kk, ok := k.(string)
if !ok {
return otelattribute.KeyValue{}, false
}
func toOTELKeyValue(k, v any) otelattribute.KeyValue {
kk := str(k)

switch vv := v.(type) {
case bool:
return otelattribute.Bool(kk, vv), true
return otelattribute.Bool(kk, vv)
case []bool:
return otelattribute.BoolSlice(kk, vv), true
return otelattribute.BoolSlice(kk, vv)
case int:
return otelattribute.Int(kk, vv), true
return otelattribute.Int(kk, vv)
case []int:
return otelattribute.IntSlice(kk, vv), true
return otelattribute.IntSlice(kk, vv)
case int64:
return otelattribute.Int64(kk, vv), true
return otelattribute.Int64(kk, vv)
case []int64:
return otelattribute.Int64Slice(kk, vv), true
return otelattribute.Int64Slice(kk, vv)
case float64:
return otelattribute.Float64(kk, vv), true
return otelattribute.Float64(kk, vv)
case []float64:
return otelattribute.Float64Slice(kk, vv), true
return otelattribute.Float64Slice(kk, vv)
case string:
return otelattribute.String(kk, vv), true
return otelattribute.String(kk, vv)
case []string:
return otelattribute.StringSlice(kk, vv), true
return otelattribute.StringSlice(kk, vv)
default:
return otelattribute.KeyValue{}, false
return otelattribute.String(kk, str(v))
}
}

func toOTELKeyValues(props smithy.Properties) []otelattribute.KeyValue {
var kvs []otelattribute.KeyValue
for k, v := range props.Values() {
if kv, ok := toOTELKeyValue(k, v); ok {
kvs = append(kvs, kv)
}
kvs = append(kvs, toOTELKeyValue(k, v))
}
return kvs
}

func str(v any) string {
if s, ok := v.(string); ok {
return s
} else if s, ok := v.(fmt.Stringer); ok {
return s.String()
}
return fmt.Sprintf("%#v", v)
}
16 changes: 13 additions & 3 deletions tracing/smithy-otel-tracing/adapt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,23 @@ func TestToOTELSpanStatus(t *testing.T) {
}
}

type stringer struct{}

func (s stringer) String() string {
return "stringer"
}

type notstringer struct{}

func TestToOTELKeyValue(t *testing.T) {
for _, tt := range []struct {
K, V any
Expect otelattribute.KeyValue
}{
{1, "asdf", otelattribute.KeyValue{}}, // non-string key
{"key", uint(0), otelattribute.KeyValue{}}, // unsupported value type
{1, "asdf", otelattribute.String("1", "asdf")}, // non-string key
{"key", stringer{}, otelattribute.String("key", "stringer")}, // stringer
// unsupported value type
{"key", notstringer{}, otelattribute.String("key", "smithyoteltracing.notstringer{}")},
{"key", true, otelattribute.Bool("key", true)},
{"key", []bool{true, false}, otelattribute.BoolSlice("key", []bool{true, false})},
{"key", int(1), otelattribute.Int("key", 1)},
Expand All @@ -72,7 +82,7 @@ func TestToOTELKeyValue(t *testing.T) {
} {
name := fmt.Sprintf("(%v, %v) -> %v", tt.K, tt.V, tt.Expect)
t.Run(name, func(t *testing.T) {
actual, _ := toOTELKeyValue(tt.K, tt.V)
actual := toOTELKeyValue(tt.K, tt.V)
if tt.Expect != actual {
t.Errorf("%v != %v", tt.Expect, actual)
}
Expand Down
19 changes: 15 additions & 4 deletions tracing/smithy-otel-tracing/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,24 @@
//
// A key-value pair set on a [smithy.Properties] container in any of the
// tracing APIs will automatically propagate to the underlying OTEL SDK if its
// key is of type string, and its value is of one of the supported types. All
// other values are silently ignored.
// key is of type string and its value is one of those supported. Otherwise,
// the adapter will make an effort to stringify the key or value as follows:
// - if value implements String(), use that value
// - otherwise, use the Go-string representation of the value (the result of fmt.Sprintf("%#v", ...))
//
// e.g.
//
// type key struct{}
//
// func (k key) String() string {
// return "app.key"
// }
//
// type key2 struct{}
//
// ctx, span := tracing.StartSpan(ctx, "Foo", func(o *tracing.SpanOptions) {
// o.Properties.Set("app.version", "bar") // propagates to OTEL
// o.Properties.Set(customPropertyKey{}, "baz") // does not
// o.Properties.Set("app.version", "bar") // -> ("app.version", "bar")
// o.Properties.Set(key{}, "baz") // -> ("app.key", "baz")
// o.Properties.Set(key2{}, "qux") // -> ("main.key2{}", "qux")
// })
package smithyoteltracing

0 comments on commit 99644da

Please sign in to comment.