Inject the current trace context into every job handed to the worker, using the per-job stdin spec as the carrier (mirrors how ImageDescription.Python puts _traceparent in the message dict):
In the spec built for the worker (SubprocessArtPipeStageExecutor ~line 61, and the resident path via ServeWorkerProcess/ResidentArtPipeStageExecutor), add ["_traceparent"] = Activity.Current?.Id (+ _tracestate when present).
Also export TRACEPARENT in ApplyWorkerEnvironment as a belt-and-suspenders carrier for tools that read env.
Per-job, not per-process: the resident serve worker (#368) is long-lived and serves many jobs — the traceparent must be set on each job line, not once at process spawn.
Add a per-stage child span in the executor around the actual worker call (child of the ProcessArtAssetStage consumer span), tagged with asset_id, stage, stage_run_id, job_id, model backend, and executor mode (subprocess/resident). Today the subprocess call runs inside the consumer span with no dedicated child — this gives the stage its own timed span even before art_pipe reports internal spans.
Notes / traps
Guard for Activity.Current == null (BypassGpuLease/fake-executor/dev paths) — emit the job without a traceparent rather than throwing.
Keep the span open across the async worker round-trip; close on the result contract (success/failure) with ActivityStatusCode.
Acceptance
Worker job spec + subprocess env carry a valid W3C traceparent for every stage in both executor modes.
Jaeger shows a per-stage child span under ProcessArtAssetStage.
Unit test asserts the spec/env carry Activity.Current.Id when an activity is active, and omit it cleanly when none is.
Part of #428. **First workstream — self-contained, backend-mergeable, and a no-op until #2 (art_pipe OTel) consumes it, so it can land immediately.**
## Scope (spikersoft-backend / SpikerSoft.EventHandlers.ArtPipeProcessor)
1. **Inject the current trace context into every job** handed to the worker, using the per-job stdin spec as the carrier (mirrors how ImageDescription.Python puts `_traceparent` in the message dict):
- In the spec built for the worker (`SubprocessArtPipeStageExecutor` ~line 61, and the resident path via `ServeWorkerProcess`/`ResidentArtPipeStageExecutor`), add `["_traceparent"] = Activity.Current?.Id` (+ `_tracestate` when present).
- Also export `TRACEPARENT` in `ApplyWorkerEnvironment` as a belt-and-suspenders carrier for tools that read env.
- **Per-job, not per-process:** the resident serve worker (#368) is long-lived and serves many jobs — the traceparent must be set on each job line, not once at process spawn.
2. **Add a per-stage child span** in the executor around the actual worker call (child of the `ProcessArtAssetStage` consumer span), tagged with `asset_id`, `stage`, `stage_run_id`, `job_id`, model backend, and executor mode (subprocess/resident). Today the subprocess call runs inside the consumer span with no dedicated child — this gives the stage its own timed span even before art_pipe reports internal spans.
## Notes / traps
- Guard for `Activity.Current == null` (BypassGpuLease/fake-executor/dev paths) — emit the job without a traceparent rather than throwing.
- Keep the span open across the async worker round-trip; close on the result contract (success/failure) with `ActivityStatusCode`.
## Acceptance
- Worker job spec + subprocess env carry a valid W3C `traceparent` for every stage in both executor modes.
- Jaeger shows a per-stage child span under `ProcessArtAssetStage`.
- Unit test asserts the spec/env carry `Activity.Current.Id` when an activity is active, and omit it cleanly when none is.
Refs #428, #368.
Resolved in spikersoft-backend PR #109 (merged to master). Added WorkerTraceContext.Inject, stamping the active W3C traceparent/tracestate onto the per-job worker spec in both executor modes (subprocess spec + resident per-job request). Per-job payload chosen over an env var because the resident serve worker multiplexes many jobs over one process. 3/3 unit tests pass; SpikerSoft.Tests.Unit builds clean. Inert until #430 consumes the context. Closing — next: #430 (art_pipe OTel spans).
Resolved in spikersoft-backend PR #109 (merged to `master`). Added `WorkerTraceContext.Inject`, stamping the active W3C `traceparent`/`tracestate` onto the per-job worker spec in both executor modes (subprocess spec + resident per-job request). Per-job payload chosen over an env var because the resident serve worker multiplexes many jobs over one process. 3/3 unit tests pass; `SpikerSoft.Tests.Unit` builds clean. Inert until #430 consumes the context. Closing — next: #430 (art_pipe OTel spans).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of #428. First workstream — self-contained, backend-mergeable, and a no-op until #2 (art_pipe OTel) consumes it, so it can land immediately.
Scope (spikersoft-backend / SpikerSoft.EventHandlers.ArtPipeProcessor)
_traceparentin the message dict):SubprocessArtPipeStageExecutor~line 61, and the resident path viaServeWorkerProcess/ResidentArtPipeStageExecutor), add["_traceparent"] = Activity.Current?.Id(+_tracestatewhen present).TRACEPARENTinApplyWorkerEnvironmentas a belt-and-suspenders carrier for tools that read env.ProcessArtAssetStageconsumer span), tagged withasset_id,stage,stage_run_id,job_id, model backend, and executor mode (subprocess/resident). Today the subprocess call runs inside the consumer span with no dedicated child — this gives the stage its own timed span even before art_pipe reports internal spans.Notes / traps
Activity.Current == null(BypassGpuLease/fake-executor/dev paths) — emit the job without a traceparent rather than throwing.ActivityStatusCode.Acceptance
traceparentfor every stage in both executor modes.ProcessArtAssetStage.Activity.Current.Idwhen an activity is active, and omit it cleanly when none is.Refs #428, #368.
Resolved in spikersoft-backend PR #109 (merged to
master). AddedWorkerTraceContext.Inject, stamping the active W3Ctraceparent/tracestateonto the per-job worker spec in both executor modes (subprocess spec + resident per-job request). Per-job payload chosen over an env var because the resident serve worker multiplexes many jobs over one process. 3/3 unit tests pass;SpikerSoft.Tests.Unitbuilds clean. Inert until #430 consumes the context. Closing — next: #430 (art_pipe OTel spans).