Skip to content

feat: extract HTTP semconv attributes for API Gateway-triggered invocations - #86

Open
RaphaelManke wants to merge 6 commits into
masterfrom
RaphaelManke/Nodejs-http-attributes
Open

feat: extract HTTP semconv attributes for API Gateway-triggered invocations#86
RaphaelManke wants to merge 6 commits into
masterfrom
RaphaelManke/Nodejs-http-attributes

Conversation

@RaphaelManke

Copy link
Copy Markdown
Contributor

Summary

Adds HTTP semantic-convention attributes to the handler span for API Gateway REST API (v1) and HTTP API (v2) proxy integration invocations, addressing open-telemetry/opentelemetry-js-contrib#999 at the extension layer instead of the upstream instrumentation-aws-lambda package.

  • The extension already buffers the raw invoke event and return payload for every invocation (extension::runtime_proxy), so extraction runs independently of the in-function OpenTelemetry SDK — it works for every supported Lambda runtime (Node.js, Python, Java, .NET, Go), and even when auto-instrumentation is disabled and the extension builds a synthetic trace itself.
  • Request attributes (http.request.method, url.path, url.scheme, http.route, server.address/server.port, client.address, network.protocol.version) and http.response.status_code are captured unconditionally — none carry PII.
  • Span renaming to <method> <route>, request/response header capture, and query-string capture are opt-in via new DASH0_* env vars, off by default so nothing changes for existing users.

Test plan

  • cargo test — 302 tests pass, including new unit tests in src/otlp/http_attributes.rs and a full request→response round-trip integration test in src/extension/runtime_proxy.rs that drives the real route::dispatch handler against a mock sandbox Runtime API.
  • cargo clippy --all-targets — no new warnings.
  • Extended the deployed e2e suite (integration-tests/tests/src/test-tracing-scenarios-general.test.ts) to assert the new attributes on the existing apigateway/httpapi scenarios — needs a real CI run against deployed infra to confirm.
  • README updated with a new "API Gateway" section and the four new env vars documented.

Comment thread README.md
| `http.request.method` | string | The HTTP method. API Gateway-triggered invocations only. |
| `url.path` | string | The request path. API Gateway-triggered invocations only. |
| `url.scheme` | string | Always `https`. API Gateway-triggered invocations only. |
| `http.route` | string | The matched route template, with path parameters normalized (`{id}` -> `:id`). API Gateway-triggered invocations only. |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK there is no mandated format to express parameters in http.route, so I am not sure we need the normalization

…ations

Detects API Gateway REST API (v1) and HTTP API (v2) proxy integration
events directly from the raw invoke event and return payload the
extension already captures, independent of the in-function OpenTelemetry
SDK. Adds http.request.method, url.path, url.scheme, http.route,
server.address/port, client.address, network.protocol.version, and
http.response.status_code to the handler span for every supported
runtime, including when auto-instrumentation is disabled.

Response attributes are gated on the invocation's request actually
being an API Gateway event, not merely on the return value having a
statusCode field, since other trigger types can happen to return one
too (e.g. the integration test SQS/EventBridge consumers).

Span renaming to "<method> <route>", request/response header capture,
and query string capture are opt-in via new DASH0_* env vars, since
none of the existing users' span names or PII exposure should change
by default.

Closes open-telemetry/opentelemetry-js-contrib#999 at the extension
layer instead of the upstream instrumentation-aws-lambda package, since
the extension already parses both payloads for every Lambda runtime.
Tags each scenario/runtime's trace lookup with its producerTraceId so
a failure (like the httpapi resourceSpans-not-found case) can be
looked up directly in the backend instead of correlating interleaved
concurrent test logs.
Drives a real HTTP API v2 invocation through the extension's own
runtime-API proxy (no AWS deploy needed) and asserts the stored event
payload is masked while the exported span's http.route attribute and
name are not. Also moves the shared mock sandbox onto a dedicated OS
thread so it survives across per-test tokio runtimes, fixing a hang
that surfaced when two round-trip tests shared it.
CI confirmed the routeKey masking fix delivers the real, unmasked
route for both apigateway and httpapi consumer spans, so the earlier
toBeDefined() relaxation is no longer needed.
invocation_entry::get_api_gateway_request_data(invocation_id);
attributes.extend(api_gateway_attributes);
if let Some(name) = api_gateway_span_name {
span_name = name;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we sure we want to change the span name here? we decided that the handler span should be easily distinguishable from the name.

Comment thread README.md

### API Gateway

When a Lambda is invoked through API Gateway, the extension recognizes both integration styles and adds HTTP semantic-convention attributes to the handler span:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm guessing this also works for lambda urls. if so, let's document it. if not, it might be worthwhile to add.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants