From eec094e9470dd3855eaf47b025d853bcbc13df68 Mon Sep 17 00:00:00 2001 From: Anton Ovchinnikov Date: Mon, 15 May 2023 13:05:47 +0200 Subject: [PATCH] fix(tracing): Make sure a valid source is set on a transaction event (#637) --- tracing.go | 32 ++++++++++++++++++++++++++++++-- tracing_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/tracing.go b/tracing.go index 519dc20ef..4c6747353 100644 --- a/tracing.go +++ b/tracing.go @@ -519,6 +519,12 @@ func (s *Span) toEvent() *Event { } contexts["trace"] = s.traceContext().Map() + // Make sure that the transaction source is valid + transactionSource := s.Source + if !transactionSource.isValid() { + transactionSource = SourceCustom + } + return &Event{ Type: transactionType, Transaction: s.Name, @@ -529,7 +535,7 @@ func (s *Span) toEvent() *Event { StartTime: s.StartTime, Spans: finished, TransactionInfo: &TransactionInfo{ - Source: s.Source, + Source: transactionSource, }, sdkMetaData: SDKMetaData{ dsc: s.dynamicSamplingContext, @@ -620,6 +626,24 @@ const ( SourceTask TransactionSource = "task" ) +// A set of all valid transaction sources. +var allTransactionSources = map[TransactionSource]struct{}{ + SourceCustom: {}, + SourceURL: {}, + SourceRoute: {}, + SourceView: {}, + SourceComponent: {}, + SourceTask: {}, +} + +// isValid returns 'true' if the given transaction source is a valid +// source as recognized by the envelope protocol: +// https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations +func (ts TransactionSource) isValid() bool { + _, found := allTransactionSources[ts] + return found +} + // SpanStatus is the status of a span. type SpanStatus uint8 @@ -788,7 +812,7 @@ type SpanOption func(s *Span) // starting a span affects the span tree as a whole, potentially overwriting a // name set previously. // -// Deprecated: Use WithTransactionSource() instead. +// Deprecated: Use WithTransactionName() instead. func TransactionName(name string) SpanOption { return WithTransactionName(name) } @@ -826,6 +850,10 @@ func TransctionSource(source TransactionSource) SpanOption { } // WithTransactionSource sets the source of the transaction name. +// +// Note: if the transaction source is not a valid source (as described +// by the spec https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations), +// it will be corrected to "custom" eventually, before the transaction is sent. func WithTransactionSource(source TransactionSource) SpanOption { return func(s *Span) { s.Source = source diff --git a/tracing_test.go b/tracing_test.go index 8a90e4e22..ca3762a1d 100644 --- a/tracing_test.go +++ b/tracing_test.go @@ -890,3 +890,49 @@ func TestDeprecatedSpanOptionSpanSampled(t *testing.T) { func TestDeprecatedSpanOptionTransctionSource(t *testing.T) { StartSpan(context.Background(), "op", TransctionSource("src")) } + +func TestAdjustingTransactionSourceBeforeSending(t *testing.T) { + tests := []struct { + name string + inputTransactionSource TransactionSource + wantTransactionSource TransactionSource + }{ + { + name: "Invalid transaction source", + inputTransactionSource: "invalidSource", + wantTransactionSource: "custom", + }, + { + name: "Valid transaction source", + inputTransactionSource: SourceTask, + wantTransactionSource: "task", + }, + { + name: "Empty transaction source", + inputTransactionSource: "", + wantTransactionSource: "custom", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + transport := &TransportMock{} + ctx := NewTestContext(ClientOptions{ + EnableTracing: true, + TracesSampleRate: 1.0, + Transport: transport, + }) + transaction := StartTransaction( + ctx, + "Test Transaction", + WithTransactionSource(tt.inputTransactionSource), + ) + transaction.Finish() + + event := transport.Events()[0] + + assertEqual(t, event.TransactionInfo.Source, tt.wantTransactionSource) + }) + } +}