diff --git a/trace/basetypes.go b/trace/basetypes.go index e57a05340..3ba7f0a34 100644 --- a/trace/basetypes.go +++ b/trace/basetypes.go @@ -41,46 +41,26 @@ type Annotation struct { Attributes map[string]interface{} } -// Attribute is an interface for attributes; -// it is implemented by BoolAttribute, IntAttribute, and StringAttribute. -type Attribute interface { - isAttribute() +// Attribute represents a key-value pair on a span, link or annotation. +// Construct with one of: BoolAttribute, Int64Attribute, or StringAttribute. +type Attribute struct { + key string + value interface{} } // BoolAttribute returns a bool-valued attribute. func BoolAttribute(key string, value bool) Attribute { - return boolAttribute{key: key, value: value} -} - -type boolAttribute struct { - key string - value bool + return Attribute{key: key, value: value} } -func (b boolAttribute) isAttribute() {} - -type int64Attribute struct { - key string - value int64 -} - -func (i int64Attribute) isAttribute() {} - // Int64Attribute returns an int64-valued attribute. func Int64Attribute(key string, value int64) Attribute { - return int64Attribute{key: key, value: value} -} - -type stringAttribute struct { - key string - value string + return Attribute{key: key, value: value} } -func (s stringAttribute) isAttribute() {} - // StringAttribute returns a string-valued attribute. func StringAttribute(key string, value string) Attribute { - return stringAttribute{key: key, value: value} + return Attribute{key: key, value: value} } // LinkType specifies the relationship between the span that had the link diff --git a/trace/benchmark_test.go b/trace/benchmark_test.go index 3d6945789..8d00717ae 100644 --- a/trace/benchmark_test.go +++ b/trace/benchmark_test.go @@ -20,66 +20,86 @@ import ( ) func BenchmarkStartEndSpan(b *testing.B) { - ctx := context.Background() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - _, span := StartSpan(ctx, "/foo") - span.End() - } + traceBenchmark(b, func(b *testing.B) { + ctx := context.Background() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, span := StartSpan(ctx, "/foo") + span.End() + } + }) } func BenchmarkSpanWithAnnotations_3(b *testing.B) { - ctx := context.Background() - b.ResetTimer() + traceBenchmark(b, func(b *testing.B) { + ctx := context.Background() + b.ResetTimer() - for i := 0; i < b.N; i++ { - _, span := StartSpan(ctx, "/foo") - span.SetAttributes( - BoolAttribute("key1", false), - StringAttribute("key2", "hello"), - Int64Attribute("key3", 123), - ) - span.End() - } + for i := 0; i < b.N; i++ { + _, span := StartSpan(ctx, "/foo") + span.SetAttributes( + BoolAttribute("key1", false), + StringAttribute("key2", "hello"), + Int64Attribute("key3", 123), + ) + span.End() + } + }) } func BenchmarkSpanWithAnnotations_6(b *testing.B) { - ctx := context.Background() - b.ResetTimer() + traceBenchmark(b, func(b *testing.B) { + ctx := context.Background() + b.ResetTimer() - for i := 0; i < b.N; i++ { - _, span := StartSpan(ctx, "/foo") - span.SetAttributes( - BoolAttribute("key1", false), - BoolAttribute("key2", true), - StringAttribute("key3", "hello"), - StringAttribute("key4", "hello"), - Int64Attribute("key5", 123), - Int64Attribute("key6", 456), - ) - span.End() - } + for i := 0; i < b.N; i++ { + _, span := StartSpan(ctx, "/foo") + span.SetAttributes( + BoolAttribute("key1", false), + BoolAttribute("key2", true), + StringAttribute("key3", "hello"), + StringAttribute("key4", "hello"), + Int64Attribute("key5", 123), + Int64Attribute("key6", 456), + ) + span.End() + } + }) } func BenchmarkTraceID_DotString(b *testing.B) { - b.ReportAllocs() - t := TraceID{0x0D, 0x0E, 0x0A, 0x0D, 0x0B, 0x0E, 0x0E, 0x0F, 0x0F, 0x0E, 0x0E, 0x0B, 0x0D, 0x0A, 0x0E, 0x0D} - want := "0d0e0a0d0b0e0e0f0f0e0e0b0d0a0e0d" - for i := 0; i < b.N; i++ { - if got := t.String(); got != want { - b.Fatalf("got = %q want = %q", got, want) + traceBenchmark(b, func(b *testing.B) { + t := TraceID{0x0D, 0x0E, 0x0A, 0x0D, 0x0B, 0x0E, 0x0E, 0x0F, 0x0F, 0x0E, 0x0E, 0x0B, 0x0D, 0x0A, 0x0E, 0x0D} + want := "0d0e0a0d0b0e0e0f0f0e0e0b0d0a0e0d" + for i := 0; i < b.N; i++ { + if got := t.String(); got != want { + b.Fatalf("got = %q want = %q", got, want) + } } - } + }) } func BenchmarkSpanID_DotString(b *testing.B) { - b.ReportAllocs() - s := SpanID{0x0D, 0x0E, 0x0A, 0x0D, 0x0B, 0x0E, 0x0E, 0x0F} - want := "0d0e0a0d0b0e0e0f" - for i := 0; i < b.N; i++ { - if got := s.String(); got != want { - b.Fatalf("got = %q want = %q", got, want) + traceBenchmark(b, func(b *testing.B) { + s := SpanID{0x0D, 0x0E, 0x0A, 0x0D, 0x0B, 0x0E, 0x0E, 0x0F} + want := "0d0e0a0d0b0e0e0f" + for i := 0; i < b.N; i++ { + if got := s.String(); got != want { + b.Fatalf("got = %q want = %q", got, want) + } } - } + }) +} + +func traceBenchmark(b *testing.B, fn func(*testing.B)) { + b.Run("AlwaysSample", func(b *testing.B) { + b.ReportAllocs() + SetDefaultSampler(AlwaysSample()) + fn(b) + }) + b.Run("NeverSample", func(b *testing.B) { + b.ReportAllocs() + SetDefaultSampler(NeverSample()) + fn(b) + }) } diff --git a/trace/trace.go b/trace/trace.go index b6ad0c60e..d669399c2 100644 --- a/trace/trace.go +++ b/trace/trace.go @@ -273,14 +273,7 @@ func (s *Span) SetAttributes(attributes ...Attribute) { // copyAttributes copies a slice of Attributes into a map. func copyAttributes(m map[string]interface{}, attributes []Attribute) { for _, a := range attributes { - switch a := a.(type) { - case boolAttribute: - m[a.key] = a.value - case int64Attribute: - m[a.key] = a.value - case stringAttribute: - m[a.key] = a.value - } + m[a.key] = a.value } }