diff --git a/instrumentation/opentelemetry/span.go b/instrumentation/opentelemetry/span.go index 164e907..79e7de0 100644 --- a/instrumentation/opentelemetry/span.go +++ b/instrumentation/opentelemetry/span.go @@ -31,13 +31,12 @@ func (l *AttributeList) GetValue(key string) interface{} { return nil } -func (l *AttributeList) GetAll() []sdk.Attribute { - size := len(l.attrs) - attributes := make([]sdk.Attribute, size) - for i := 0; i < size; i++ { - attributes[i] = sdk.Attribute{Key: string(l.attrs[i].Key), Value: l.attrs[i].Value.AsInterface()} +func (l *AttributeList) Iterate(yield func(key string, value interface{}) bool) { + for _, attr := range l.attrs { + if !yield(string(attr.Key), attr.Value.AsInterface()) { + return + } } - return attributes } var _ sdk.Span = (*Span)(nil) diff --git a/instrumentation/opentelemetry/span_test.go b/instrumentation/opentelemetry/span_test.go index c1c9764..2e8d01e 100644 --- a/instrumentation/opentelemetry/span_test.go +++ b/instrumentation/opentelemetry/span_test.go @@ -110,7 +110,7 @@ func TestGetAttributes(t *testing.T) { assert.Equal(t, nil, attrs.GetValue("non_existent")) } -func TestGetAllAttributes(t *testing.T) { +func TestIterate(t *testing.T) { sampler := sdktrace.AlwaysSample() tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sampler), @@ -119,15 +119,17 @@ func TestGetAllAttributes(t *testing.T) { _, s, _ := StartSpan(context.Background(), "test_span", &sdk.SpanOptions{}) s.SetAttribute("k1", "v1") s.SetAttribute("k2", 200) - attrs := s.GetAttributes().GetAll() - // service.instance.id is added implicitly in StartSpan so 3 attributes will be present. - assert.Equal(t, 3, len(attrs)) - for _, attr := range attrs { - if attr.Key == "k1" { - assert.Equal(t, "v1", fmt.Sprintf("%v", attr.Value)) - } else if attr.Key == "k2" { - assert.Equal(t, "200", fmt.Sprintf("%v", attr.Value)) + numAttrs := 0 + s.GetAttributes().Iterate(func(key string, value interface{}) bool { + if key == "k1" { + assert.Equal(t, "v1", fmt.Sprintf("%v", value)) + } else if key == "k2" { + assert.Equal(t, "200", fmt.Sprintf("%v", value)) } - } + numAttrs++ + return true + }) + // service.instance.id is added implicitly in StartSpan so 3 attributes will be present. + assert.Equal(t, 3, numAttrs) } diff --git a/sdk/internal/mock/span.go b/sdk/internal/mock/span.go index 08f2047..e8b279f 100644 --- a/sdk/internal/mock/span.go +++ b/sdk/internal/mock/span.go @@ -29,15 +29,12 @@ func (l *AttributeList) GetValue(key string) interface{} { return l.attrs[key] } -func (l *AttributeList) GetAll() []sdk.Attribute { - - attributes := make([]sdk.Attribute, len(l.attrs)) - i := 0 +func (l *AttributeList) Iterate(yield func(key string, value interface{}) bool) { for key, value := range l.attrs { - attributes[i] = sdk.Attribute{Key: key, Value: value} - i++ + if !yield(key, value) { + return + } } - return attributes } var _ sdk.Span = &Span{} diff --git a/sdk/span.go b/sdk/span.go index 54dc8c7..8f34577 100644 --- a/sdk/span.go +++ b/sdk/span.go @@ -5,14 +5,12 @@ import ( "time" ) -type Attribute struct { - Key string - Value interface{} -} - type AttributeList interface { GetValue(key string) interface{} - GetAll() []Attribute + + // Iterate loops through the attributes list and applies the yield function on each attribute. + // If the yield function returns false, we exit the loop. + Iterate(yield func(key string, value interface{}) bool) } // Span is an interface that accepts attributes and can be