Skip to content

feat(otel): connect durable orchestration spans across worker processes - #9794

Draft
chemystery09 wants to merge 4 commits into
ishara/otel-azure-trace-context-linkagefrom
ishara/otel-azure-orchestration-spans
Draft

feat(otel): connect durable orchestration spans across worker processes#9794
chemystery09 wants to merge 4 commits into
ishara/otel-azure-trace-context-linkagefrom
ishara/otel-azure-orchestration-spans

Conversation

@chemystery09

@chemystery09 chemystery09 commented Aug 12, 2026

Copy link
Copy Markdown

Summary

Stacked on #9683. Fixes cross-worker trace parenting for Durable Functions on Azure.

Problem this solves: Azure DTF distributed tracing parents each invocation to extension-internal spans. Orchestrations also run later and on different workers than the HTTP trigger that called startNew. Without shared state:

  • HTTP → orchestration link is lost when the orchestrator runs on another worker
  • Activities parent to Azure's W3C parent (phantom span) instead of the orchestration span
  • Orchestration would emit one span per replay turn instead of one span per instance

What this PR does:

  1. Records one orchestration span identity per instanceId in a shared store (in-process cache → local JSON → Azure Table DDAzureOrchestrationSpans)
  2. Seeds orchestration metadata from the active HTTP span at DurableClient.startNew so the orchestration span can parent under HTTP even when the orchestrator runs elsewhere
  3. Exports a single orchestration span at instance completion with a full-instance time window (startTime anchored at HTTP startNew, endTime at completion, clamped to earliest activity start)
  4. Resolves activity parent context from the shared store so activities on any worker parent under the orchestration span

All activity handlers use async parent resolution so sync activities on a different worker than the HTTP trigger can read the Azure Table store (not just local JSON).

Orchestration span timing (approach 1: backfill at completion)

We intentionally do not emit a live orchestration span on every replay turn. Instead, one span is backfilled when the instance completes, using metadata timestamps:

  • startTime — anchored at DurableClient.startNew (HTTP span start time when available), merged with recordEarliestChildStartTime at export via resolveExportStartTime
  • endTime — instance completion time

This fixes waterfall ordering where activity spans (live) appeared to start before their orchestration parent. The prior “first non-replay orchestrator turn” stamp was too late because replay turns skipped metadata updates until after the first activity had already exported.

Drawbacks of this approach (explicit trade-offs):

  • Not live during execution — the orchestration span only appears in Datadog after the instance completes; you cannot watch an in-flight orchestration span in Trace Explorer mid-run.
  • Backfilled, not measured per replay turn — duration covers the whole instance (first turn → completion), not individual orchestrator replays; sub-yield orchestrator work is not separately timed.
  • Activity spans export before the orchestration span — activities emit live timestamps immediately; the orchestration span is inserted at completion. Parent links are correct, but the orchestration bar is synthesized retroactively (minor waterfall lag vs a live parent span).
  • Clock source mixing — activities use live OTel timing while the orchestration span uses stored Date.now() bounds; extreme clock skew across workers could still produce small visual gaps (clamped on export).
  • Incomplete instances — if an orchestration fails or is abandoned before completion, no orchestration span is exported (same as before); only activities/orchestrator turns that ran will appear.

A future live orchestration span mode (approach 2) could address in-flight visibility but adds complexity across replay, worker scale-out, and agentless flush — out of scope here.

Required configuration (Function app)

Everything from #9683, plus:

Must be enabled

Setting Value Why
AzureWebJobsStorage valid connection string (Azurite locally, real storage on Azure) Backing store for DDAzureOrchestrationSpans table used cross-worker
@azure/data-tables available at runtime (provided by Functions host / app deps) Table client for shared orchestration meta
HTTP trigger that calls client.startNew() e.g. PizzaPartystartNew('PizzaOrderOrchestration', …) startNew hook seeds orchestration span identity from the active HTTP span

Optional

Setting Value Why
DD_TRACE_AZURE_ORCHESTRATION_STORE_DIR custom path Override local JSON cache dir (tests/dev only; default is $TMPDIR/dd-orchestration-spans)

Still must be disabled (same as #9683)

Setting Value
DD_TRACE_AZURE_DURABLE_FUNCTIONS_ENABLED false
Native dd-trace plugins plugins: false
.NET tracer loader removed

host.json (unchanged from #9683)

"tracing": {
  "distributedTracingEnabled": true,
  "version": "V2"
}

Architecture (brief)

HTTP span (worker A)
  └─ startNew → seed orchestration meta → Azure Table + local JSON
       └─ orchestration span (exported once at completion; start=turn 1, end=complete)
            ├─ PreparePizzaActivity (worker A: local file hit)
            └─ BakePizzaActivity (worker B: Azure Table async read)

Changes

  • otel-orchestration-store.js, otel-orchestration-meta.js, otel-orchestration-export.js, otel-orchestration-http-link.js, otel-orchestration-registry.js
  • azure-trace-context.js — activity parent resolution from store
  • otel-azure-durable-functions.js / otel-azure-functions.js — one span per instance; async activity parent resolution
  • azure-durable-functions.jsDurableClient.startNew hook
  • recordHttpInstanceStartTime / recordEarliestChildStartTime / resolveExportStartTime — full-instance orchestration span window

Test plan

Verified — local Azurite storage (durable-node, not DTS)

Storage: AzureWebJobsStorage=UseDevelopmentStorage=true (Azurite). Service durable-node-azurite-local, env local.

  • Unit tests for orchestration span timing bounds (test(otel): Azure durable instrumentation unit coverage #9793)
  • E2E pizza party: POST http://localhost:7071/api/pizzaparty (PizzaOrderOrchestration: Prepare → Bake)
  • Both PreparePizzaActivity and BakePizzaActivity parent under orchestration PizzaOrderOrchestration
  • Orchestration span parents under http PizzaParty, not phantom root
  • Orchestration waterfall bar starts at HTTP startNew time and covers activity children

Example trace (2026-08-13): instance 22d765967b474e87a1c4f54e50020e7dhttps://ddserverless.datadoghq.com/apm/trace/b888f30374a9d9ce987b9b921f204eb4

Pending — Azure Durable Task Scheduler (durable-node-fx)

Storage: DTS (test-scheduler / ishara-node-hub), service durable-function-poc-node, env dev.

  • E2E pizza party: POST https://durable-node-fx.azurewebsites.net/api/pizzaparty — orchestrations complete
  • Orchestration timing waterfall on DTS when all spans run on one worker — trace 17862494001755642471
  • Reliable cross-worker activity parenting on DTS — see Known limitation below
  • Multi language-worker regression (FUNCTIONS_WORKER_PROCESS_COUNT=4 locally or Azure scale-out)

Known limitation: multi-worker activity parenting

This is not an Azurite vs DTS storage issue. The shared store path (local JSON → Azure Table via AzureWebJobsStorage) is the same on local Azurite and Azure. What matters is worker topology:

Topology Parenting Example
Single worker (typical local func start) Works — HTTP, orchestration, and activities read the same in-process / local-file meta Local trace b888f303…; DTS trace 17862494001755642471
Multi-worker / scale-out Intermittent — an activity dispatched to a cold worker can miss orchestration meta in the Azure Table store before the async read window expires and fall back to Azure's internal W3C parent (phantom span) DTS trace 5825695498924434065: PreparePizzaActivity parented correctly (same worker as orchestrator); BakePizzaActivity orphaned (different worker)

Locally, FUNCTIONS_WORKER_PROCESS_COUNT>1 can reproduce the same race; default single-worker dev runs do not exercise it.

Root cause: orchestration meta is published to Azure Table asynchronously (errors swallowed); activity handlers async-read with a short retry budget (~300 ms). A second worker that starts before the row is visible gets no meta and parents to the Azure extension span instead.

Possible follow-ups (not in this PR)

Approach Pros Drawbacks
Wire tracestate injection (dd=o:{orchestrationSpanId} at dispatch; helper exists) No orchestrator stall; propagates with W3C tracecontext Depends on Azure host preserving custom tracestate keys end-to-end
Await first table publish before orchestrator yield Deterministic cross-worker reads Adds table latency on first turn; must guard replay turns
Extend async retry window Smallest change Still probabilistic; increases activity cold-start delay
Hybrid (recommended) Tracestate fast path + first-yield table await + modest retry safety net Most implementation and test surface

Recommended next step: hybrid — tracestate injection first, then await only the first table publish before the orchestrator's first yield.

Quick reference — full OTel-only stack (#9683 + #9794)

// local.settings.json / Azure app settings
{
  "DD_TRACE_OTEL_ENABLED": "true",
  "DD_TRACE_AZURE_DURABLE_FUNCTIONS_ENABLED": "false",
  "DD_API_KEY": "<key>",
  "DD_TRACE_SAMPLE_RATE": "1",
  "DD_TRACE_FLUSH_INTERVAL": "0",
  "_DD_APM_TRACING_AGENTLESS_ENABLED": "true",
  "languageWorkers__node__arguments": "--require ./src/instrumentation.js",
  "NODE_OPTIONS": "",
  "AzureWebJobsStorage": "<connection-string>"
}
// host.json
"extensions": {
  "durableTask": {
    "tracing": {
      "distributedTracingEnabled": true,
      "version": "V2"
    }
  }
}

Persist one orchestration span identity per instance in a shared store so
activities on any worker parent correctly, seed metadata from the HTTP
span at startNew, and export a single orchestration span when the instance
completes instead of one span per replay turn.

Co-authored-by: Cursor <cursoragent@cursor.com>
@dd-octo-sts

dd-octo-sts Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Overall package size

Self size: 8.07 MB
Deduped: 8.73 MB
No deduping: 8.73 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.3 | 125.43 kB | 441.68 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

@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Aug 12, 2026

Copy link
Copy Markdown

Pipelines  Tests

Unblock PR with BitsAI

⚠️ Warnings

🚦 22 Pipeline jobs failed

All Green | all-green   View in Datadog   GitHub Actions

See error Workflow run 31634078519 failed after retry due to one or more jobs failing. Process completed with exit code 1.

🧪 4 Tests failed

db sources with sequelize with sequelize &gt;=4 (4.0.0) sequelize &#34;before each&#34; hook for &#34;Should have SQL_INJECTION using the first row of the result&#34; from using query method   View in Datadog
Could not locate the bindings file. Tried:
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/build/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/build/Release/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/out/Release/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/Release/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/build/default/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/compiled/20.20.2/linux/x64/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/addon-build/release/install-root/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/addon-build/default/install-root/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/lib/binding/node-v115-linux-x64/node_sqlite3.node
...
db sources with sequelize with sequelize &gt;=4 (4.44.4) sequelize &#34;before each&#34; hook for &#34;Should have SQL_INJECTION using the first row of the result&#34; from using query method   View in Datadog
Could not locate the bindings file. Tried:
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/build/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/build/Release/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/out/Release/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/Release/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/build/default/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/compiled/20.20.2/linux/x64/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/addon-build/release/install-root/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/addon-build/default/install-root/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/lib/binding/node-v115-linux-x64/node_sqlite3.node
...
db sources with sequelize with sequelize &gt;=4 (5.22.5) sequelize &#34;before each&#34; hook for &#34;Should have SQL_INJECTION using the first row of the result&#34; from using query method   View in Datadog
Could not locate the bindings file. Tried:
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/build/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/build/Release/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/out/Release/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/Release/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/build/default/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/compiled/20.20.2/linux/x64/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/addon-build/release/install-root/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/addon-build/default/install-root/node_sqlite3.node
 → /home/runner/work/dd-trace-js/dd-trace-js/versions/node_modules/sqlite3/lib/binding/node-v115-linux-x64/node_sqlite3.node
...
View all failed tests

AppSec | AppSec / integration (node-active)   View in Datadog   GitHub Actions

🔧 Fix in code. This looks caused by changes in this PR. Build failed due to unresolved dependencies: Could not resolve '../../../dd-trace/src/opentelemetry/time'.

AppSec | AppSec / integration (node-latest)   View in Datadog   GitHub Actions

🔧 Fix in code. This looks caused by changes in this PR. Build failed: Could not resolve '../../../dd-trace/src/opentelemetry/time' in iast/index.js.

View all 22 failed jobs.

📋 Copy prompt for your agent
CI on my pull request is failing. Help me find and fix the root cause of each failing job below — they were flagged as caused by changes in this PR, so focus on the diff. For each job, explain the failure and propose a fix.

Branch: ishara/otel-azure-orchestration-spans

AppSec | AppSec / integration (node-active)
Commit: 39eb383e04eb12a59a591c0c9979aa3fc9eb934f
Error (code / build):
Build failed due to unresolved dependencies: Could not resolve '../../../dd-trace/src/opentelemetry/time'.
CI job: https://github.com/DataDog/dd-trace-js/actions/runs/31634078454/job/94241613925

AppSec | AppSec / integration (node-latest)
Commit: 39eb383e04eb12a59a591c0c9979aa3fc9eb934f
Error (code / build):
Build failed: Could not resolve '../../../dd-trace/src/opentelemetry/time' in iast/index.js.
CI job: https://github.com/DataDog/dd-trace-js/actions/runs/31634078454/job/94241613970

Plus 15 more failing jobs not shown here.

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

🔄 Datadog retried 1 test - 1 passed on retry View in Datadog

🔄 Datadog auto-retried 10 jobs - 7 passed on retry View in Datadog

🎯 Code Coverage (details)
Patch Coverage: 83.33%
Overall Coverage: 96.50% (-2.06%)

Useful? React with 👍 / 👎

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

@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: ad72846cff

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

try {
// Provided by the Azure Functions host, so it is never a tracer dependency.
// eslint-disable-next-line n/no-missing-require
const { TableClient } = require('@azure/data-tables')

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 Require a bundled table client for cross-worker storage

When the app has AzureWebJobsStorage but has not installed @azure/data-tables, this require throws and getTableClient() permanently returns null. Since dd-trace does not declare that package (I only find this dynamic require in the repo), the Azure Table leg of the shared store is disabled for ordinary Durable Functions apps, leaving only per-worker tmp/cache and breaking the cross-worker parent resolution this change is meant to provide.

Useful? React with 👍 / 👎.


function ensureOrchestrationMeta (instanceId, invocationContext, functionName) {
const traceContext = invocationContext?.traceContext
let meta = readOrchestrationSpanMetaSync(instanceId, traceContext)

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 Read the shared table before replacing seeded meta

When startNew runs on worker A and the orchestration first executes on worker B, the HTTP-seeded identity is only in Azure Table. This synchronous lookup checks only cache/file/tracestate, so worker B creates and publishes a fresh orchestration span ID/parent, often overwriting the seeded row; the exported orchestration span and subsequent activities no longer connect to the HTTP span.

Useful? React with 👍 / 👎.

Comment on lines +48 to +49
const { readOrchestrationSpanMetaSync } = require('./otel-orchestration-store')
const meta = readOrchestrationSpanMetaSync(instanceId, traceContext)

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 Resolve table-backed parents for sync activities

For durable activity handlers that are not AsyncFunction, wrapSyncWithTraceContext comes through this path, which only calls readOrchestrationSpanMetaSync. If the activity lands on a different worker and the orchestration metadata only exists in Azure Table, the span falls back to the Azure-internal traceparent instead of the orchestration span, so sync activities remain disconnected while async ones work.

Useful? React with 👍 / 👎.

function writeMetaFileSync (instanceId, meta) {
const directory = getStoreDirectory()
fs.mkdirSync(directory, { recursive: true })
fs.writeFileSync(getMetaFilePath(instanceId), JSON.stringify(meta))

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 Isolate local metadata write failures from handlers

This write runs synchronously from startNew and orchestration setup/completion; if the temp store is unwritable/full or a caller-supplied instance ID produces an invalid path, the fs exception propagates out of the instrumentation and fails the user's function even though losing this cache should only degrade tracing. Catch/log and continue around the local store write.

Useful? React with 👍 / 👎.

Comment on lines +26 to +27
httpParentByInstance.set(key, normalized)
pendingHttpParentByTraceId.set(normalized.traceId, normalized)

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 Evict orchestration parent maps after use

Every successful startNew adds entries to these module-level maps, but there is no delete path when the instance is seeded, completed, or evicted. In long-lived Azure Functions workers that start many orchestrations, these maps retain one metadata object per instance/trace indefinitely, so tracer memory grows with total historical orchestrations rather than active work.

Useful? React with 👍 / 👎.

Comment on lines +281 to +282
META_CACHE.delete(instanceId)
deleteMetaFileSync(instanceId)

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 Delete completed metadata from Azure Table

After completion this only clears the process cache and temp file, leaving the Azure Table row written by publishOrchestrationMetaSync() behind. In apps that purge and reuse custom/singleton instance IDs, another worker can later read the stale completed row from readOrchestrationSpanMetaAsync() and parent a new run's activities to the old span; high-volume apps also accumulate one extra table row per orchestration indefinitely.

Useful? React with 👍 / 👎.

Comment on lines +123 to +124
ensureTable()
.then(table => table.upsertEntity({

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 Wait for the shared-store write before returning

The Azure Table upsert is detached from the HTTP startNew path, so the starter can return (and be frozen on a serverless plan) before the cross-worker row is written. If the orchestration is picked up by another worker in that window, or the process freezes before the promise runs, the worker cannot find the HTTP-seeded parent and creates a different orchestration identity; make the seed path await the shared-store persistence before startNew resolves.

Useful? React with 👍 / 👎.

Comment on lines +39 to +40
function getMetaFilePath (instanceId) {
return path.join(getStoreDirectory(), `${instanceId}.json`)

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 Sanitize instance IDs before building local paths

Durable custom instance IDs may be user-specified strings, and this uses them directly in path.join(). An ID containing path separators or .. can make the tracer write and later delete JSON outside dd-orchestration-spans (for example under another temp directory path), so encode or hash the ID before using it as a filename.

Useful? React with 👍 / 👎.

Comment on lines +125 to +126
partitionKey: TABLE_PARTITION_KEY,
rowKey: instanceId,

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 Scope stored metadata by task hub

Durable instance IDs are only unique within a task hub, but the shared table key uses a constant partition and only instanceId as the row key. When two task hubs or function apps share AzureWebJobsStorage and use the same custom/singleton ID, one orchestration's metadata can overwrite the other's and activities can be parented to the wrong trace; include the task hub/app scope in the key.

Useful? React with 👍 / 👎.

Comment on lines +90 to +91
if (instanceId) {
completeOrchestrationSpan(TRACER_NAME, instanceId, invocationContext, functionName)

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 Do not complete generator orchestrations on replay

This completion path now runs even when invocationContext.df.isReplaying was true at entry (only ensureOrchestrationMeta() is gated). A replay of an already-started orchestration that reaches the end can therefore export and clear the synthetic orchestration span before a non-replay completion, causing duplicate or missing parent metadata; keep the previous replay short-circuit or gate completion on non-replay terminal execution.

Useful? React with 👍 / 👎.

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.50%. Comparing base (806c888) to head (9fe549d).

Files with missing lines Patch % Lines
...og-instrumentations/src/azure-durable-functions.js 83.33% 2 Missing ⚠️
Additional details and impacted files
@@                             Coverage Diff                             @@
##           ishara/otel-azure-trace-context-linkage    #9794      +/-   ##
===========================================================================
- Coverage                                    98.56%   96.50%   -2.06%     
===========================================================================
  Files                                          973      970       -3     
  Lines                                       140870   140728     -142     
  Branches                                     12426    10051    -2375     
===========================================================================
- Hits                                        138847   135811    -3036     
- Misses                                        2023     4917    +2894     
Flag Coverage Δ
aiguard 57.49% <ø> (ø)
aiguard-integration 55.69% <ø> (ø)
apm-bucket-0 57.23% <ø> (ø)
apm-bucket-1 63.35% <ø> (ø)
apm-bucket-2 62.20% <ø> (ø)
apm-bucket-3 59.80% <ø> (ø)
apm-capabilities-tracing 62.46% <ø> (-0.05%) ⬇️
apm-integrations-aerospike 56.28% <ø> (ø)
apm-integrations-confluentinc-kafka-javascript 61.16% <ø> (ø)
apm-integrations-couchbase 56.71% <ø> (ø)
apm-integrations-http 61.89% <ø> (ø)
apm-integrations-kafkajs ?
apm-integrations-next 59.40% <ø> (ø)
apm-integrations-prisma ?
appsec 72.04% <ø> (-0.07%) ⬇️
appsec-express_fastify_graphql 69.41% <ø> (ø)
appsec-integration ?
appsec-kafka_ldapjs_lodash 63.40% <ø> (ø)
appsec-mongodb-core_mongoose_mysql ?
appsec-mongodb-core_mongoose_node-serialize 64.68% <ø> (?)
appsec-next 56.66% <ø> (ø)
appsec-node-serialize_passport_postgres ?
appsec-passport_postgres_sourcing 66.29% <ø> (?)
appsec-sourcing_stripe_template ?
appsec-stripe_template 63.13% <ø> (?)
debugger 64.21% <ø> (-0.04%) ⬇️
instrumentations-bucket-0 51.68% <ø> (ø)
instrumentations-bucket-1 59.65% <ø> (ø)
instrumentations-bucket-10 60.88% <ø> (ø)
instrumentations-bucket-11 61.54% <ø> (ø)
instrumentations-bucket-12 51.59% <ø> (ø)
instrumentations-bucket-13 52.43% <ø> (ø)
instrumentations-bucket-14 51.70% <ø> (ø)
instrumentations-bucket-2 52.91% <ø> (ø)
instrumentations-bucket-3 53.57% <ø> (ø)
instrumentations-bucket-4 58.72% <ø> (ø)
instrumentations-bucket-5 49.41% <ø> (ø)
instrumentations-bucket-6 60.27% <ø> (ø)
instrumentations-bucket-7 51.88% <ø> (ø)
instrumentations-bucket-8 58.40% <ø> (+<0.01%) ⬆️
instrumentations-bucket-9 57.25% <ø> (ø)
instrumentations-instrumentation-couchbase 50.94% <ø> (ø)
instrumentations-integration-esbuild ?
llmobs-ai_anthropic_bedrock 62.86% <ø> (ø)
llmobs-bucket-1 61.34% <ø> (ø)
llmobs-openai 61.74% <ø> (ø)
llmobs-openai-agents_vertex-ai 60.02% <ø> (-0.01%) ⬇️
llmobs-sdk 66.77% <ø> (ø)
master-coverage ?
openfeature 55.68% <ø> (ø)
openfeature-unit 53.20% <ø> (ø)
platform-core_esbuild_instrumentations-misc 41.22% <58.33%> (+<0.01%) ⬆️
platform-integration 60.42% <ø> (ø)
platform-shimmer_unit-guardrails_webpack 38.89% <58.33%> (+<0.01%) ⬆️
plugins-bucket-0 56.93% <ø> (ø)
plugins-bucket-1 54.03% <ø> (ø)
plugins-bucket-11 61.34% <ø> (-0.14%) ⬇️
plugins-bucket-17 61.45% <ø> (+0.16%) ⬆️
plugins-bucket-18 59.72% <ø> (-2.20%) ⬇️
plugins-bucket-19 61.64% <ø> (+0.32%) ⬆️
plugins-bucket-20 ?
plugins-bucket-4 58.31% <ø> (ø)
plugins-bullmq_cassandra_cookie 61.37% <ø> (ø)
plugins-cookie-parser_crypto_dd-trace-api 56.36% <ø> (ø)
plugins-fetch_fs_generic-pool 58.22% <ø> (ø)
plugins-google-cloud-pubsub_grpc_handlebars 64.15% <ø> (+<0.01%) ⬆️
plugins-hapi_hono_ioredis 59.90% <ø> (ø)
plugins-knex_langgraph_ldapjs ?
plugins-langgraph_ldapjs_light-my-request 57.87% <ø> (?)
plugins-light-my-request_limitd-client_lodash ?
plugins-limitd-client_lodash_mariadb 57.58% <ø> (?)
plugins-mariadb_memcached_mercurius ?
plugins-memcached_mercurius_microgateway-core 61.00% <ø> (?)
plugins-mongodb_mongodb-core_mongoose ?
plugins-mongoose_multer_mysql 59.23% <ø> (?)
plugins-multer_mysql_mysql2 ?
plugins-mysql2_nats_node-serialize 60.90% <ø> (?)
plugins-nats_node-serialize_opensearch ?
plugins-opensearch_passport-http_pino 59.13% <ø> (?)
plugins-passport-http_pino_postgres ?
plugins-postgres_process_pug 58.27% <ø> (?)
plugins-process_pug_redis ?
plugins-redis_router_sequelize 61.51% <ø> (?)
plugins-test-and-upstream-rhea_undici_url 61.07% <ø> (?)
plugins-undici_url_valkey ?
plugins-valkey_vm_winston 57.64% <ø> (?)
plugins-vm_winston_ws ?
plugins-ws 59.26% <ø> (?)
profiling 61.51% <ø> (ø)
serverless-aws-sdk-aws-sdk 55.13% <ø> (ø)
serverless-aws-sdk-base-inject-field 50.91% <ø> (ø)
serverless-aws-sdk-bedrockruntime 54.67% <ø> (ø)
serverless-aws-sdk-client 56.23% <ø> (ø)
serverless-aws-sdk-dynamodb 55.50% <ø> (ø)
serverless-aws-sdk-eventbridge 49.71% <ø> (ø)
serverless-aws-sdk-kinesis 59.08% <ø> (ø)
serverless-aws-sdk-lambda 57.24% <ø> (ø)
serverless-aws-sdk-s3 55.60% <ø> (ø)
serverless-aws-sdk-serverless-peer-service 59.34% <ø> (ø)
serverless-aws-sdk-sns 59.89% <ø> (ø)
serverless-aws-sdk-sqs 60.33% <ø> (+0.02%) ⬆️
serverless-aws-sdk-stepfunctions 55.43% <ø> (ø)
serverless-aws-sdk-util 51.44% <ø> (ø)
serverless-azure-functions-servicebus_lambda 58.72% <ø> (?)
serverless-bucket-0 54.10% <83.33%> (+<0.01%) ⬆️
serverless-bucket-1 ?
test-optimization-cucumber 64.45% <ø> (-6.76%) ⬇️
test-optimization-cypress 64.68% <ø> (-0.37%) ⬇️
test-optimization-jest 71.38% <ø> (-1.17%) ⬇️
test-optimization-mocha 72.11% <ø> (-0.11%) ⬇️
test-optimization-playwright-playwright-atr 59.90% <ø> (ø)
test-optimization-playwright-playwright-efd 59.85% <ø> (-0.22%) ⬇️
test-optimization-playwright-playwright-final-status 60.22% <ø> (ø)
test-optimization-playwright-playwright-impacted-tests 59.59% <ø> (-0.18%) ⬇️
test-optimization-playwright-playwright-reporting 60.96% <ø> (-0.13%) ⬇️
test-optimization-playwright-playwright-test-management 60.45% <ø> (-0.30%) ⬇️
test-optimization-playwright-playwright-test-span 59.91% <ø> (-0.05%) ⬇️
test-optimization-selenium 59.15% <ø> (ø)
test-optimization-testopt ?
test-optimization-vitest 72.01% <ø> (-1.28%) ⬇️
test-optimization-vitest-browser 59.01% <ø> (ø)
test-optimization-webdriverio ?

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.

@chemystery09
chemystery09 marked this pull request as draft August 12, 2026 18:36
chemystery09 and others added 2 commits August 12, 2026 15:36
…rents async

Stamp orchestration start time on the first non-replay turn instead of at
startNew, export one backfilled span for the full instance window, and wrap
all durable activities with async parent resolution so sync handlers on other
workers read the shared orchestration store.

Co-authored-by: Cursor <cursoragent@cursor.com>
…vity times

The prior first-turn stamp could run after replay resumed, which left activity
spans starting before their orchestration parent in the waterfall. Seed
startTime at HTTP startNew, record the earliest activity start in the shared
store, and clamp export bounds to that window.

Co-authored-by: Cursor <cursoragent@cursor.com>
chemystery09 added a commit that referenced this pull request Aug 12, 2026
Add unit tests for stampOrchestrationStartTime and
resolveOrchestrationSpanBounds used by the backfilled orchestration span
export path in #9794.

Co-authored-by: Cursor <cursoragent@cursor.com>
…t bounds

Always record the HTTP instance start at startNew (using the active span
start time when available), track earliest activity starts even before shared
meta exists, and merge both floors when exporting the backfilled orchestration
span so activities no longer precede their parent in the waterfall.

Co-authored-by: Cursor <cursoragent@cursor.com>
chemystery09 added a commit that referenced this pull request Aug 12, 2026
Add unit tests for stampOrchestrationStartTime and
resolveOrchestrationSpanBounds used by the backfilled orchestration span
export path in #9794.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant