1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-01-30 04:40:41 +02:00

Record links/events attribute drops independently (#1771)

* Record links/events attribute drops independently

* Update PR number

* Remove unneeded span.droppedAttributeCount
This commit is contained in:
Tyler Yahn 2021-04-06 14:51:15 +00:00 committed by GitHub
parent 5bbfc22cbc
commit e9aaa04b8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 56 additions and 21 deletions

View File

@ -30,6 +30,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE` - `OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE`
- `OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE` - `OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE`
- `trace.TraceFlags` is now a defined type over `byte` and `WithSampled(bool) TraceFlags` and `IsSampled() bool` methods have been added to it. (#1770) - `trace.TraceFlags` is now a defined type over `byte` and `WithSampled(bool) TraceFlags` and `IsSampled() bool` methods have been added to it. (#1770)
- The `Event` and `Link` struct types from the `go.opentelemetry.io/otel` package now include a `DroppedAttributeCount` field to record the number of attributes that were not recorded due to configured limits being reached. (#1771)
- The Jaeger exporter now reports dropped attributes for a Span event in the exported log. (#1771)
### Fixed ### Fixed
@ -54,6 +56,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
This changes it to make `SamplingParameters` conform with the OpenTelemetry specification. (#1749) This changes it to make `SamplingParameters` conform with the OpenTelemetry specification. (#1749)
- Modify `BatchSpanProcessor.ForceFlush` to abort after timeout/cancellation. (#1757) - Modify `BatchSpanProcessor.ForceFlush` to abort after timeout/cancellation. (#1757)
- Improve OTLP/gRPC exporter connection errors. (#1737) - Improve OTLP/gRPC exporter connection errors. (#1737)
- The `DroppedAttributeCount` field of the `Span` in the `go.opentelemetry.io/otel` package now only represents the number of attributes dropped for the span itself.
It no longer is a conglomerate of itself, events, and link attributes that have been dropped. (#1771)
- Make `ExportSpans` in Jaeger Exporter honor context deadline. (#1773) - Make `ExportSpans` in Jaeger Exporter honor context deadline. (#1773)
### Removed ### Removed

View File

@ -113,6 +113,7 @@ func TestExporter_ExportSpan(t *testing.T) {
`"Value":{"Type":"STRING","Value":"value"}` + `"Value":{"Type":"STRING","Value":"value"}` +
`}` + `}` +
`],` + `],` +
`"DroppedAttributeCount":0,` +
`"Time":` + string(expectedSerializedNow) + `"Time":` + string(expectedSerializedNow) +
`},` + `},` +
`{` + `{` +
@ -123,6 +124,7 @@ func TestExporter_ExportSpan(t *testing.T) {
`"Value":{"Type":"FLOAT64","Value":123.456}` + `"Value":{"Type":"FLOAT64","Value":123.456}` +
`}` + `}` +
`],` + `],` +
`"DroppedAttributeCount":0,` +
`"Time":` + string(expectedSerializedNow) + `"Time":` + string(expectedSerializedNow) +
`}` + `}` +
`],` + `],` +

View File

@ -41,6 +41,7 @@ const (
keySpanKind = "span.kind" keySpanKind = "span.kind"
keyStatusCode = "otel.status_code" keyStatusCode = "otel.status_code"
keyStatusMessage = "otel.status_description" keyStatusMessage = "otel.status_description"
keyDroppedAttributeCount = "otel.event.dropped_attributes_count"
keyEventName = "event" keyEventName = "event"
) )
@ -301,6 +302,9 @@ func spanSnapshotToThrift(ss *export.SpanSnapshot) *gen.Span {
if a.Name != "" { if a.Name != "" {
nTags++ nTags++
} }
if a.DroppedAttributeCount != 0 {
nTags++
}
fields := make([]*gen.Tag, 0, nTags) fields := make([]*gen.Tag, 0, nTags)
if a.Name != "" { if a.Name != "" {
// If an event contains an attribute with the same key, it needs // If an event contains an attribute with the same key, it needs
@ -313,6 +317,9 @@ func spanSnapshotToThrift(ss *export.SpanSnapshot) *gen.Span {
fields = append(fields, tag) fields = append(fields, tag)
} }
} }
if a.DroppedAttributeCount != 0 {
fields = append(fields, getInt64Tag(keyDroppedAttributeCount, int64(a.DroppedAttributeCount)))
}
logs = append(logs, &gen.Log{ logs = append(logs, &gen.Log{
Timestamp: a.Time.UnixNano() / 1000, Timestamp: a.Time.UnixNano() / 1000,
Fields: fields, Fields: fields,

View File

@ -356,6 +356,7 @@ func Test_spanSnapshotToThrift(t *testing.T) {
linkSpanID, _ := trace.SpanIDFromHex("0102030405060709") linkSpanID, _ := trace.SpanIDFromHex("0102030405060709")
eventNameValue := "event-test" eventNameValue := "event-test"
eventDropped := int64(10)
keyValue := "value" keyValue := "value"
statusCodeValue := int64(1) statusCodeValue := int64(1)
doubleValue := 123.456 doubleValue := 123.456
@ -432,7 +433,12 @@ func Test_spanSnapshotToThrift(t *testing.T) {
attribute.Int64("int", intValue), attribute.Int64("int", intValue),
}, },
MessageEvents: []trace.Event{ MessageEvents: []trace.Event{
{Name: eventNameValue, Attributes: []attribute.KeyValue{attribute.String("k1", keyValue)}, Time: now}, {
Name: eventNameValue,
Attributes: []attribute.KeyValue{attribute.String("k1", keyValue)},
DroppedAttributeCount: int(eventDropped),
Time: now,
},
}, },
StatusCode: codes.Error, StatusCode: codes.Error,
StatusMessage: statusMessage, StatusMessage: statusMessage,
@ -482,6 +488,11 @@ func Test_spanSnapshotToThrift(t *testing.T) {
VStr: &keyValue, VStr: &keyValue,
VType: gen.TagType_STRING, VType: gen.TagType_STRING,
}, },
{
Key: keyDroppedAttributeCount,
VLong: &eventDropped,
VType: gen.TagType_LONG,
},
}, },
}, },
}, },

View File

@ -68,7 +68,7 @@ type SpanSnapshot struct {
StatusCode codes.Code StatusCode codes.Code
StatusMessage string StatusMessage string
// DroppedAttributeCount contains dropped attributes for the span itself, events and links. // DroppedAttributeCount contains dropped attributes for the span itself.
DroppedAttributeCount int DroppedAttributeCount int
DroppedMessageEventCount int DroppedMessageEventCount int
DroppedLinkCount int DroppedLinkCount int

View File

@ -19,7 +19,6 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"sync" "sync"
"sync/atomic"
"time" "time"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
@ -75,9 +74,6 @@ type ReadWriteSpan interface {
// span is an implementation of the OpenTelemetry Span API representing the // span is an implementation of the OpenTelemetry Span API representing the
// individual component of a trace. // individual component of a trace.
type span struct { type span struct {
// droppedAttributeCount contains dropped attributes for the events and links.
droppedAttributeCount int64
// mu protects the contents of this span. // mu protects the contents of this span.
mu sync.Mutex mu sync.Mutex
@ -292,17 +288,19 @@ func (s *span) addEvent(name string, o ...trace.EventOption) {
c := trace.NewEventConfig(o...) c := trace.NewEventConfig(o...)
// Discard over limited attributes // Discard over limited attributes
var discarded int
if len(c.Attributes) > s.spanLimits.AttributePerEventCountLimit { if len(c.Attributes) > s.spanLimits.AttributePerEventCountLimit {
s.addDroppedAttributeCount(len(c.Attributes) - s.spanLimits.AttributePerEventCountLimit) discarded = len(c.Attributes) - s.spanLimits.AttributePerEventCountLimit
c.Attributes = c.Attributes[:s.spanLimits.AttributePerEventCountLimit] c.Attributes = c.Attributes[:s.spanLimits.AttributePerEventCountLimit]
} }
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.messageEvents.add(trace.Event{ s.messageEvents.add(trace.Event{
Name: name, Name: name,
Attributes: c.Attributes, Attributes: c.Attributes,
Time: c.Timestamp, DroppedAttributeCount: discarded,
Time: c.Timestamp,
}) })
} }
@ -423,7 +421,7 @@ func (s *span) addLink(link trace.Link) {
// Discard over limited attributes // Discard over limited attributes
if len(link.Attributes) > s.spanLimits.AttributePerLinkCountLimit { if len(link.Attributes) > s.spanLimits.AttributePerLinkCountLimit {
s.addDroppedAttributeCount(len(link.Attributes) - s.spanLimits.AttributePerLinkCountLimit) link.DroppedAttributeCount = len(link.Attributes) - s.spanLimits.AttributePerLinkCountLimit
link.Attributes = link.Attributes[:s.spanLimits.AttributePerLinkCountLimit] link.Attributes = link.Attributes[:s.spanLimits.AttributePerLinkCountLimit]
} }
@ -449,10 +447,9 @@ func (s *span) Snapshot() *export.SpanSnapshot {
sd.StatusCode = s.statusCode sd.StatusCode = s.statusCode
sd.StatusMessage = s.statusMessage sd.StatusMessage = s.statusMessage
sd.DroppedAttributeCount = int(s.droppedAttributeCount)
if s.attributes.evictList.Len() > 0 { if s.attributes.evictList.Len() > 0 {
sd.Attributes = s.attributes.toKeyValue() sd.Attributes = s.attributes.toKeyValue()
sd.DroppedAttributeCount += s.attributes.droppedCount sd.DroppedAttributeCount = s.attributes.droppedCount
} }
if len(s.messageEvents.queue) > 0 { if len(s.messageEvents.queue) > 0 {
sd.MessageEvents = s.interfaceArrayToMessageEventArray() sd.MessageEvents = s.interfaceArrayToMessageEventArray()
@ -502,10 +499,6 @@ func (s *span) addChild() {
s.mu.Unlock() s.mu.Unlock()
} }
func (s *span) addDroppedAttributeCount(delta int) {
atomic.AddInt64(&s.droppedAttributeCount, int64(delta))
}
func (*span) private() {} func (*span) private() {}
func startSpanInternal(ctx context.Context, tr *tracer, name string, o *trace.SpanConfig) *span { func startSpanInternal(ctx context.Context, tr *tracer, name string, o *trace.SpanConfig) *span {

View File

@ -1491,10 +1491,10 @@ func TestAddEventsWithMoreAttributesThanLimit(t *testing.T) {
attribute.Bool("key1", true), attribute.Bool("key1", true),
attribute.String("key2", "value2"), attribute.String("key2", "value2"),
}, },
DroppedAttributeCount: 2,
}, },
}, },
SpanKind: trace.SpanKindInternal, SpanKind: trace.SpanKindInternal,
DroppedAttributeCount: 2,
InstrumentationLibrary: instrumentation.Library{Name: "AddSpanEventWithOverLimitedAttributes"}, InstrumentationLibrary: instrumentation.Library{Name: "AddSpanEventWithOverLimitedAttributes"},
} }
if diff := cmpDiff(got, want); diff != "" { if diff := cmpDiff(got, want); diff != "" {
@ -1536,10 +1536,17 @@ func TestAddLinksWithMoreAttributesThanLimit(t *testing.T) {
Parent: sc.WithRemote(true), Parent: sc.WithRemote(true),
Name: "span0", Name: "span0",
Links: []trace.Link{ Links: []trace.Link{
{SpanContext: sc1, Attributes: []attribute.KeyValue{k1v1}}, {
{SpanContext: sc2, Attributes: []attribute.KeyValue{k2v2}}, SpanContext: sc1,
Attributes: []attribute.KeyValue{k1v1},
DroppedAttributeCount: 1,
},
{
SpanContext: sc2,
Attributes: []attribute.KeyValue{k2v2},
DroppedAttributeCount: 2,
},
}, },
DroppedAttributeCount: 3,
SpanKind: trace.SpanKindInternal, SpanKind: trace.SpanKindInternal,
InstrumentationLibrary: instrumentation.Library{Name: "Links"}, InstrumentationLibrary: instrumentation.Library{Name: "Links"},
} }

View File

@ -547,6 +547,10 @@ type Event struct {
// Attributes describe the aspects of the event. // Attributes describe the aspects of the event.
Attributes []attribute.KeyValue Attributes []attribute.KeyValue
// DroppedAttributeCount is the number of attributes that were not
// recorded due to configured limits being reached.
DroppedAttributeCount int
// Time at which this event was recorded. // Time at which this event was recorded.
Time time.Time Time time.Time
} }
@ -567,8 +571,15 @@ type Event struct {
// form. A Link is used to keep reference to the original SpanContext and // form. A Link is used to keep reference to the original SpanContext and
// track the relationship. // track the relationship.
type Link struct { type Link struct {
// SpanContext of the linked Span.
SpanContext SpanContext
// Attributes describe the aspects of the link.
Attributes []attribute.KeyValue Attributes []attribute.KeyValue
// DroppedAttributeCount is the number of attributes that were not
// recorded due to configured limits being reached.
DroppedAttributeCount int
} }
// SpanKind is the role a Span plays in a Trace. // SpanKind is the role a Span plays in a Trace.