diff --git a/input/otlp/traces.go b/input/otlp/traces.go index 3bc26a7f..1e7c574e 100644 --- a/input/otlp/traces.go +++ b/input/otlp/traces.go @@ -71,8 +71,12 @@ const ( attributeNetworkMNC = "net.host.carrier.mnc" attributeNetworkCarrierName = "net.host.carrier.name" attributeNetworkICC = "net.host.carrier.icc" - - attributeUrlFull = "url.full" + attributeHttpRequestMethod = "http.request.method" + attributeHttpResponseStatusCode = "http.response.status_code" + attributeServerAddress = "server.address" + attributeServerPort = "server.port" + attributeUrlFull = "url.full" + attributeUserAgentOriginal = "user_agent.original" ) // ConsumeTraces consumes OpenTelemetry trace data, @@ -260,11 +264,11 @@ func TranslateTransaction( setLabel(k, event, ifaceAttributeValue(v)) case pcommon.ValueTypeInt: switch kDots { - case semconv.AttributeHTTPStatusCode: + case semconv.AttributeHTTPStatusCode, attributeHttpResponseStatusCode: isHTTP = true httpResponse.StatusCode = uint32(v.Int()) http.Response = &httpResponse - case semconv.AttributeNetPeerPort: + case semconv.AttributeNetPeerPort, attributeServerPort: event.Source = populateNil(event.Source) event.Source.Port = uint32(v.Int()) case semconv.AttributeNetHostPort: @@ -280,11 +284,11 @@ func TranslateTransaction( stringval := truncate(v.Str()) switch kDots { // http.* - case semconv.AttributeHTTPMethod: + case semconv.AttributeHTTPMethod, attributeHttpRequestMethod: isHTTP = true httpRequest.Method = stringval http.Request = &httpRequest - case semconv.AttributeHTTPURL, semconv.AttributeHTTPTarget, "http.path": + case semconv.AttributeHTTPURL, semconv.AttributeHTTPTarget, "http.path", attributeUrlFull: isHTTP = true httpURL = stringval case semconv.AttributeHTTPHost: @@ -293,7 +297,7 @@ func TranslateTransaction( case semconv.AttributeHTTPScheme: isHTTP = true httpScheme = stringval - case semconv.AttributeHTTPStatusCode: + case semconv.AttributeHTTPStatusCode, attributeHttpResponseStatusCode: if intv, err := strconv.Atoi(stringval); err == nil { isHTTP = true httpResponse.StatusCode = uint32(intv) @@ -318,7 +322,7 @@ func TranslateTransaction( event.Client = populateNil(event.Client) event.Client.Ip = ip } - case semconv.AttributeHTTPUserAgent: + case semconv.AttributeHTTPUserAgent, attributeUserAgentOriginal: event.UserAgent = populateNil(event.UserAgent) event.UserAgent.Original = stringval @@ -328,7 +332,7 @@ func TranslateTransaction( if ip, err := modelpb.ParseIP(stringval); err == nil { event.Source.Ip = ip } - case semconv.AttributeNetPeerName: + case semconv.AttributeNetPeerName, attributeServerAddress: event.Source = populateNil(event.Source) event.Source.Domain = stringval case semconv.AttributeNetHostName: @@ -536,11 +540,11 @@ func TranslateSpan(spanKind ptrace.SpanKind, attributes pcommon.Map, event *mode setLabel(k, event, v.Double()) case pcommon.ValueTypeInt: switch kDots { - case "http.status_code": + case "http.status_code", attributeHttpResponseStatusCode: httpResponse.StatusCode = uint32(v.Int()) http.Response = &httpResponse isHTTP = true - case semconv.AttributeNetPeerPort, "peer.port": + case semconv.AttributeNetPeerPort, "peer.port", attributeServerPort: netPeerPort = int(v.Int()) case semconv.AttributeRPCGRPCStatusCode: rpcSystem = "grpc" @@ -565,7 +569,7 @@ func TranslateSpan(spanKind ptrace.SpanKind, attributes pcommon.Map, event *mode case semconv.AttributeHTTPURL: httpURL = stringval isHTTP = true - case semconv.AttributeHTTPMethod: + case semconv.AttributeHTTPMethod, attributeHttpRequestMethod: httpRequest.Method = stringval http.Request = &httpRequest isHTTP = true @@ -622,6 +626,10 @@ func TranslateSpan(spanKind ptrace.SpanKind, attributes pcommon.Map, event *mode event.Network.Carrier = populateNil(event.Network.Carrier) event.Network.Carrier.Icc = stringval + // server.* + case attributeServerAddress: + netPeerName = stringval + // session.* case "session.id": event.Session = populateNil(event.Session) diff --git a/input/otlp/traces_test.go b/input/otlp/traces_test.go index 6e0fdb9b..0ab6a6e0 100644 --- a/input/otlp/traces_test.go +++ b/input/otlp/traces_test.go @@ -246,6 +246,19 @@ func TestHTTPTransactionURL(t *testing.T) { "http.target": "/foo", }) }) + t.Run("url.full", func(t *testing.T) { + test(t, &modelpb.URL{ + Scheme: "https", + Original: "https://testing.invalid:80/foo?bar", + Full: "https://testing.invalid:80/foo?bar", + Path: "/foo", + Query: "bar", + Domain: "testing.invalid", + Port: 80, + }, map[string]interface{}{ + "url.full": "https://testing.invalid:80/foo?bar", + }) + }) } func TestHTTPSpanURL(t *testing.T) { @@ -416,10 +429,23 @@ func TestHTTPTransactionFlavor(t *testing.T) { } func TestHTTPTransactionUserAgent(t *testing.T) { - event := transformTransactionWithAttributes(t, map[string]interface{}{ - "http.user_agent": "Foo/bar (baz)", + test := func(t *testing.T, attrs map[string]interface{}) { + t.Helper() + event := transformTransactionWithAttributes(t, attrs) + assert.Equal(t, &modelpb.UserAgent{Original: "Foo/bar (baz)"}, event.UserAgent) + } + + t.Run("http.user_agent", func(t *testing.T) { + test(t, map[string]interface{}{ + "http.user_agent": "Foo/bar (baz)", + }) + }) + + t.Run("user_agent.original", func(t *testing.T) { + test(t, map[string]interface{}{ + "user_agent.original": "Foo/bar (baz)", + }) }) - assert.Equal(t, &modelpb.UserAgent{Original: "Foo/bar (baz)"}, event.UserAgent) } func TestHTTPTransactionClientIP(t *testing.T) { @@ -435,10 +461,23 @@ func TestHTTPTransactionClientIP(t *testing.T) { } func TestHTTPTransactionStatusCode(t *testing.T) { - event := transformTransactionWithAttributes(t, map[string]interface{}{ - "http.status_code": 200, + test := func(t *testing.T, expected uint32, attrs map[string]interface{}) { + t.Helper() + event := transformSpanWithAttributes(t, attrs) + assert.Equal(t, expected, event.Http.Response.StatusCode) + } + + t.Run("http.status_code", func(t *testing.T) { + test(t, 200, map[string]interface{}{ + "http.status_code": 200, + }) + }) + + t.Run("http.response.status_code", func(t *testing.T) { + test(t, 200, map[string]interface{}{ + "http.response.status_code": 200, + }) }) - assert.Equal(t, uint32(200), event.Http.Response.StatusCode) } func TestDatabaseSpan(t *testing.T) { @@ -485,6 +524,24 @@ func TestDatabaseSpan(t *testing.T) { }, event.Span.DestinationService, protocmp.Transform())) } +func TestDatabaseSpanWithServerAttributes(t *testing.T) { + event := transformSpanWithAttributes(t, map[string]interface{}{ + "db.system": "mysql", + "db.name": "ShopDb", + "server.address": "shopdb.example.com", + "server.port": 3306, + }) + + assert.Equal(t, "db", event.Span.Type) + assert.Equal(t, "mysql", event.Span.Subtype) + assert.Equal(t, "", event.Span.Action) + + assert.Equal(t, &modelpb.Destination{ + Address: "shopdb.example.com", + Port: 3306, + }, event.Destination) +} + func TestInstrumentationLibrary(t *testing.T) { traces, spans := newTracesSpans() spans.Scope().SetName("library-name")