diff --git a/CHANGELOG.md b/CHANGELOG.md index 16cff070c06..cdfa4ea2a9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Added the `WithRetry` option to the `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` package. This option is a replacement for the removed `WithMaxAttempts` and `WithBackoff` options. (#2095) - Added API `LinkFromContext` to return Link which encapsulates SpanContext from provided context and also encapsulates attributes. (#2115) +- Added a new `Link` type under the SDK `otel/sdk/trace` package that counts the number of attributes that were dropped for surpassing the `AttributePerLinkCountLimit` configured in the Span's `SpanLimits`. + This new type replaces the equal-named API `Link` type found in the `otel/trace` package for most usages within the SDK. + For example, instances of this type are now returned by the `Links()` function of `ReadOnlySpan`s provided in places like the `OnEnd` function of `SpanProcessor` implementations. (#2118) ### Changed @@ -35,6 +38,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Removed the `WithMaxAttempts` and `WithBackoff` options from the `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` package. The retry logic of the package has been updated to match the `otlptracegrpc` package and accordingly a `WithRetry` option is added that should be used instead. (#2095) - Removed metrics test package `go.opentelemetry.io/otel/sdk/export/metric/metrictest`. (#2105) +- Removed `DroppedAttributeCount` field from `otel/trace.Link` struct. (#2118) ### Fixed diff --git a/exporters/jaeger/jaeger_test.go b/exporters/jaeger/jaeger_test.go index 4db4a36ddef..b9844b7d2f7 100644 --- a/exporters/jaeger/jaeger_test.go +++ b/exporters/jaeger/jaeger_test.go @@ -219,7 +219,7 @@ func Test_spanSnapshotToThrift(t *testing.T) { Name: "/foo", StartTime: now, EndTime: now, - Links: []trace.Link{ + Links: []sdktrace.Link{ { SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ TraceID: linkTraceID, @@ -311,7 +311,7 @@ func Test_spanSnapshotToThrift(t *testing.T) { TraceID: traceID, SpanID: parentSpanID, }), - Links: []trace.Link{ + Links: []sdktrace.Link{ { SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ TraceID: linkTraceID, diff --git a/exporters/otlp/otlptrace/internal/otlptracetest/data.go b/exporters/otlp/otlptrace/internal/otlptracetest/data.go index 71708cd7393..cf6142e01db 100644 --- a/exporters/otlp/otlptrace/internal/otlptracetest/data.go +++ b/exporters/otlp/otlptrace/internal/otlptracetest/data.go @@ -47,7 +47,7 @@ func SingleReadOnlySpan() []tracesdk.ReadOnlySpan { EndTime: time.Date(2020, time.December, 0, 20, 24, 0, 0, time.UTC), Attributes: []attribute.KeyValue{}, Events: []tracesdk.Event{}, - Links: []trace.Link{}, + Links: []tracesdk.Link{}, Status: tracesdk.Status{Code: codes.Ok}, DroppedAttributes: 0, DroppedEvents: 0, diff --git a/exporters/otlp/otlptrace/internal/tracetransform/span.go b/exporters/otlp/otlptrace/internal/tracetransform/span.go index d6ac6377ed2..d9f0831092c 100644 --- a/exporters/otlp/otlptrace/internal/tracetransform/span.go +++ b/exporters/otlp/otlptrace/internal/tracetransform/span.go @@ -146,7 +146,7 @@ func status(status codes.Code, message string) *tracepb.Status { } // links transforms span Links to OTLP span links. -func links(links []trace.Link) []*tracepb.Span_Link { +func links(links []tracesdk.Link) []*tracepb.Span_Link { if len(links) == 0 { return nil } diff --git a/exporters/otlp/otlptrace/internal/tracetransform/span_test.go b/exporters/otlp/otlptrace/internal/tracetransform/span_test.go index 62b7cc161f7..d220d770ab3 100644 --- a/exporters/otlp/otlptrace/internal/tracetransform/span_test.go +++ b/exporters/otlp/otlptrace/internal/tracetransform/span_test.go @@ -120,12 +120,12 @@ func TestNilLinks(t *testing.T) { } func TestEmptyLinks(t *testing.T) { - assert.Nil(t, links([]trace.Link{})) + assert.Nil(t, links([]tracesdk.Link{})) } func TestLinks(t *testing.T) { attrs := []attribute.KeyValue{attribute.Int("one", 1), attribute.Int("two", 2)} - l := []trace.Link{ + l := []tracesdk.Link{ {}, { SpanContext: trace.SpanContext{}, @@ -234,7 +234,7 @@ func TestSpanData(t *testing.T) { }, }, }, - Links: []trace.Link{ + Links: []tracesdk.Link{ { SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ TraceID: trace.TraceID{0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF}, @@ -244,6 +244,7 @@ func TestSpanData(t *testing.T) { Attributes: []attribute.KeyValue{ attribute.String("LinkType", "Parent"), }, + DroppedAttributeCount: 0, }, { SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ @@ -254,6 +255,7 @@ func TestSpanData(t *testing.T) { Attributes: []attribute.KeyValue{ attribute.String("LinkType", "Child"), }, + DroppedAttributeCount: 0, }, }, Status: tracesdk.Status{ diff --git a/sdk/trace/link.go b/sdk/trace/link.go new file mode 100644 index 00000000000..19cfea4ba45 --- /dev/null +++ b/sdk/trace/link.go @@ -0,0 +1,34 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package trace // import "go.opentelemetry.io/otel/sdk/trace" + +import ( + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +// Link is the relationship between two Spans. The relationship can be within +// the same Trace or across different Traces. +type Link struct { + // SpanContext of the linked Span. + SpanContext trace.SpanContext + + // Attributes describe the aspects of the link. + Attributes []attribute.KeyValue + + // DroppedAttributeCount is the number of attributes that were not + // recorded due to configured limits being reached. + DroppedAttributeCount int +} diff --git a/sdk/trace/snapshot.go b/sdk/trace/snapshot.go index 847617a382b..68670bb0b54 100644 --- a/sdk/trace/snapshot.go +++ b/sdk/trace/snapshot.go @@ -34,7 +34,7 @@ type snapshot struct { endTime time.Time attributes []attribute.KeyValue events []Event - links []trace.Link + links []Link status Status childSpanCount int droppedAttributeCount int @@ -87,7 +87,7 @@ func (s snapshot) Attributes() []attribute.KeyValue { } // Links returns all the links the span has to other spans. -func (s snapshot) Links() []trace.Link { +func (s snapshot) Links() []Link { return s.links } diff --git a/sdk/trace/span.go b/sdk/trace/span.go index 722f354762f..5200fa59b7a 100644 --- a/sdk/trace/span.go +++ b/sdk/trace/span.go @@ -55,7 +55,7 @@ type ReadOnlySpan interface { // Attributes returns the defining attributes of the span. Attributes() []attribute.KeyValue // Links returns all the links the span has to other spans. - Links() []trace.Link + Links() []Link // Events returns all the events that occurred within in the spans // lifetime. Events() []Event @@ -386,11 +386,11 @@ func (s *span) Attributes() []attribute.KeyValue { } // Links returns the links of this span. -func (s *span) Links() []trace.Link { +func (s *span) Links() []Link { s.mu.Lock() defer s.mu.Unlock() if len(s.links.queue) == 0 { - return []trace.Link{} + return []Link{} } return s.interfaceArrayToLinksArray() } @@ -435,13 +435,15 @@ func (s *span) addLink(link trace.Link) { s.mu.Lock() defer s.mu.Unlock() + var droppedAttributeCount int + // Discard over limited attributes if len(link.Attributes) > s.spanLimits.AttributePerLinkCountLimit { - link.DroppedAttributeCount = len(link.Attributes) - s.spanLimits.AttributePerLinkCountLimit + droppedAttributeCount = len(link.Attributes) - s.spanLimits.AttributePerLinkCountLimit link.Attributes = link.Attributes[:s.spanLimits.AttributePerLinkCountLimit] } - s.links.add(link) + s.links.add(Link{link.SpanContext, link.Attributes, droppedAttributeCount}) } // DroppedAttributes returns the number of attributes dropped by the span @@ -514,10 +516,10 @@ func (s *span) snapshot() ReadOnlySpan { return &sd } -func (s *span) interfaceArrayToLinksArray() []trace.Link { - linkArr := make([]trace.Link, 0) +func (s *span) interfaceArrayToLinksArray() []Link { + linkArr := make([]Link, 0) for _, value := range s.links.queue { - linkArr = append(linkArr, value.(trace.Link)) + linkArr = append(linkArr, value.(Link)) } return linkArr } diff --git a/sdk/trace/trace_test.go b/sdk/trace/trace_test.go index 4bf1116108b..e7e2084c883 100644 --- a/sdk/trace/trace_test.go +++ b/sdk/trace/trace_test.go @@ -656,10 +656,10 @@ func TestLinks(t *testing.T) { sc1 := trace.NewSpanContext(trace.SpanContextConfig{TraceID: trace.TraceID([16]byte{1, 1}), SpanID: trace.SpanID{3}}) sc2 := trace.NewSpanContext(trace.SpanContextConfig{TraceID: trace.TraceID([16]byte{1, 1}), SpanID: trace.SpanID{3}}) - links := []trace.Link{ - {SpanContext: sc1, Attributes: []attribute.KeyValue{k1v1}}, - {SpanContext: sc2, Attributes: []attribute.KeyValue{k2v2, k3v3}}, - } + l1 := trace.Link{SpanContext: sc1, Attributes: []attribute.KeyValue{k1v1}} + l2 := trace.Link{SpanContext: sc2, Attributes: []attribute.KeyValue{k2v2, k3v3}} + + links := []trace.Link{l1, l2} span := startSpan(tp, "Links", trace.WithLinks(links...)) got, err := endSpan(te, span) @@ -674,7 +674,7 @@ func TestLinks(t *testing.T) { }), parent: sc.WithRemote(true), name: "span0", - links: links, + links: []Link{{l1.SpanContext, l1.Attributes, 0}, {l2.SpanContext, l2.Attributes, 0}}, spanKind: trace.SpanKindInternal, instrumentationLibrary: instrumentation.Library{Name: "Links"}, } @@ -715,9 +715,9 @@ func TestLinksOverLimit(t *testing.T) { }), parent: sc.WithRemote(true), name: "span0", - links: []trace.Link{ - {SpanContext: sc2, Attributes: []attribute.KeyValue{k2v2}}, - {SpanContext: sc3, Attributes: []attribute.KeyValue{k3v3}}, + links: []Link{ + {SpanContext: sc2, Attributes: []attribute.KeyValue{k2v2}, DroppedAttributeCount: 0}, + {SpanContext: sc3, Attributes: []attribute.KeyValue{k3v3}, DroppedAttributeCount: 0}, }, droppedLinkCount: 1, spanKind: trace.SpanKindInternal, @@ -1585,7 +1585,7 @@ func TestAddLinksWithMoreAttributesThanLimit(t *testing.T) { }), parent: sc.WithRemote(true), name: "span0", - links: []trace.Link{ + links: []Link{ { SpanContext: sc1, Attributes: []attribute.KeyValue{k1v1}, diff --git a/sdk/trace/tracetest/span.go b/sdk/trace/tracetest/span.go index 0e6da2e081d..ece4633c525 100644 --- a/sdk/trace/tracetest/span.go +++ b/sdk/trace/tracetest/span.go @@ -63,7 +63,7 @@ type SpanStub struct { EndTime time.Time Attributes []attribute.KeyValue Events []tracesdk.Event - Links []trace.Link + Links []tracesdk.Link Status tracesdk.Status DroppedAttributes int DroppedEvents int @@ -133,7 +133,7 @@ type spanSnapshot struct { endTime time.Time attributes []attribute.KeyValue events []tracesdk.Event - links []trace.Link + links []tracesdk.Link status tracesdk.Status droppedAttributes int droppedEvents int @@ -150,7 +150,7 @@ func (s spanSnapshot) SpanKind() trace.SpanKind { return s.spanKind } func (s spanSnapshot) StartTime() time.Time { return s.startTime } func (s spanSnapshot) EndTime() time.Time { return s.endTime } func (s spanSnapshot) Attributes() []attribute.KeyValue { return s.attributes } -func (s spanSnapshot) Links() []trace.Link { return s.links } +func (s spanSnapshot) Links() []tracesdk.Link { return s.links } func (s spanSnapshot) Events() []tracesdk.Event { return s.events } func (s spanSnapshot) Status() tracesdk.Status { return s.status } func (s spanSnapshot) DroppedAttributes() int { return s.droppedAttributes } diff --git a/trace/trace.go b/trace/trace.go index 8564cb9dfe6..0923ceb98d5 100644 --- a/trace/trace.go +++ b/trace/trace.go @@ -402,10 +402,6 @@ type Link struct { // Attributes describe the aspects of the link. Attributes []attribute.KeyValue - - // DroppedAttributeCount is the number of attributes that were not - // recorded due to configured limits being reached. - DroppedAttributeCount int } // LinkFromContext returns a link encapsulating the SpanContext in the provided ctx.