refactor aws lambda span (#3541)

* refactor: migrate http_attributes from SpanAttributes to new semantic conventions and refactor tests

* fix precommit linting

* refactor aws lambda to use new semantics

* refactor tests

* update resourceattributes to cloud attrs

* update main for attrs
This commit is contained in:
wesley
2025-05-27 13:30:47 -07:00
committed by GitHub
parent a164d37a3c
commit 75c73d1e29
2 changed files with 77 additions and 49 deletions

View File

@ -86,8 +86,25 @@ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.instrumentation.utils import unwrap
from opentelemetry.metrics import MeterProvider, get_meter_provider
from opentelemetry.propagate import get_global_textmap
from opentelemetry.semconv.resource import ResourceAttributes
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.semconv._incubating.attributes.cloud_attributes import (
CLOUD_ACCOUNT_ID,
CLOUD_RESOURCE_ID,
)
from opentelemetry.semconv._incubating.attributes.faas_attributes import (
FAAS_INVOCATION_ID,
FAAS_TRIGGER,
)
from opentelemetry.semconv._incubating.attributes.http_attributes import (
HTTP_METHOD,
HTTP_ROUTE,
HTTP_SCHEME,
HTTP_STATUS_CODE,
HTTP_TARGET,
HTTP_USER_AGENT,
)
from opentelemetry.semconv._incubating.attributes.net_attributes import (
NET_HOST_NAME,
)
from opentelemetry.trace import (
Span,
SpanKind,
@ -171,38 +188,34 @@ def _set_api_gateway_v1_proxy_attributes(
More info:
https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
"""
span.set_attribute(
SpanAttributes.HTTP_METHOD, lambda_event.get("httpMethod")
)
span.set_attribute(HTTP_METHOD, lambda_event.get("httpMethod"))
if lambda_event.get("headers"):
if "User-Agent" in lambda_event["headers"]:
span.set_attribute(
SpanAttributes.HTTP_USER_AGENT,
HTTP_USER_AGENT,
lambda_event["headers"]["User-Agent"],
)
if "X-Forwarded-Proto" in lambda_event["headers"]:
span.set_attribute(
SpanAttributes.HTTP_SCHEME,
HTTP_SCHEME,
lambda_event["headers"]["X-Forwarded-Proto"],
)
if "Host" in lambda_event["headers"]:
span.set_attribute(
SpanAttributes.NET_HOST_NAME,
NET_HOST_NAME,
lambda_event["headers"]["Host"],
)
if "resource" in lambda_event:
span.set_attribute(SpanAttributes.HTTP_ROUTE, lambda_event["resource"])
span.set_attribute(HTTP_ROUTE, lambda_event["resource"])
if lambda_event.get("queryStringParameters"):
span.set_attribute(
SpanAttributes.HTTP_TARGET,
HTTP_TARGET,
f"{lambda_event['resource']}?{urlencode(lambda_event['queryStringParameters'])}",
)
else:
span.set_attribute(
SpanAttributes.HTTP_TARGET, lambda_event["resource"]
)
span.set_attribute(HTTP_TARGET, lambda_event["resource"])
return span
@ -217,34 +230,34 @@ def _set_api_gateway_v2_proxy_attributes(
"""
if "domainName" in lambda_event["requestContext"]:
span.set_attribute(
SpanAttributes.NET_HOST_NAME,
NET_HOST_NAME,
lambda_event["requestContext"]["domainName"],
)
if lambda_event["requestContext"].get("http"):
if "method" in lambda_event["requestContext"]["http"]:
span.set_attribute(
SpanAttributes.HTTP_METHOD,
HTTP_METHOD,
lambda_event["requestContext"]["http"]["method"],
)
if "userAgent" in lambda_event["requestContext"]["http"]:
span.set_attribute(
SpanAttributes.HTTP_USER_AGENT,
HTTP_USER_AGENT,
lambda_event["requestContext"]["http"]["userAgent"],
)
if "path" in lambda_event["requestContext"]["http"]:
span.set_attribute(
SpanAttributes.HTTP_ROUTE,
HTTP_ROUTE,
lambda_event["requestContext"]["http"]["path"],
)
if lambda_event.get("rawQueryString"):
span.set_attribute(
SpanAttributes.HTTP_TARGET,
HTTP_TARGET,
f"{lambda_event['requestContext']['http']['path']}?{lambda_event['rawQueryString']}",
)
else:
span.set_attribute(
SpanAttributes.HTTP_TARGET,
HTTP_TARGET,
lambda_event["requestContext"]["http"]["path"],
)
@ -319,11 +332,11 @@ def _instrument(
# See more:
# https://github.com/open-telemetry/semantic-conventions/blob/main/docs/faas/aws-lambda.md#resource-detector
span.set_attribute(
SpanAttributes.CLOUD_RESOURCE_ID,
CLOUD_RESOURCE_ID,
lambda_context.invoked_function_arn,
)
span.set_attribute(
SpanAttributes.FAAS_INVOCATION_ID,
FAAS_INVOCATION_ID,
lambda_context.aws_request_id,
)
@ -335,7 +348,7 @@ def _instrument(
":"
)[4]
span.set_attribute(
ResourceAttributes.CLOUD_ACCOUNT_ID,
CLOUD_ACCOUNT_ID,
account_id,
)
@ -354,7 +367,7 @@ def _instrument(
if isinstance(lambda_event, dict) and lambda_event.get(
"requestContext"
):
span.set_attribute(SpanAttributes.FAAS_TRIGGER, "http")
span.set_attribute(FAAS_TRIGGER, "http")
if lambda_event.get("version") == "2.0":
_set_api_gateway_v2_proxy_attributes(
@ -367,7 +380,7 @@ def _instrument(
if isinstance(result, dict) and result.get("statusCode"):
span.set_attribute(
SpanAttributes.HTTP_STATUS_CODE,
HTTP_STATUS_CODE,
result.get("statusCode"),
)
finally:

View File

@ -33,8 +33,25 @@ from opentelemetry.propagators.aws.aws_xray_propagator import (
TRACE_ID_FIRST_PART_LENGTH,
TRACE_ID_VERSION,
)
from opentelemetry.semconv.resource import ResourceAttributes
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.semconv._incubating.attributes.cloud_attributes import (
CLOUD_ACCOUNT_ID,
CLOUD_RESOURCE_ID,
)
from opentelemetry.semconv._incubating.attributes.faas_attributes import (
FAAS_INVOCATION_ID,
FAAS_TRIGGER,
)
from opentelemetry.semconv._incubating.attributes.http_attributes import (
HTTP_METHOD,
HTTP_ROUTE,
HTTP_SCHEME,
HTTP_STATUS_CODE,
HTTP_TARGET,
HTTP_USER_AGENT,
)
from opentelemetry.semconv._incubating.attributes.net_attributes import (
NET_HOST_NAME,
)
from opentelemetry.test.test_base import TestBase
from opentelemetry.trace import NoOpTracerProvider, SpanKind, StatusCode
from opentelemetry.trace.propagation.tracecontext import (
@ -68,11 +85,9 @@ MOCK_LAMBDA_CONTEXT = MockLambdaContext(
)
MOCK_LAMBDA_CONTEXT_ATTRIBUTES = {
SpanAttributes.CLOUD_RESOURCE_ID: MOCK_LAMBDA_CONTEXT.invoked_function_arn,
SpanAttributes.FAAS_INVOCATION_ID: MOCK_LAMBDA_CONTEXT.aws_request_id,
ResourceAttributes.CLOUD_ACCOUNT_ID: MOCK_LAMBDA_CONTEXT.invoked_function_arn.split(
":"
)[4],
CLOUD_RESOURCE_ID: MOCK_LAMBDA_CONTEXT.invoked_function_arn,
FAAS_INVOCATION_ID: MOCK_LAMBDA_CONTEXT.aws_request_id,
CLOUD_ACCOUNT_ID: MOCK_LAMBDA_CONTEXT.invoked_function_arn.split(":")[4],
}
MOCK_XRAY_TRACE_ID = 0x5FB7331105E8BB83207FA31D4D9CDB4C
@ -571,14 +586,14 @@ class TestAwsLambdaInstrumentorMocks(TestAwsLambdaInstrumentorBase):
self.assertSpanHasAttributes(
span,
{
SpanAttributes.FAAS_TRIGGER: "http",
SpanAttributes.HTTP_METHOD: "POST",
SpanAttributes.HTTP_ROUTE: "/{proxy+}",
SpanAttributes.HTTP_TARGET: "/{proxy+}?foo=bar",
SpanAttributes.NET_HOST_NAME: "1234567890.execute-api.us-east-1.amazonaws.com",
SpanAttributes.HTTP_USER_AGENT: "Custom User Agent String",
SpanAttributes.HTTP_SCHEME: "https",
SpanAttributes.HTTP_STATUS_CODE: 200,
FAAS_TRIGGER: "http",
HTTP_METHOD: "POST",
HTTP_ROUTE: "/{proxy+}",
HTTP_TARGET: "/{proxy+}?foo=bar",
NET_HOST_NAME: "1234567890.execute-api.us-east-1.amazonaws.com",
HTTP_USER_AGENT: "Custom User Agent String",
HTTP_SCHEME: "https",
HTTP_STATUS_CODE: 200,
},
)
@ -599,12 +614,12 @@ class TestAwsLambdaInstrumentorMocks(TestAwsLambdaInstrumentorBase):
self.assertSpanHasAttributes(
span,
{
SpanAttributes.FAAS_TRIGGER: "http",
SpanAttributes.HTTP_METHOD: "POST",
SpanAttributes.HTTP_ROUTE: "/path/to/resource",
SpanAttributes.HTTP_TARGET: "/path/to/resource?parameter1=value1&parameter1=value2&parameter2=value",
SpanAttributes.NET_HOST_NAME: "id.execute-api.us-east-1.amazonaws.com",
SpanAttributes.HTTP_USER_AGENT: "agent",
FAAS_TRIGGER: "http",
HTTP_METHOD: "POST",
HTTP_ROUTE: "/path/to/resource",
HTTP_TARGET: "/path/to/resource?parameter1=value1&parameter1=value2&parameter2=value",
NET_HOST_NAME: "id.execute-api.us-east-1.amazonaws.com",
HTTP_USER_AGENT: "agent",
},
)
@ -625,8 +640,8 @@ class TestAwsLambdaInstrumentorMocks(TestAwsLambdaInstrumentorBase):
self.assertSpanHasAttributes(
span,
{
SpanAttributes.FAAS_TRIGGER: "http",
SpanAttributes.HTTP_METHOD: "GET",
FAAS_TRIGGER: "http",
HTTP_METHOD: "GET",
},
)
@ -647,8 +662,8 @@ class TestAwsLambdaInstrumentorMocks(TestAwsLambdaInstrumentorBase):
self.assertSpanHasAttributes(
span,
{
SpanAttributes.FAAS_TRIGGER: "http",
SpanAttributes.HTTP_METHOD: "GET",
FAAS_TRIGGER: "http",
HTTP_METHOD: "GET",
},
)