The new Art Studio backend pipeline (CQRS submit → RabbitMQ → ArtPipeProcessor consumer → orchestrator → art_pipe subprocess) does not yet give us the same level of debuggability as the original workers. When a stage is slow or fails, we can't easily answer, from Jaeger/Seq alone:
which container picked up the message and ran the stage,
when/where it went through RabbitMQ and when a consumer took it in,
what happened and how long each step took (queue/GPU wait vs. the art_pipe subprocess vs. artifact persistence + safety gate),
and pivot across the C# ↔ Python boundary via correlation ids.
The consumer already starts a W3C-correlated ProcessArtAssetStage span (per the telemetry-correlation rule), but the orchestrator emits no per-step spans and its Seq log lines don't all carry the asset/stage/run/correlation ids, so a single failing run is hard to isolate.
Scope (this ticket — backend, no cross-repo/cross-cutting decision)
P2 — per-step Jaeger spans under the existing consumer span (reusing the already-registered SpikerSoft.EventHandlers.ArtPipeProcessor ActivitySource, zero tracer-config change):
artpipe.gpu.lease — the GPU/queue wait bucket,
artpipe.stage.execute — end-to-end executing stage (tags: asset id, stage, model, action, run id), with error status set on failure paths,
artpipe.worker.execute — the art_pipe subprocess itself,
P3 — correlated Seq logs: push AssetId / Stage / StageRunId / CorrelationId into the Serilog LogContext around the orchestrator dispatch so every downstream log line is filterable (TraceId is already enriched from the active Activity; ServiceName/DeploymentName/MachineName already answer "which container"). Add ProcessingTimeMs to the two stage-completion log lines.
Out of scope (tracked separately — each needs a decision or another repo)
P1 — port the OTLP + _traceparent consumer-span pattern from image_description_service.py into art_pipe's worker.py (separate art_pipe repo, adds opentelemetry dep) — the biggest single win for true cross-language traces; the C# side already injects _traceparent via WorkerTraceContext.Inject.
P4 — register the dropped SpikerSoft.MessageBus / SpikerSoft.Api ActivitySources with the tracer (global span volume).
P5 — per-stack Deployment__Name differentiation in the infra stack files (mostly covered already by the existing DeploymentName/MachineName/ServiceName Serilog enrichers).
Part of the ProArt Art Studio epic (#346); follows the telemetry-correlation conventions (Jaeger:EndPoint, ActivityHelper, jaeger/seq-attachable overlays).
## Problem
The new Art Studio backend pipeline (CQRS submit → RabbitMQ → `ArtPipeProcessor` consumer → orchestrator → art_pipe subprocess) does not yet give us the same level of debuggability as the original workers. When a stage is slow or fails, we can't easily answer, from Jaeger/Seq alone:
- **which container** picked up the message and ran the stage,
- **when/where** it went through RabbitMQ and when a consumer took it in,
- **what happened and how long** each step took (queue/GPU wait vs. the art_pipe subprocess vs. artifact persistence + safety gate),
- and pivot across the **C# ↔ Python** boundary via correlation ids.
The consumer already starts a W3C-correlated `ProcessArtAssetStage` span (per the `telemetry-correlation` rule), but the orchestrator emits no per-step spans and its Seq log lines don't all carry the asset/stage/run/correlation ids, so a single failing run is hard to isolate.
## Scope (this ticket — backend, no cross-repo/cross-cutting decision)
Bounded, verifiable, decision-free slice inside `SpikerSoft.EventHandlers.ArtPipeProcessor`:
- **P2 — per-step Jaeger spans** under the existing consumer span (reusing the already-registered `SpikerSoft.EventHandlers.ArtPipeProcessor` ActivitySource, zero tracer-config change):
- `artpipe.gpu.lease` — the GPU/queue wait bucket,
- `artpipe.stage.execute` — end-to-end executing stage (tags: asset id, stage, model, action, run id), with error status set on failure paths,
- `artpipe.worker.execute` — the art_pipe subprocess itself,
- `artpipe.outputs.persist` — GridFS upload + output-side safety gate.
- **P3 — correlated Seq logs**: push `AssetId` / `Stage` / `StageRunId` / `CorrelationId` into the Serilog `LogContext` around the orchestrator dispatch so **every** downstream log line is filterable (TraceId is already enriched from the active Activity; `ServiceName`/`DeploymentName`/`MachineName` already answer "which container"). Add `ProcessingTimeMs` to the two stage-completion log lines.
## Out of scope (tracked separately — each needs a decision or another repo)
- **P1** — port the OTLP + `_traceparent` consumer-span pattern from `image_description_service.py` into `art_pipe`'s `worker.py` (separate `art_pipe` repo, adds `opentelemetry` dep) — the biggest single win for true cross-language traces; the C# side already injects `_traceparent` via `WorkerTraceContext.Inject`.
- **P4** — register the dropped `SpikerSoft.MessageBus` / `SpikerSoft.Api` ActivitySources with the tracer (global span volume).
- **P5** — per-stack `Deployment__Name` differentiation in the infra stack files (mostly covered already by the existing `DeploymentName`/`MachineName`/`ServiceName` Serilog enrichers).
Part of the ProArt Art Studio epic (#346); follows the `telemetry-correlation` conventions (`Jaeger:EndPoint`, `ActivityHelper`, `jaeger`/`seq-attachable` overlays).
P2 + P3 (the backend, decision-free slice) opened for review as spikersoft-backend PR #182 (feat/artpipe-worker-observability-457 → master), awaiting merge.
Per-step Jaeger spans (artpipe.gpu.lease / stage.execute / worker.execute / outputs.persist) nested under the existing consumer span via the already-registered ActivitySource — zero tracer-config change.
AssetId/Stage/StageRunId/CorrelationId pushed into the Serilog LogContext so every orchestrator log line is filterable in Seq; {ProcessingTimeMs} added to the two completion logs.
Build clean, 209 ArtPipe unit tests pass.
P1 (art_pipe worker.py OTLP for true C#↔Python spans), P4 (MessageBus/Api ActivitySource registration), and P5 (per-stack Deployment name) remain open here — each needs a decision or the art_pipe/infrastructure repo. Will close this ticket once #182 merges and note the residual P1/P4/P5 as follow-ups.
P2 + P3 (the backend, decision-free slice) opened for review as **spikersoft-backend PR #182** (`feat/artpipe-worker-observability-457` → `master`), awaiting merge.
- Per-step Jaeger spans (`artpipe.gpu.lease` / `stage.execute` / `worker.execute` / `outputs.persist`) nested under the existing consumer span via the already-registered ActivitySource — zero tracer-config change.
- `AssetId`/`Stage`/`StageRunId`/`CorrelationId` pushed into the Serilog `LogContext` so every orchestrator log line is filterable in Seq; `{ProcessingTimeMs}` added to the two completion logs.
- Build clean, 209 ArtPipe unit tests pass.
P1 (art_pipe `worker.py` OTLP for true C#↔Python spans), P4 (MessageBus/Api ActivitySource registration), and P5 (per-stack Deployment name) remain open here — each needs a decision or the `art_pipe`/infrastructure repo. Will close this ticket once #182 merges and note the residual P1/P4/P5 as follow-ups.
Resolved by spikersoft-backend PR #182 (merged to master, HEAD 1638bf0). The P2 per-step Jaeger spans and P3 correlated Seq logs + ProcessingTimeMs are in — the new Art Studio stage worker now has span-level "how long / where / what happened" and asset/stage/run/correlation-id filtering, nesting under the existing consumer span. Build clean, 209 ArtPipe unit tests pass.
The remaining P1 (art_pipe worker.py OTLP for true C#↔Python spans), P4 (MessageBus/Api ActivitySource registration), and P5 (per-stack Deployment name) are decision-gated / cross-repo and moved to #458. Closing.
Resolved by spikersoft-backend **PR #182** (merged to `master`, HEAD `1638bf0`). The P2 per-step Jaeger spans and P3 correlated Seq logs + `ProcessingTimeMs` are in — the new Art Studio stage worker now has span-level "how long / where / what happened" and asset/stage/run/correlation-id filtering, nesting under the existing consumer span. Build clean, 209 ArtPipe unit tests pass.
The remaining P1 (art_pipe `worker.py` OTLP for true C#↔Python spans), P4 (MessageBus/Api ActivitySource registration), and P5 (per-stack Deployment name) are decision-gated / cross-repo and moved to **#458**. Closing.
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.
Problem
The new Art Studio backend pipeline (CQRS submit → RabbitMQ →
ArtPipeProcessorconsumer → orchestrator → art_pipe subprocess) does not yet give us the same level of debuggability as the original workers. When a stage is slow or fails, we can't easily answer, from Jaeger/Seq alone:The consumer already starts a W3C-correlated
ProcessArtAssetStagespan (per thetelemetry-correlationrule), but the orchestrator emits no per-step spans and its Seq log lines don't all carry the asset/stage/run/correlation ids, so a single failing run is hard to isolate.Scope (this ticket — backend, no cross-repo/cross-cutting decision)
Bounded, verifiable, decision-free slice inside
SpikerSoft.EventHandlers.ArtPipeProcessor:SpikerSoft.EventHandlers.ArtPipeProcessorActivitySource, zero tracer-config change):artpipe.gpu.lease— the GPU/queue wait bucket,artpipe.stage.execute— end-to-end executing stage (tags: asset id, stage, model, action, run id), with error status set on failure paths,artpipe.worker.execute— the art_pipe subprocess itself,artpipe.outputs.persist— GridFS upload + output-side safety gate.AssetId/Stage/StageRunId/CorrelationIdinto the SerilogLogContextaround the orchestrator dispatch so every downstream log line is filterable (TraceId is already enriched from the active Activity;ServiceName/DeploymentName/MachineNamealready answer "which container"). AddProcessingTimeMsto the two stage-completion log lines.Out of scope (tracked separately — each needs a decision or another repo)
_traceparentconsumer-span pattern fromimage_description_service.pyintoart_pipe'sworker.py(separateart_piperepo, addsopentelemetrydep) — the biggest single win for true cross-language traces; the C# side already injects_traceparentviaWorkerTraceContext.Inject.SpikerSoft.MessageBus/SpikerSoft.ApiActivitySources with the tracer (global span volume).Deployment__Namedifferentiation in the infra stack files (mostly covered already by the existingDeploymentName/MachineName/ServiceNameSerilog enrichers).Part of the ProArt Art Studio epic (#346); follows the
telemetry-correlationconventions (Jaeger:EndPoint,ActivityHelper,jaeger/seq-attachableoverlays).P2 + P3 (the backend, decision-free slice) opened for review as spikersoft-backend PR #182 (
feat/artpipe-worker-observability-457→master), awaiting merge.artpipe.gpu.lease/stage.execute/worker.execute/outputs.persist) nested under the existing consumer span via the already-registered ActivitySource — zero tracer-config change.AssetId/Stage/StageRunId/CorrelationIdpushed into the SerilogLogContextso every orchestrator log line is filterable in Seq;{ProcessingTimeMs}added to the two completion logs.P1 (art_pipe
worker.pyOTLP for true C#↔Python spans), P4 (MessageBus/Api ActivitySource registration), and P5 (per-stack Deployment name) remain open here — each needs a decision or theart_pipe/infrastructure repo. Will close this ticket once #182 merges and note the residual P1/P4/P5 as follow-ups.Resolved by spikersoft-backend PR #182 (merged to
master, HEAD1638bf0). The P2 per-step Jaeger spans and P3 correlated Seq logs +ProcessingTimeMsare in — the new Art Studio stage worker now has span-level "how long / where / what happened" and asset/stage/run/correlation-id filtering, nesting under the existing consumer span. Build clean, 209 ArtPipe unit tests pass.The remaining P1 (art_pipe
worker.pyOTLP for true C#↔Python spans), P4 (MessageBus/Api ActivitySource registration), and P5 (per-stack Deployment name) are decision-gated / cross-repo and moved to #458. Closing.