Skip to content

SLES 2889 | Fixing payload size#1257

Merged
jchrostek-dd merged 4 commits into
mainfrom
john/SLES-2889
Jun 17, 2026
Merged

SLES 2889 | Fixing payload size#1257
jchrostek-dd merged 4 commits into
mainfrom
john/SLES-2889

Conversation

@jchrostek-dd

Copy link
Copy Markdown
Contributor

https://datadoghq.atlassian.net/browse/SLES-2889

Overview

Large single-invocation traces could be rejected by the trace intake with a 413, because the extension undercounted how big a payload would be once it left the extension.

The extension enriches every span after the tracer posts it (adding the tags-provider map), so the protobuf payload it sends is larger than the raw msgpack it received. The trace aggregator's batch cap therefore undercounted the true outbound bytes and packed too much into a single request, whose combined size exceeded the intake limit → 413.

The batch cap was below realistic enriched payload sizes. The cap was set to the old 3.2 MB documented limit. However, from trace intake config, the limit is actually 15.

This PR:

  • Computes body_size from the enriched, protobuf-encoded payload unconditionally (not only when on-extension stats are enabled), so the aggregator's batch cap reflects exactly what will be sent.
  • Raises the batch cap from 3.2 MB to 12 MB — kept below the trace intake's ~15 MB limit so a large enriched payload flushes in a single batch without a 413.
  • Adds debug logs for the post-enrichment payload size and per-batch coalesced size.

Testing

  • Unit: new test asserting body_size equals the protobuf encoded_len of the payload actually sent, and exceeds the (smaller) ingress size — on the default config (no on-extension stats).
  • Integration: new payload-size suite deploys a Node Lambda that emits a ~10 MB single-invocation trace (400 spans carrying large captured payloads) and verifies it: enriches to >10 MB, flushes in a single batch >10 MB, arrives with no 413, and is delivered intact (one trace, root span present, all 400 spans). Run against a locally published extension layer in the serverless sandbox.

process_traces captured body_size from the raw msgpack request at ingress
and passed it through unchanged. But every span is then enriched with the
tags-provider map (function_arn, region, env, ...), so the protobuf payload
actually sent is substantially larger than that ingress figure.

Both size caps gate on this value: the TraceAggregator's per-batch limit and
libdatadog's coalesce limit. Sizing by the smaller ingress number lets the
extension bundle and send payloads that exceed the backend's limit, which
rejects them with 413 Payload Too Large (and retries that can never succeed).

Recompute body_size from the protobuf encoded_len of the payload that will
actually be sent. This previously happened only when
compute_trace_stats_on_extension was enabled; it now runs unconditionally so
the default configuration is correct too.
The TraceAggregator's per-batch cap was 3.2 MB. Combined with the
enriched-protobuf sizing fix, a single trace whose enriched payload sits
between 3.2 MB and the trace intake's ~15 MB limit could neither be split
within one SendData nor flushed: get_batch() put it back on the queue
indefinitely, stalling every trace behind it (silently dropped traces and
apparent timeouts).

Raise MAX_CONTENT_SIZE_BYTES to 12 MB so such a payload flushes in a single
batch while staying under the ~15 MB intake limit. Add debug logging of the
per-batch total and the post-enrichment payload size for diagnosability.
Deploys a Node Lambda that produces a single ~10 MB trace from real
instrumented spans (a payload-logging service capturing sizeable order
documents on a few hundred spans) and asserts the trace reaches Datadog with
its root span and >100 child spans. Reads the extension's post-enrichment
payload-size debug line from CloudWatch and asserts it lands in (3.2 MB,
12 MB) -- above the old cap (so it would have stalled before the fix) and
below the new cap and the backend limit.

Registered in bin/app.ts and the test-suites datasource.
@datadog-prod-us1-5

datadog-prod-us1-5 Bot commented Jun 15, 2026

Copy link
Copy Markdown

Pipelines

Fix all issues with BitsAI

⚠️ Warnings

🚦 2 Pipeline jobs failed

DataDog/datadog-lambda-extension | bottlecap (arm64)   View in Datadog   GitLab

DataDog/datadog-lambda-extension | bottlecap (arm64, fips)   View in Datadog   GitLab

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 265fe0b | Docs | Datadog PR Page | Give us feedback!

@jchrostek-dd
jchrostek-dd marked this pull request as ready for review June 15, 2026 18:40
@jchrostek-dd
jchrostek-dd requested review from a team as code owners June 15, 2026 18:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses 413 “Payload Too Large” failures for large single-invocation traces by ensuring outbound trace batching uses the post-enrichment, protobuf-encoded payload size (the size actually sent), and by increasing the trace batch size cap to better align with trace intake limits. It also adds unit + integration coverage to prevent regressions and to validate end-to-end behavior for ~10MB traces.

Changes:

  • Compute body_size from the enriched protobuf payload size for batching accuracy (not just when on-extension stats are enabled).
  • Increase trace aggregator max batch size to 12 MB and add debug logs for enriched and batched sizes.
  • Add a new integration test suite that generates and validates delivery of a large single-invocation trace.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
integration-tests/tests/utils/cloudwatch.ts Adds CloudWatch Logs helper for filtering extension/Lambda log lines (region/pagination handling needs fixes).
integration-tests/tests/payload-size.test.ts New integration test asserting large enriched + batched payloads flush without 413 and are delivered intact.
integration-tests/lib/stacks/payload-size.ts New CDK stack deploying a Node Lambda that emits a large trace with debug logging enabled.
integration-tests/lambda/large-trace-node/index.js Node Lambda code to generate a large single-invocation trace by attaching large tag payloads across many spans.
integration-tests/bin/app.ts Registers the new PayloadSize stack in the integration test app.
bottlecap/src/traces/trace_processor.rs Fixes body_size accounting to reflect enriched protobuf payload size; adds debug log; adds unit test.
bottlecap/src/traces/trace_aggregator.rs Raises max trace batch cap to 12MB; adds debug log for per-batch coalesced size.
.gitlab/datasources/test-suites.yaml Adds payload-size suite to CI test suite list.

Comment on lines +1 to +6
import {
CloudWatchLogsClient,
FilterLogEventsCommand,
} from '@aws-sdk/client-cloudwatch-logs';

const logsClient = new CloudWatchLogsClient({ region: 'us-east-1' });
Comment on lines +21 to +40
const messages: string[] = [];
let nextToken: string | undefined;

do {
const response = await logsClient.send(
new FilterLogEventsCommand({
logGroupName,
filterPattern,
startTime,
endTime,
nextToken,
}),
);
for (const event of response.events ?? []) {
if (event.message) {
messages.push(event.message);
}
}
nextToken = response.nextToken;
} while (nextToken);
Comment on lines +134 to +141
if !self.buffer.is_empty() {
debug!(
"TRACES | batched {} payload(s) totaling {batch_size} bytes (cap {} bytes)",
self.buffer.len(),
self.max_content_size_bytes
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Wonder if libdatadog has something similar?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't think they do. If they did, would still prefer for it to be here as well since we use this log message for our integration tests to ensure we are actually testing against a large payload.

@lucaspimentel lucaspimentel left a comment

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.

LGTM aside from Copilot's comment about the hard-coded us-east-1 which seems legit.

@jchrostek-dd
jchrostek-dd merged commit 57558de into main Jun 17, 2026
40 of 47 checks passed
@jchrostek-dd
jchrostek-dd deleted the john/SLES-2889 branch June 17, 2026 18:38
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.

4 participants