diff --git a/enrichments/trace/config/config.go b/enrichments/trace/config/config.go index f28a99d..6bb50f1 100644 --- a/enrichments/trace/config/config.go +++ b/enrichments/trace/config/config.go @@ -40,6 +40,7 @@ type ScopeConfig struct { // ElasticTransactionConfig configures the enrichment attributes for the // spans which are identified as elastic transaction. type ElasticTransactionConfig struct { + TimestampUs AttributeConfig `mapstructure:"timestamp_us"` ID AttributeConfig `mapstructure:"id"` Root AttributeConfig `mapstructure:"root"` Name AttributeConfig `mapstructure:"name"` @@ -54,6 +55,7 @@ type ElasticTransactionConfig struct { // ElasticSpanConfig configures the enrichment attributes for the spans // which are NOT identified as elastic transaction. type ElasticSpanConfig struct { + TimestampUs AttributeConfig `mapstructure:"timestamp_us"` Name AttributeConfig `mapstructure:"name"` ProcessorEvent AttributeConfig `mapstructure:"processor_event"` RepresentativeCount AttributeConfig `mapstructure:"representative_count"` @@ -81,6 +83,7 @@ func Enabled() Config { ServiceFrameworkVersion: AttributeConfig{Enabled: true}, }, Transaction: ElasticTransactionConfig{ + TimestampUs: AttributeConfig{Enabled: true}, ID: AttributeConfig{Enabled: true}, Root: AttributeConfig{Enabled: true}, Name: AttributeConfig{Enabled: true}, @@ -92,6 +95,7 @@ func Enabled() Config { RepresentativeCount: AttributeConfig{Enabled: true}, }, Span: ElasticSpanConfig{ + TimestampUs: AttributeConfig{Enabled: true}, Name: AttributeConfig{Enabled: true}, ProcessorEvent: AttributeConfig{Enabled: true}, TypeSubtype: AttributeConfig{Enabled: true}, diff --git a/enrichments/trace/internal/elastic/attributes.go b/enrichments/trace/internal/elastic/attributes.go index c8be4f2..778bf48 100644 --- a/enrichments/trace/internal/elastic/attributes.go +++ b/enrichments/trace/internal/elastic/attributes.go @@ -27,6 +27,7 @@ const ( AttributeServiceFrameworkVersion = "service.framework.version" // span attributes + AttributeTimestampUs = "timestamp.us" AttributeProcessorEvent = "processor.event" AttributeTransactionID = "transaction.id" AttributeTransactionRoot = "transaction.root" diff --git a/enrichments/trace/internal/elastic/span.go b/enrichments/trace/internal/elastic/span.go index 708f191..fee81c8 100644 --- a/enrichments/trace/internal/elastic/span.go +++ b/enrichments/trace/internal/elastic/span.go @@ -163,6 +163,9 @@ func (s *spanEnrichmentContext) enrichTransaction( span ptrace.Span, cfg config.ElasticTransactionConfig, ) { + if cfg.TimestampUs.Enabled { + s.setTimestampUs(span) + } if cfg.ID.Enabled { span.Attributes().PutStr(AttributeTransactionID, span.SpanID().String()) } @@ -197,6 +200,9 @@ func (s *spanEnrichmentContext) enrichSpan( span ptrace.Span, cfg config.ElasticSpanConfig, ) { + if cfg.TimestampUs.Enabled { + s.setTimestampUs(span) + } if cfg.Name.Enabled { span.Attributes().PutStr(AttributeSpanName, span.Name()) } @@ -232,6 +238,26 @@ func (s *spanEnrichmentContext) normalizeAttributes() { } } +// setTimestampUs sets the attribute timestamp.us for span and +// span events. This is a temporary function to enable higher +// resolution timestamps in Elasticsearch. For more details see: +// https://github.com/elastic/opentelemetry-dev/issues/374. +// +// TODO (lahsivjar): If more enrichments need to be added +// for span events then consider having a separate flow for span +// events enrichment with its own configuration. +func (s *spanEnrichmentContext) setTimestampUs(span ptrace.Span) { + startTsUs := int64(span.StartTimestamp()) / 1000 + span.Attributes().PutInt(AttributeTimestampUs, startTsUs) + + events := span.Events() + for i := 0; i < events.Len(); i++ { + event := events.At(i) + eventTsUs := int64(event.Timestamp()) / 1000 + event.Attributes().PutInt(AttributeTimestampUs, eventTsUs) + } +} + func (s *spanEnrichmentContext) setTxnType(span ptrace.Span) { txnType := "unknown" switch { diff --git a/enrichments/trace/internal/elastic/span_test.go b/enrichments/trace/internal/elastic/span_test.go index 15b0796..68f0a6f 100644 --- a/enrichments/trace/internal/elastic/span_test.go +++ b/enrichments/trace/internal/elastic/span_test.go @@ -57,6 +57,7 @@ func TestElasticTransactionEnrich(t *testing.T) { input: ptrace.NewSpan(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: int64(0), AttributeTransactionRoot: true, AttributeTransactionID: "", AttributeTransactionName: "", @@ -83,6 +84,7 @@ func TestElasticTransactionEnrich(t *testing.T) { }(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: int64(0), AttributeTransactionRoot: true, AttributeTransactionID: "", AttributeTransactionName: "", @@ -105,6 +107,7 @@ func TestElasticTransactionEnrich(t *testing.T) { }(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeTransactionRoot: true, AttributeTransactionID: "0100000000000000", AttributeTransactionName: "testtxn", @@ -133,6 +136,7 @@ func TestElasticTransactionEnrich(t *testing.T) { }(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeTransactionRoot: true, AttributeTransactionID: "0100000000000000", AttributeTransactionName: "testtxn", @@ -160,6 +164,7 @@ func TestElasticTransactionEnrich(t *testing.T) { }(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeTransactionRoot: true, AttributeTransactionID: "0100000000000000", AttributeTransactionName: "testtxn", @@ -188,6 +193,7 @@ func TestElasticTransactionEnrich(t *testing.T) { }(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeTransactionRoot: true, AttributeTransactionID: "0100000000000000", AttributeTransactionName: "testtxn", @@ -216,6 +222,7 @@ func TestElasticTransactionEnrich(t *testing.T) { }(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeTransactionRoot: true, AttributeTransactionID: "0100000000000000", AttributeTransactionName: "testtxn", @@ -239,6 +246,7 @@ func TestElasticTransactionEnrich(t *testing.T) { }(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeTransactionRoot: true, AttributeTransactionID: "0100000000000000", AttributeTransactionName: "testtxn", @@ -262,6 +270,7 @@ func TestElasticTransactionEnrich(t *testing.T) { }(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeTransactionRoot: true, AttributeTransactionID: "0100000000000000", AttributeTransactionName: "testtxn", @@ -285,6 +294,7 @@ func TestElasticTransactionEnrich(t *testing.T) { }(), config: config.Enabled().Transaction, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeTransactionRoot: true, AttributeTransactionID: "0100000000000000", AttributeTransactionName: "testtxn", @@ -344,6 +354,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: int64(0), AttributeSpanName: "", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -368,6 +379,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: int64(0), AttributeSpanName: "", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -388,6 +400,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -414,6 +427,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -447,6 +461,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -478,6 +493,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -505,6 +521,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -529,6 +546,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -555,6 +573,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -578,6 +597,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -602,6 +622,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -626,6 +647,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -656,6 +678,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1), @@ -692,6 +715,7 @@ func TestElasticSpanEnrich(t *testing.T) { }(), config: config.Enabled().Span, enrichedAttrs: map[string]any{ + AttributeTimestampUs: startTs.AsTime().UnixMicro(), AttributeSpanName: "testspan", AttributeProcessorEvent: "span", AttributeSpanRepresentativeCount: float64(1),