feat(core): add public tracer.flush() API#9444
Conversation
Serverless/isolate runtimes (Cloudflare Workers, Lambda, graceful shutdown handlers) need a way to guarantee buffered spans are sent before the runtime freezes or exits, instead of relying on fixed-timer workarounds. Adds a promise-returning tracer.flush() that delegates to the active exporter's flush and resolves once the export completes, for both the batching agent exporters and the OTLP exporter (which previously had no flush concept since it sends each payload immediately). The OTLP exporter's request completion handler is now idempotent per request: Node's http.ClientRequest#destroy() (called on timeout) can still emit a later 'error' event on the same request, which was double-decrementing the pending-request counter and could let flush() resolve while a genuinely in-flight export was still running. The public flush() also wraps its delegation to the exporter/tracer in try/catch so a synchronous throw can't turn the returned promise into a rejection, keeping the documented "never rejects" contract structurally true. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Overall package sizeSelf size: 7.48 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.1 | 122.62 kB | 438.86 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
|
BenchmarksBenchmark execution time: 2026-07-20 19:33:11 Comparing candidate commit bf9087a in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 2323 metrics, 35 unstable metrics.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #9444 +/- ##
==========================================
+ Coverage 98.34% 98.42% +0.07%
==========================================
Files 924 938 +14
Lines 123080 126289 +3209
Branches 10599 11046 +447
==========================================
+ Hits 121048 124299 +3251
+ Misses 2032 1990 -42
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
What does this PR do?
Adds a public, promise-returning
tracer.flush(): Promise<void>that flushes buffered/pending spans and resolves once the resulting export completes. This gives serverless/isolate runtimes a way to guarantee spans are sent before the runtime freezes or the process exits:Writer.flush(done)/AgentExporter.flush(done)plumbing for the agent/agentless path.OtlpHttpExporterBase) soflush()resolves when in-flight OTLP requests complete — the Cloudflare Workers path.ctx.waitUntil(tracer.flush())can't error the caller.async/awaitin production code — the Promise is constructed only at the public boundary; internals stay callback-based.Motivation
Serverless/isolate runtimes (Cloudflare Workers via
ctx.waitUntil, AWS Lambda, graceful shutdown) freeze or exit as soon as the handler returns, dropping any not-yet-exported spans. dd-trace previously only flushed on an interval and onbeforeExit(which Workers never fires). A promise-returningflush()lets callers await export completion. Complements the Cloudflare Workers support effort (#1892).Additional Notes
semver-minor— new public API. Added to bothindex.d.tsandindex.d.v5.ts, documented indocs/API.md.flush()waits on already-in-flight requests (doesn't trigger a new send). It does not currently wait on the separate OTel span-stats exporter — noted indocs/API.md.timeout→destroy()→error), which would letflush()resolve while an export was still in flight; guarded with a per-requestsettledflag + a regression test.