Scope executor spans to operations and link handed-off work - #3724
Merged
Conversation
… with named targets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
otel.kindon entry-point, producer and consumer spans.RUST_LOG-style filter underGOLEM_OTLP_FILTER, with stable target names for the two high-volume sources.worker_admission_wait_seconds.Trace
126019611fb73a83e301cd611cb13505showedget_or_create_workerrunning for 3m26s inside a 1.76s gRPC call. Spans modelled worker and loop lifetime rather than operations, so they stayed open for as long as the worker was resident, reported durations unrelated to any request, and accumulated an OpenTelemetry event for everytracingevent recorded inside them.tracing-opentelemetryholds those events until the span closes, and the SDK appliesmax_events_per_spanonly at close, keeping the first N — so a span that never closed retained everything and exported none of it. Executor RSS reached 11 GB, and the resulting OOMs failed worker admission.Behavior
Every span now covers one bounded operation. Background loops — the scheduler, quota renewal, resource-limit batching, agent status flushing, oplog transfer and forwarding — span each tick rather than the loop, so a span always closes and its events are bounded by one iteration. Worker residency and the invocation loop have no span at all; the phases inside them span themselves. A worker's admission waits are spanned one at a time, and each records its duration to
worker_admission_wait_seconds, labelled by phase.Work that is handed off is related to its originator by a link, never by parent-child nesting. This includes the synchronous invoke-and-await path: the caller enqueues an invocation and waits on a published event rather than a return, and the work continues if the caller goes away, so the caller does not contain it in time. Nesting there reported children outliving their parents. The caller keeps its own span for the time it spends waiting, and the execution is the root of its own trace, linked back to the producer span.
otel.kindisserveron gRPC and HTTP entry points, andproducer/consumeron the enqueue and pickup pair, following the OpenTelemetry messaging conventions. A request abandoned by its caller is markedcancelledrather than failed.Origins are carried as captured span contexts rather than
tracing::Spanhandles, so remembering where an invocation came from no longer holds a span open until it completes.GOLEM_OTLP_FILTERsets the OTLP layer's filter inRUST_LOGsyntax, and is used exactly as written — nothing is merged into it, soinfomeans info everywhere including third-party crates, and quietening a crate is the deployment's judgement to make. Unset meansoff: exporting already requiresGOLEM__TRACING__OTLP__ENABLED,__HOSTand__PORT, and this is the remaining switch. Levels belowinfoexport nothing, because the spans bounding an operation areinfoand an error reaches a trace as an event on a span rather than as a span of its own.GOLEM_OTLP_LOGis still honoured, with a warning naming the replacement. The filter in force, and the variable it came from, are logged at startup.Two sources whose volume is decided outside the executor have stable target names, so they can be tuned without naming a Rust module path:
golem::plugin_logfor log output from oplog-processor plugin agents, andgolem::agent_rdbmsfor SQL an agent runs against its own database. Everything else keeps its module's target, so ordinaryRUST_LOGconventions apply.Scheduler storage operations retry transient failures according to
scheduler.storage_retry, and a failed acknowledgement aborts the remaining claimed actions rather than being ignored.Notes
debugwith a set of directives merged in, and now exports atinfo.