Skip to content

fix: parent lazily imported module spans to the function span - #856

Merged
joeyzhao2018 merged 2 commits into
mainfrom
joey/apms-20524
Sep 24, 2026
Merged

joeyzhao2018 merged 2 commits into
mainfrom
joey/apms-20524

Conversation

@joeyzhao2018

@joeyzhao2018 joeyzhao2018 commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

https://datadoghq.atlassian.net/browse/APMS-20524

What does this PR do?

Parents aws.lambda.import spans for modules lazily imported during the invocation
to the function span, instead of to whatever span was active at import time.
Imports during init are unchanged (still children of aws.lambda.load).

Motivation

APMS-20524 / APMS-20380: peer.service=aws.lambda was being set on DynamoDB client
spans. The first botocore call in a handler lazily imports
ddtrace._trace.utils_botocore*, and those import spans were nested under the
active dynamodb.command client span with service:aws.lambda. The backend peer
service pipeline learns "client host → callee service" from exactly that shape, so
it mapped the DynamoDB host to aws.lambda. Reproduced locally with ddtrace 4.15.2
and a stubbed DynamoDB client.

The function span is a server span, so parenting to it gives the pipeline no client
span to learn from.

Why not change the service instead?

The extension (Go since 2021, Rust since v67) and the Forwarder already rewrite
aws.lambda downstream. Changing the service at the source either does nothing or,
on the Forwarder path, splits cold start spans from the function span. The bad edge
comes from the parenting.

What changes for customers

  • Lazily imported module spans triggered inside a nested span now appear directly
    under the function span. They keep their timing, name, service and nested imports.
  • No service, operation, or trace metric changes.

Testing

  • New test: a lazy import inside a client span is parented to the function span.
  • The existing lazy-import test (import directly in the handler) is unchanged.
  • Verified with a real boto3 DynamoDB call (Stubber): no import span ends up under
    dynamodb.command.
    also tested in real lambdas
image image

🤖 Generated with Claude Code

Modules imported during the invocation were parented to whatever span
was active at import time. When that is a client span (e.g. botocore
lazily importing helpers on the first DynamoDB call), the backend peer
service pipeline learns the client's host -> the import span's service
and sets peer.service=aws.lambda on DynamoDB spans (APMS-20524).

Parent them to the function span instead. Imports during init are
unchanged, and span service, names and metrics are not affected.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@datadog-datadog-prod-us1

This comment has been minimized.

@joeyzhao2018
joeyzhao2018 merged commit 71b7244 into main Sep 24, 2026
104 checks passed
@joeyzhao2018
joeyzhao2018 deleted the joey/apms-20524 branch September 24, 2026 17:52
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.

2 participants