From 0babeca0f4a5bf2dc4af47aad9d5b204236f1f58 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 29 Aug 2023 16:10:02 +0100 Subject: [PATCH 1/3] Collect additional new attributes and add tests --- input/otlp/traces.go | 35 ++++++++++++++------ input/otlp/traces_test.go | 69 +++++++++++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 16 deletions(-) diff --git a/input/otlp/traces.go b/input/otlp/traces.go index f034ba9a..3c6e6223 100644 --- a/input/otlp/traces.go +++ b/input/otlp/traces.go @@ -70,6 +70,12 @@ const ( attributeNetworkMNC = "net.host.carrier.mnc" attributeNetworkCarrierName = "net.host.carrier.name" attributeNetworkICC = "net.host.carrier.icc" + 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, @@ -257,11 +263,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: @@ -277,11 +283,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: @@ -290,7 +296,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) @@ -315,7 +321,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 @@ -325,7 +331,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: @@ -533,11 +539,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" @@ -562,7 +568,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 @@ -619,6 +625,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) @@ -651,6 +661,11 @@ func TranslateSpan(spanKind ptrace.SpanKind, attributes pcommon.Map, event *mode isRPC = true case semconv.AttributeRPCMethod: + // url.* + case attributeUrlFull: + httpURL = stringval + isHTTP = true + // miscellaneous case "span.kind": // filter out case semconv.AttributePeerService: diff --git a/input/otlp/traces_test.go b/input/otlp/traces_test.go index 555e6c4b..2adc64a1 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") From f03c53fb574ccc2370c13404b44de039e76a9e66 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Wed, 30 Aug 2023 14:39:07 +0100 Subject: [PATCH 2/3] PR feedback fixes --- input/otlp/traces.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/input/otlp/traces.go b/input/otlp/traces.go index 3c6e6223..9f72c037 100644 --- a/input/otlp/traces.go +++ b/input/otlp/traces.go @@ -267,7 +267,7 @@ func TranslateTransaction( isHTTP = true httpResponse.StatusCode = uint32(v.Int()) http.Response = &httpResponse - case semconv.AttributeNetPeerPort, attributeServerPort: + case semconv.AttributeNetPeerPort: event.Source = populateNil(event.Source) event.Source.Port = uint32(v.Int()) case semconv.AttributeNetHostPort: @@ -331,7 +331,7 @@ func TranslateTransaction( if ip, err := modelpb.ParseIP(stringval); err == nil { event.Source.Ip = ip } - case semconv.AttributeNetPeerName, attributeServerAddress: + case semconv.AttributeNetPeerName: event.Source = populateNil(event.Source) event.Source.Domain = stringval case semconv.AttributeNetHostName: From 155d58e26867e14cc44a121624dca7d566319fd7 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 12 Sep 2023 09:26:52 +0100 Subject: [PATCH 3/3] PR feedback --- input/otlp/traces.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/input/otlp/traces.go b/input/otlp/traces.go index 9f72c037..6a3e1a44 100644 --- a/input/otlp/traces.go +++ b/input/otlp/traces.go @@ -287,7 +287,7 @@ func TranslateTransaction( isHTTP = true httpRequest.Method = stringval http.Request = &httpRequest - case semconv.AttributeHTTPURL, semconv.AttributeHTTPTarget, "http.path", attributeUrlFull: + case semconv.AttributeHTTPURL, semconv.AttributeHTTPTarget, "http.path": isHTTP = true httpURL = stringval case semconv.AttributeHTTPHost: @@ -378,6 +378,11 @@ func TranslateTransaction( case semconv.AttributeRPCService: case semconv.AttributeRPCMethod: + // URL + case attributeUrlFull: + isHTTP = true + httpURL = stringval + // miscellaneous case "type": event.Transaction.Type = stringval