Skip to content

Commit

Permalink
handling http semantic convention breaking changes in v1.23.0 (#31120)
Browse files Browse the repository at this point in the history
**Description:** <Describe what has changed.>
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->

`awsxrayexporter` is able to handle both old and new versions of http
span attributes, support translate new http attributes to xray segment
fields by following http [server
span](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-server)
and [client
span](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-client)
spec.

**Link to tracking Issue:** <Issue number if applicable>

#30935

**Testing:** <Describe what testing was performed and which tests were
added.>

**Documentation:** <Describe the documentation added.>
https://opentelemetry.io/blog/2023/http-conventions-declared-stable/

---------

Co-authored-by: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
  • Loading branch information
wangzlei and TylerHelmuth authored Feb 27, 2024
1 parent 414cfa1 commit fe35716
Show file tree
Hide file tree
Showing 3 changed files with 334 additions and 13 deletions.
27 changes: 27 additions & 0 deletions .chloggen/aws-xray-exporter-http-semconv-stable.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: awsxrayexporter

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: support both deprecated and stable http attributes translation for backward compatibility.

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [30935]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
80 changes: 67 additions & 13 deletions exporter/awsxrayexporter/internal/translator/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package translator // import "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsxrayexporter/internal/translator"

import (
"net"
"strconv"

"github.com/aws/aws-sdk-go/aws"
Expand All @@ -14,6 +15,19 @@ import (
awsxray "github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/xray"
)

const (
AttributeHTTPRequestMethod = "http.request.method"
AttributeHTTPResponseStatusCode = "http.response.status_code"
AttributeServerAddress = "server.address"
AttributeServerPort = "server.port"
AttributeNetworkPeerAddress = "network.peer.address"
AttributeClientAddress = "client.address"
AttributeURLScheme = "url.scheme"
AttributeURLFull = "url.full"
AttributeURLPath = "url.path"
AttributeUserAgentOriginal = "user_agent.original"
)

func makeHTTP(span ptrace.Span) (map[string]pcommon.Value, *awsxray.HTTPData) {
var (
info = awsxray.HTTPData{
Expand All @@ -30,28 +44,28 @@ func makeHTTP(span ptrace.Span) (map[string]pcommon.Value, *awsxray.HTTPData) {

hasHTTP := false
hasHTTPRequestURLAttributes := false
hasNetPeerAddr := false

span.Attributes().Range(func(key string, value pcommon.Value) bool {
switch key {
case conventions.AttributeHTTPMethod:
case conventions.AttributeHTTPMethod, AttributeHTTPRequestMethod:
info.Request.Method = awsxray.String(value.Str())
hasHTTP = true
case conventions.AttributeHTTPClientIP:
info.Request.ClientIP = awsxray.String(value.Str())
info.Request.XForwardedFor = aws.Bool(true)
hasHTTP = true
case conventions.AttributeHTTPUserAgent:
case conventions.AttributeHTTPUserAgent, AttributeUserAgentOriginal:
info.Request.UserAgent = awsxray.String(value.Str())
hasHTTP = true
case conventions.AttributeHTTPStatusCode:
case conventions.AttributeHTTPStatusCode, AttributeHTTPResponseStatusCode:
info.Response.Status = aws.Int64(value.Int())
hasHTTP = true
case conventions.AttributeHTTPURL:
urlParts[key] = value.Str()
case conventions.AttributeHTTPURL, AttributeURLFull:
urlParts[conventions.AttributeHTTPURL] = value.Str()
hasHTTP = true
hasHTTPRequestURLAttributes = true
case conventions.AttributeHTTPScheme:
urlParts[key] = value.Str()
case conventions.AttributeHTTPScheme, AttributeURLScheme:
urlParts[conventions.AttributeHTTPScheme] = value.Str()
hasHTTP = true
case conventions.AttributeHTTPHost:
urlParts[key] = value.Str()
Expand Down Expand Up @@ -90,12 +104,41 @@ func makeHTTP(span ptrace.Span) (map[string]pcommon.Value, *awsxray.HTTPData) {
}
urlParts[key] = value.Str()
hasHTTPRequestURLAttributes = true
hasNetPeerAddr = true
case AttributeNetworkPeerAddress:
// Prefer HTTP forwarded information (AttributeHTTPClientIP) when present.
if net.ParseIP(value.Str()) != nil {
if info.Request.ClientIP == nil {
info.Request.ClientIP = awsxray.String(value.Str())
}
hasHTTPRequestURLAttributes = true
hasNetPeerAddr = true
}
case AttributeClientAddress:
if net.ParseIP(value.Str()) != nil {
info.Request.ClientIP = awsxray.String(value.Str())
}
case AttributeURLPath:
urlParts[key] = value.Str()
hasHTTP = true
case AttributeServerAddress:
urlParts[key] = value.Str()
hasHTTPRequestURLAttributes = true
case AttributeServerPort:
urlParts[key] = value.Str()
if len(urlParts[key]) == 0 {
urlParts[key] = strconv.FormatInt(value.Int(), 10)
}
default:
filtered[key] = value
}
return true
})

if !hasNetPeerAddr && info.Request.ClientIP != nil {
info.Request.XForwardedFor = aws.Bool(true)
}

if !hasHTTP {
// Didn't have any HTTP-specific information so don't need to fill it in segment
return filtered, nil
Expand Down Expand Up @@ -142,7 +185,7 @@ func extractResponseSizeFromAttributes(attributes pcommon.Map) int64 {

func constructClientURL(urlParts map[string]string) string {
// follows OpenTelemetry specification-defined combinations for client spans described in
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-client
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-client

url, ok := urlParts[conventions.AttributeHTTPURL]
if ok {
Expand Down Expand Up @@ -181,7 +224,7 @@ func constructClientURL(urlParts map[string]string) string {

func constructServerURL(urlParts map[string]string) string {
// follows OpenTelemetry specification-defined combinations for server spans described in
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-server-semantic-conventions
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-server

url, ok := urlParts[conventions.AttributeHTTPURL]
if ok {
Expand All @@ -200,12 +243,18 @@ func constructServerURL(urlParts map[string]string) string {
if !ok {
host, ok = urlParts[conventions.AttributeNetHostName]
if !ok {
host = urlParts[conventions.AttributeHostName]
host, ok = urlParts[conventions.AttributeHostName]
if !ok {
host = urlParts[AttributeServerAddress]
}
}
}
port, ok = urlParts[conventions.AttributeNetHostPort]
if !ok {
port = ""
port, ok = urlParts[AttributeServerPort]
if !ok {
port = ""
}
}
}
url = scheme + "://" + host
Expand All @@ -216,7 +265,12 @@ func constructServerURL(urlParts map[string]string) string {
if ok {
url += target
} else {
url += "/"
path, ok := urlParts[AttributeURLPath]
if ok {
url += path
} else {
url += "/"
}
}
return url
}
Loading

0 comments on commit fe35716

Please sign in to comment.