From 64e886dbca1d5ae08ac23b6e7862942c4fc65859 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 17 Dec 2024 11:54:16 +0100 Subject: [PATCH 1/2] Add specific type and sybtypes for otlp gen_ai spans --- input/otlp/traces.go | 15 ++++++++++++++- input/otlp/traces_test.go | 10 ++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/input/otlp/traces.go b/input/otlp/traces.go index a56b8c87..5669c37d 100644 --- a/input/otlp/traces.go +++ b/input/otlp/traces.go @@ -615,6 +615,10 @@ func TranslateSpan(spanKind ptrace.SpanKind, attributes pcommon.Map, event *mode rpcService string ) + var ( + genAiSystem string + ) + var http modelpb.HTTP var httpRequest modelpb.HTTPRequest var httpResponse modelpb.HTTPResponse @@ -622,7 +626,7 @@ func TranslateSpan(spanKind ptrace.SpanKind, attributes pcommon.Map, event *mode var db modelpb.DB var destinationService modelpb.DestinationService var serviceTarget modelpb.ServiceTarget - var isHTTP, isDatabase, isRPC, isMessaging bool + var isHTTP, isDatabase, isRPC, isMessaging, isGenAi bool var samplerType, samplerParam pcommon.Value attributes.Range(func(kDots string, v pcommon.Value) bool { if isJaeger { @@ -812,6 +816,11 @@ func TranslateSpan(spanKind ptrace.SpanKind, attributes pcommon.Map, event *mode // stacktrace is expected to be large thus un-truncated value is needed event.Code.Stacktrace = v.Str() + // gen_ai.* + case "gen_ai.system": + genAiSystem = stringval + isGenAi = true + // miscellaneous case "span.kind": // filter out case semconv.AttributePeerService: @@ -991,6 +1000,10 @@ func TranslateSpan(spanKind ptrace.SpanKind, attributes pcommon.Map, event *mode destinationService.Resource = resource } } + case isGenAi: + event.Span.Type = "genai" + event.Span.Subtype = genAiSystem + serviceTarget.Type = event.Span.Type default: // Only set event.Span.Type if not already set if event.Span.Type == "" { diff --git a/input/otlp/traces_test.go b/input/otlp/traces_test.go index 4c6665b4..26a447c3 100644 --- a/input/otlp/traces_test.go +++ b/input/otlp/traces_test.go @@ -1438,6 +1438,16 @@ func TestSpanEventsDataStream(t *testing.T) { } } +func TestGenAiSpan(t *testing.T) { + event := transformSpanWithAttributes(t, map[string]interface{}{ + "gen_ai.system": "openai", + }) + + assert.Equal(t, "genai", event.Span.Type) + assert.Equal(t, "openai", event.Span.Subtype) + assert.Equal(t, "", event.Span.Action) +} + func transformTransactionWithAttributes(t *testing.T, attrs map[string]interface{}, configFns ...func(ptrace.Span)) *modelpb.APMEvent { traces, spans := newTracesSpans() otelSpan := spans.Spans().AppendEmpty() From d01e6fe35a0ba1bc63f3e4ec8ee0395fdc3e5110 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 17 Dec 2024 15:09:24 +0100 Subject: [PATCH 2/2] Use a constant for the semconv attribute --- input/otlp/traces.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/input/otlp/traces.go b/input/otlp/traces.go index 5669c37d..cbb2f522 100644 --- a/input/otlp/traces.go +++ b/input/otlp/traces.go @@ -82,6 +82,7 @@ const ( attributeStackTrace = "code.stacktrace" // semconv 1.24 or later attributeDataStreamDataset = "data_stream.dataset" attributeDataStreamNamespace = "data_stream.namespace" + attributeGenAiSystem = "gen_ai.system" ) // ConsumeTracesResult contains the number of rejected spans and error message for partial success response. @@ -817,7 +818,7 @@ func TranslateSpan(spanKind ptrace.SpanKind, attributes pcommon.Map, event *mode event.Code.Stacktrace = v.Str() // gen_ai.* - case "gen_ai.system": + case attributeGenAiSystem: genAiSystem = stringval isGenAi = true