Skip to content

fix(id): drop stale data on MicroVM identity refresh - #9814

Draft
litianningdatadog wants to merge 8 commits into
masterfrom
tianning.li/2026-08-05-microvm-identity-refresh-review-followup
Draft

litianningdatadog wants to merge 8 commits into
masterfrom
tianning.li/2026-08-05-microvm-identity-refresh-review-followup

Conversation

@litianningdatadog

@litianningdatadog litianningdatadog commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

https://datadoghq.atlassian.net/browse/SVLS-9768

What does this PR do?

Follow-up to #9709. When a MicroVM clone resumes, telemetry buffered or aggregated before the snapshot can be flushed again under the clone's refreshed identity. This resets or rebases that state on the identity-refresh path instead of only retagging it:

  • DogStatsD metric and telemetry queues, including detached sends, aggregation state, buffered lines, and telemetry counters. The reset is unconditional, even when the serialized tag prefix is unchanged.
  • Trace batches for both the agent and agentless exporters. The agent path also cancels scheduled retries and active common HTTP requests that can still hold a payload with the old runtime-id. Active agentless @datadog/libdatadog exports remain out of scope.
  • OTLP log queues and metric aggregator state: cumulative start time, dropped-measurement count, and ObservableCounter delta baselines.
  • Span-stats buckets (preserving OTLP trace-root mode) and Data Streams buckets, including pre-refresh compression jobs, scheduled retries, and active common HTTP requests.
  • Runtime-metrics CPU/event-loop baselines, including draining @datadog/native-metrics's own accumulators and any GC entries already queued but not yet delivered.

Motivation

Without these resets, clones can duplicate pre-snapshot telemetry, traces, and metrics under fresh MicroVM identities. They can also send a pre-refresh request after the reset, so the same activity may be reported more than once.

Tests

  • Unit tests
  • Integration tests running in AWS env where the debugging log shows the buffer is reset when the ID is refreshed.
image

Additional Notes

  • Remote Config client-id tag behavior is intentionally unchanged here; scope is limited to buffered/aggregated state.
  • The debugger/Dynamic Instrumentation identity-refresh path is deliberately untouched. It was implemented and then removed in 632c70c because a restored MicroVM cannot have an active debugger session.
  • Known gaps remain out of scope for this PR:
    • The sampling profilers (wall/space/event) do not discard buffered pre-snapshot samples on refresh. That needs orchestration-level changes in profiler.js, not the per-processor subscription pattern used here.
    • The tracer's own telemetry queue (telemetry.js's retryData and sentIntegrations) can duplicate or drop pre-snapshot telemetry across clones on resume. This needs separate follow-up work.
    • Active agentless @datadog/libdatadog exports and OTLP HTTP requests are not cancelled on identity refresh. Their transport-specific cancellation paths need separate changes.

Regression tests cover each reset above, including detached sends, pre-refresh compression jobs, active common HTTP request cancellation, and callback-once behavior. Verified locally with the full spec for each affected module (DogStatsD, writer, common request, agent/agentless exporters, OTel logs/metrics, runtime metrics, span stats, Data Streams), plus node --expose-gc against runtime_metrics.spec.js.

@litianningdatadog
litianningdatadog requested a lite review from Copilot August 13, 2026 18:49
@dd-octo-sts

dd-octo-sts Bot commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

Overall package size

Self size: 8.98 MB
Deduped: 9.71 MB
No deduping: 9.71 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.5.1 | 127.66 kB | 513.61 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

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 follows up on MicroVM clone-resume identity refresh behavior in dd-trace-js, ensuring pre-snapshot buffered/aggregated telemetry is dropped (instead of being flushed under each clone’s refreshed identity) and fixing a remote-config client-id tag regression after identity refresh.

Changes:

  • Reset/discard pending state on datadog:identity:refresh across span-stats buckets, agentless trace batches, OTel metrics measurement queues/cumulative baselines, and OTel logs queued records.
  • Rebase runtime-metrics sampler baselines (CPU/ELU/event-loop delay) on identity refresh to avoid deltas spanning the snapshot pause.
  • Ensure _dd.rc.client_id is written back into config.tags whenever an RC client exists (even if tags were rebuilt by an RC lib-config update).

Reviewed changes

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

Show a summary per file
File Description
packages/dd-trace/test/span_stats.spec.js Adds coverage for clearing pending span-stats buckets on identity refresh.
packages/dd-trace/test/runtime_metrics.spec.js Adds coverage for rebasing event-loop-delay baseline on identity refresh (runtime + OTLP variants).
packages/dd-trace/test/remote_config/index.spec.js Ensures RC client-id tag is restored on identity refresh when an RC client exists.
packages/dd-trace/test/opentelemetry/metrics.spec.js Adds coverage for dropping pre-refresh sync Counter measurements on identity refresh.
packages/dd-trace/test/opentelemetry/logs.spec.js Adds coverage for dropping queued pre-refresh log records on identity refresh.
packages/dd-trace/test/exporters/common/writer.spec.js Adds unit test for discarding a pending encoded batch via resetPendingBatch().
packages/dd-trace/test/exporters/agentless/exporter.spec.js Adds coverage that agentless exporter drops pending trace batch on identity refresh.
packages/dd-trace/test/dogstatsd.spec.js Adds coverage for dropping pending aggregated metrics when identity refresh changes tags, and preserving when unchanged.
packages/dd-trace/src/span_stats.js Subscribes to identity refresh to drop pre-snapshot span-stats buckets.
packages/dd-trace/src/runtime_metrics/runtime_metrics.js Routes identity refresh through subscribeToIdentityRefresh(..., resetSamplerBaselines) and implements baseline rebase.
packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js Rebases OTLP runtime-metrics baselines (ELU + event-loop histogram) on identity refresh.
packages/dd-trace/src/runtime_metrics/client.js Extends subscribeToIdentityRefresh to accept an optional post-refresh callback.
packages/dd-trace/src/remote_config/index.js Writes _dd.rc.client_id back to config.tags whenever an RC client exists.
packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js Adds resetPendingState() to discard queued measurements and sync cumulative state.
packages/dd-trace/src/opentelemetry/metrics/index.js Subscribes to identity refresh to drop pending OTel metrics state (with restart-safe unsubscribe handling).
packages/dd-trace/src/opentelemetry/logs/index.js Subscribes to identity refresh to drop pending OTel logs state (with restart-safe unsubscribe handling).
packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js Adds resetPendingState() to discard queued log records and clear the timer.
packages/dd-trace/src/exporters/common/writer.js Adds resetPendingBatch() to drop pending encoded trace batches.
packages/dd-trace/src/exporters/agentless/index.js Subscribes to identity refresh to drop pending agentless trace batches.
packages/dd-trace/src/dogstatsd.js Makes tag updates report whether tags changed; resets aggregation only when the underlying tag prefix changed.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/dd-trace/src/span_stats.js Outdated
Comment thread packages/dd-trace/src/exporters/agentless/index.js Outdated
@pr-commenter

pr-commenter Bot commented Aug 13, 2026 •

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-09-14 19:33:11

Comparing candidate commit 3075325 in PR branch tianning.li/2026-08-05-microvm-identity-refresh-review-followup with baseline commit 3dcb352 in branch master.

📊 Benchmarking dashboard

Found 0 performance improvements and 0 performance regressions! Performance is the same for 2306 metrics, 7 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:appsec-appsec-enabled-24

  • unstable max_rss_usage [-29.900MB; +47.732MB] or [-10.527%; +16.805%]

scenario:encoders-0.4-immediate-flush-20

  • unstable max_rss_usage [-13.656MB; +0.497MB] or [-17.552%; +0.638%]

scenario:llmobs-encode-unicode-mixed-20

  • unstable max_rss_usage [-5.909MB; +12.466MB] or [-8.062%; +17.007%]

scenario:plugin-graphql-long-with-depth-off-26

  • unstable max_rss_usage [-13.547MB; +44.567MB] or [-6.055%; +19.921%]
  • unstable throughput [-25.023op/s; +8.738op/s] or [-7.468%; +2.608%]

scenario:plugin-pino-json-log-injection-24

  • unstable execution_time [-164.351ms; +238.124ms] or [-5.681%; +8.231%]
  • unstable throughput [-110842.320op/s; +78933.015op/s] or [-6.373%; +4.538%]

@datadog-prod-us1-4

datadog-prod-us1-4 Bot commented Aug 13, 2026 •

Copy link
Copy Markdown

Tests

✅ All CI checks and tests passed.

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
• Patch Coverage: 99.46%
• Overall Coverage: 98.21% (+0.00%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 3075325 | Docs | View more details | Give us feedback!

@codecov

codecov Bot commented Aug 13, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.46043% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 98.71%. Comparing base (3dcb352) to head (3075325).

Files with missing lines Patch % Lines
...ackages/dd-trace/src/exporters/span-stats/index.js 62.50% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           master    #9814    +/-   ##
========================================
  Coverage   98.71%   98.71%            
========================================
  Files        1025     1025            
  Lines      160626   161126   +500     
  Branches       74       74            
========================================
+ Hits       158563   159060   +497     
- Misses       2063     2066     +3     
Flag Coverage Δ
ai-guard 65.28% <68.33%> (+<0.01%) ⬆️
apm-capabilities 63.83% <99.46%> (+0.15%) ⬆️
apm-integrations 81.55% <71.42%> (-0.05%) ⬇️
appsec 58.96% <68.72%> (+0.01%) ⬆️
debugger 70.20% <64.54%> (-0.06%) ⬇️
instrumentation 54.49% <66.02%> (+0.02%) ⬆️
llmobs 79.04% <68.33%> (-0.06%) ⬇️
master-coverage 98.71% <99.46%> (?)
openfeature 66.52% <66.81%> (-0.03%) ⬇️
platform 69.37% <64.77%> (-0.04%) ⬇️
profiling 66.86% <66.81%> (-0.03%) ⬇️
serverless 66.02% <71.42%> (+<0.01%) ⬆️
test-optimization 82.51% <73.18%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@litianningdatadog
litianningdatadog force-pushed the tianning.li/2026-08-05-microvm-identity-refresh-review-followup branch from 4f85c4a to 016848d Compare August 13, 2026 19:14
@litianningdatadog litianningdatadog changed the title fix(id): drop pending telemetry and fix RC client-id on MicroVM identity refresh fix(id): drop stale telemetry and RC tag on identity refresh Aug 13, 2026
@litianningdatadog
litianningdatadog force-pushed the tianning.li/2026-08-05-microvm-identity-refresh-review-followup branch from 016848d to 579c97e Compare August 13, 2026 19:31
@litianningdatadog
litianningdatadog marked this pull request as ready for review August 14, 2026 13:20
@litianningdatadog
litianningdatadog requested review from a team as code owners August 14, 2026 13:20
@litianningdatadog
litianningdatadog requested review from BridgeAR and a balanced review from Copilot and removed request for a team August 14, 2026 13:20

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

Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.

Suppressed comments (3)

packages/dd-trace/src/dogstatsd.js:255

  • The aggregation maps also need to be discarded on every identity refresh, not only when the rendered tag prefix changes. Otherwise configurations that omit runtime-id and RC tags preserve identical pre-snapshot counters/gauges/histograms in every clone; the refresh event itself is the signal to drop them.
    if (this._client.updateTags(tags)) {
      this.reset()

packages/dd-trace/src/dogstatsd.js:71

  • An identity refresh still represents a clone resume when the generated DogStatsD tags are unchanged—for example, with runtime-id tagging disabled and Remote Config disabled. Returning here keeps the pre-snapshot encoded buffer, so every clone can flush the same metrics. Clear the buffer on every refresh while retaining the boolean only as an indication that the prefix changed.

This issue also appears on line 254 of the same file.

    if (tagsPrefix === this.#tagsPrefix) return false

packages/dd-trace/src/runtime_metrics/runtime_metrics.js:186

  • On supported Node versions before the new per-iteration sampler, the default path uses @datadog/native-metrics; its stats() call owns and drains the CPU, event-loop, and GC accumulators. This reset only rebases JavaScript state, so the first post-resume capture still exports the native pre-snapshot accumulations from every clone. Drain nativeMetrics.stats() during refresh as well.
function resetSamplerBaselines () {

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 579c97eb74

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/dd-trace/src/dogstatsd.js Outdated
Comment on lines +254 to +256
if (this._client.updateTags(tags)) {
this.reset()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reset aggregates even when generated tags are unchanged

On a MicroVM resume, the generated DogStatsD tags commonly remain unchanged: DogStatsDClient.generateClientConfig() excludes runtime-id unless runtimeMetricsRuntimeId is enabled, which defaults to false, and serverless configuration disables Remote Config so there may be no changing RC client-id tag either. In that default case updateTags() returns false and this branch retains counters, gauges, and histograms accumulated in the snapshot, causing every clone to flush duplicate pre-snapshot values; the identity-refresh subscriber should reset aggregation regardless of whether the serialized tag prefix changes. The added tests only exercise the non-default runtime-id-enabled case and explicitly preserve the faulty sibling case.

AGENTS.md reference: AGENTS.md:L127-L129

Useful? React with 👍 / 👎.

Comment on lines +173 to +178
function resetSamplerBaselines () {
lastTime = performance.now()
lastElu = performance.eventLoopUtilization()

if (lastCpuUsage !== null) {
lastCpuUsage = process.cpuUsage()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Drain native metric accumulators before rebasing the clock

When the @datadog/native-metrics branch is active, this rebases lastTime but does not consume or reset the addon's accumulated CPU, event-loop, and GC statistics. The next captureNativeMetrics() therefore reads pre-snapshot values from nativeMetrics.stats() while dividing CPU usage by only the post-refresh elapsed time, producing an inflated first sample and exporting the stale event-loop/GC data the change intends to discard. Resetting this branch needs to drain the native statistics as well; the new observer-reset test explicitly skips this supported sibling path.

AGENTS.md reference: AGENTS.md:L127-L129

Useful? React with 👍 / 👎.

Comment on lines +224 to +227
for (const key of this.#cumulativeState.keys()) {
this.#lastExportedState.delete(key)
}
this.#cumulativeState.clear()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Rebase cumulative metric start times on identity refresh

Clearing #cumulativeState starts a new value series for synchronous cumulative counters, histograms, and up/down counters, but MetricAggregator.#startTime remains the timestamp captured when the snapshot image initialized. After a clone resumes—potentially days later—the first cumulative point therefore contains only post-resume measurements while claiming an interval beginning before the snapshot, which yields incorrect rates and temporal metadata under the clone's new resource identity. The reset must also advance the aggregator start time; the added test covers only the default delta-counter sibling.

AGENTS.md reference: AGENTS.md:L127-L129

Useful? React with 👍 / 👎.

@datadog-prod-us1-4 datadog-prod-us1-4 Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Datadog Autotest: FAIL

Native runtime metrics still retain pre-snapshot CPU/event-loop/GC accumulators, while span stats can retain the old tags object after an RC tag update. Both paths can make clones emit telemetry associated with snapshot-era state or identity.

Open Bits AI session

🤖 Datadog Autotest · Commit 579c97e · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

Comment on lines +174 to +175
lastTime = performance.now()
lastElu = performance.eventLoopUtilization()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Drain native runtime metrics during refresh

Every clone using native runtime metrics can report the same pre-snapshot event-loop/GC activity and inflated CPU usage under its fresh identity.

Assertion details
  • Input: A MicroVM snapshot taken after @datadog/native-metrics accumulates activity but before its periodic stats() collection, then resumed into one or more clones.
  • Expected: Identity refresh should drain the native addon's CPU, event-loop, and GC state before establishing post-resume baselines.
  • Actual: The new refresh callback only rebases JavaScript timestamps. On the native path, the addon's CPU baseline and event-loop/GC histograms remain populated until nativeMetrics.stats() is called, so the next periodic collection includes snapshot-era activity.
Suggested change
lastTime = performance.now()
lastElu = performance.eventLoopUtilization()
nativeMetrics?.stats()
lastTime = performance.now()
lastElu = performance.eventLoopUtilization()

Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

Comment thread packages/dd-trace/src/span_stats.js Outdated
Comment on lines +219 to +220
const onIdentityRefresh = () => {
this.buckets = new TimeBuckets()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Refresh span-stats' replaced tags reference

Agent span stats from multiple clones can share the snapshot runtime ID, causing cross-clone identity collisions and incorrect aggregation.

Assertion details
  • Input: Remote Config applies tracing_tags after SpanStatsProcessor construction, replacing config.tags, followed by a MicroVM identity refresh and agent-format span-stats export.
  • Expected: The span-stats processor should adopt the current config.tags object when identity refresh fires, before exporting new buckets.
  • Actual: The callback clears buckets but leaves this.tags pointing to the object captured during construction. An RC tracing_tags update replaces config.tags, so identity refresh mutates a different object and subsequent v0.6 stats retain the snapshot runtime ID.
Suggested change
const onIdentityRefresh = () => {
this.buckets = new TimeBuckets()
const onIdentityRefresh = (config) => {
this.tags = config?.tags ?? this.tags
this.buckets = new TimeBuckets()

Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-08-05-microvm-identity-refresh-review branch from 6cac3ff to 31556cd Compare August 14, 2026 19:38
@BridgeAR
BridgeAR requested review from a team as code owners August 14, 2026 19:38
@BridgeAR
BridgeAR requested review from crysmags and removed request for a team August 14, 2026 19:38
@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-08-05-microvm-identity-refresh-review branch 3 times, most recently from aa18e4e to dcf016d Compare August 20, 2026 16:51

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e427594c00

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


// A clone resume shouldn't flush spans buffered before the snapshot under its own identity.
unsubscribeBatchReset?.()
const onIdentityRefresh = () => this._writer.resetPendingBatch()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Cancel active agentless trace exports on refresh

When an agentless batch has already reached AgentlessWriter._sendPayload() before the MicroVM snapshot, this reset only clears the encoder; the active @datadog/libdatadog exporter and its sendV04() operation remain live, so every clone can complete the same pre-snapshot trace delivery. Fresh evidence in this revision is that the agentless transport never receives the new common-request reset controller, despite caching an exporter that can be closed; the refresh path needs to invalidate the active pipeline export as well as the queued encoder batch.

AGENTS.md reference: AGENTS.md:L79-L79

Useful? React with 👍 / 👎.

Comment on lines +77 to +78
const onIdentityRefresh = () => processor.resetPendingState()
identityRefreshChannel.subscribe(onIdentityRefresh)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Cancel detached OTLP exports on identity refresh

When an OTLP log or metric batch has already been transformed and passed to OtlpHttpExporterBase.sendPayload() before the snapshot, resetting only the processor queue or metric reader cannot reach it: the base exporter retains the HTTP request and serialized payload and exposes no reset/cancellation hook. Each resumed clone can therefore finish the same pre-snapshot OTLP export, so both newly added reset subscriptions need to invalidate active exporter requests as well as stored measurements or log records.

AGENTS.md reference: AGENTS.md:L79-L79

Useful? React with 👍 / 👎.

Comment on lines +253 to +255
this.tags = config?.tags ?? this.tags
this.buckets = new TimeBuckets()
this.writer.resetPendingRequests()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reset schema-sampling weights with Data Streams state

When Avro or Protobuf schema sampling has accumulated calls in DataStreamsProcessor._schemaSamplers before the snapshot, this handler clears only buckets, leaving every clone with the same SchemaSampler.weight and lastSampleMs. The next eligible post-resume schema span in each clone therefore reports a schema.weight that includes the identical pre-snapshot message count (and may retain the old sampling window); reset the schema samplers along with the other inherited Data Streams aggregation state.

AGENTS.md reference: AGENTS.md:L79-L79

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7af4bdaa12

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +48 to +50
for (const retry of controller.pendingRetryTimers) {
retry.cancel()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Abort active requests during identity reset

When an agent, span-stats, or Data Streams request is still in an asynchronous DNS lookup or socket connection at clone resume, reset() only cancels entries in pendingRetryTimers; the ClientRequest already created by attempt() remains live and can transmit its pre-snapshot buffer from every restored clone. Track and abort active requests as well as retry timers, settling their callbacks with the refresh cancellation error.

AGENTS.md reference: AGENTS.md:L73-L79

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 40b95a8f35

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +440 to +442
const { type } = measurement
if (type !== METRIC_TYPES.OBSERVABLECOUNTER || this.#getTemporality(type) !== TEMPORALITY.DELTA) {
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Rebase observable up/down counters on identity refresh

When an application uses an ObservableUpDownCounter, its callback can report a process-lifetime total, but these lines only rebase delta ObservableCounter values. Because observable up/down counters are always cumulative, the first export after a MicroVM resume therefore reports the entire pre-snapshot value under the clone's refreshed runtime ID while using the newly reset start time. Preserve and subtract a refresh offset for this sibling instrument type as well.

AGENTS.md reference: AGENTS.md:L79-L79

Useful? React with 👍 / 👎.

@BridgeAR BridgeAR 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.

Could we split this into smaller chunks? Now that the main functionality exists, we could change smaller pieces at a time

litianningdatadog and others added 8 commits September 14, 2026 15:10
Copilot/Codex review of #9814 found several reset paths that still leaked
pre-snapshot state across MicroVM clones. DogStatsD only reset buffered
lines/telemetry counters when the serialized tag prefix changed, which a
clone resume with runtime-id tagging disabled skips entirely. Runtime
metrics didn't drain the native-metrics addon or queued GC observer
entries. Span stats dropped the OTLP trace-root flag on reset. The OTel
periodic metric reader didn't rebase its cumulative start time. The
default (non-agentless) agent exporter never reset its pending batch at
all. Fixes each with regression tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes the last three gaps from PR review: Data Streams span-stats
buckets, in-flight trace-transport retries, and OTel metrics' dropped-
measurement count and ObservableCounter delta baselines all survived
a MicroVM identity refresh and could be re-flushed under a clone's
new identity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@litianningdatadog
litianningdatadog force-pushed the tianning.li/2026-08-05-microvm-identity-refresh-review-followup branch from 40b95a8 to 3075325 Compare September 14, 2026 19:18

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3075325e07

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
controller.pendingRetryTimers.clear()

const activeRequests = [...controller.activeRequests]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Snapshot active requests before invoking retry callbacks

When a MicroVM refresh cancels a scheduled retry, retry.cancel() synchronously invokes the original flush callback before activeRequests is snapshotted. If that callback records post-refresh data and starts another flush, its new request uses the current generation but is added to activeRequests in time to be included here and is then aborted as though it were stale. Capture the active-request set before invoking any cancellation callbacks so reentrant post-refresh exports are preserved.

Useful? React with 👍 / 👎.

This branch has not been deployed

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

Labels

aws-microvm AWS MicroVM related features semver-patch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants