Skip to main content

Event

Enum Event 

Source
#[non_exhaustive]
pub enum Event<'a> { Admitted { queue: &'a str, count: usize, }, Rejected { queue: &'a str, policy: &'a str, count: usize, }, Completed { kind: &'a str, ms: u64, }, Quarantined { fingerprint: &'a str, crashes: u32, }, Evicted { queue: &'a str, count: u64, }, JobSpan { job_id: &'a str, kind: &'a str, queue: &'a str, attempt: u32, outcome: &'a str, started_at_ms: i64, ms: u64, trace: Option<&'a TraceContext>, }, WorkerSaturation { worker: &'a str, inflight: u32, capacity: u32, utilization: f64, empty_poll_ratio: f64, polls: u64, empty_polls: u64, }, WorkerMemory { worker: &'a str, used_bytes: u64, limit_bytes: u64, restart_requested: bool, }, }
Expand description

Events emitted through the telemetry facade.

#[non_exhaustive] lets the facade grow without breaking exhaustive downstream matches. Job spans and worker-saturation gauges were both additive signals, and without this attribute every such addition is a breaking change for anyone who wrote an exhaustive match in their bridge. That is the wrong incentive: it makes “do not emit the signal” the cheap option. Adding a variant is now additive; changing an existing variant’s fields still is not, which is why the two additions below are new variants rather than new fields on Completed.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Admitted

Fields

§queue: &'a str
§count: usize
§

Rejected

Fields

§queue: &'a str
§policy: &'a str
§count: usize
§

Completed

Fields

§kind: &'a str
§ms: u64
§

Quarantined

Fields

§fingerprint: &'a str
§crashes: u32
§

Evicted

Eviction is always observable through both this event and a counter.

Fields

§queue: &'a str
§count: u64
§

JobSpan

Emitted exactly once per attempt after the handler returns, carrying everything an OTel-bridged deployment needs to build one span: identity, outcome, and — the point of the addition — the traceparent the PRODUCER put on the envelope, already parsed.

It fires at the END and carries started_at_ms + ms rather than firing at the start, because a facade has no span object to hand back: a start-only callback would force every bridge to keep its own job-id→span map and to leak one whenever a worker is killed mid-attempt. An OTel span builder takes explicit start and end timestamps, so one event is enough and nothing has to be remembered.

trace is None when the envelope carried no traceparent OR carried an invalid one — see parse_traceparent. A bridge then starts a root span.

Fields

§job_id: &'a str
§kind: &'a str
§queue: &'a str
§attempt: u32
§outcome: &'a str

success | retry | skip | revoke | snooze | undecodable | rate_limited — the Outcome the runtime acked (or would have).

§started_at_ms: i64
§ms: u64
§

WorkerSaturation

Worker-saturation gauges emitted by the runner on every heartbeat, alongside the registry upsert that already happens — so the same numbers reach a metrics exporter and GET /cluster from one place and cannot disagree. This is a SIGNAL, not an autoscaler: headgate never sizes a fleet, it only publishes the two numbers that decide the direction.

  • utilization = inflight / capacity — scale UP when it is high AND the backlog’s time-to-drain is growing (backlog metrics).
  • empty_poll_ratio = admits that returned zero / total admits, over the runner’s rolling window — scale DOWN when it is high: the fleet is asking for work that is not there.

Its own variant rather than fields on Admitted for the reason in the type’s doc: Admitted is per-admission and these are per-worker levels.

Fields

§worker: &'a str
§inflight: u32
§capacity: u32
§utilization: f64
§empty_poll_ratio: f64
§polls: u64

Window totals behind the ratio, so an exporter can publish counters too.

§empty_polls: u64
§

WorkerMemory

Process-memory sample emitted by the worker guard. restart_requested is true only for the threshold-crossing sample that starts graceful shutdown.

Fields

§worker: &'a str
§used_bytes: u64
§limit_bytes: u64
§restart_requested: bool

Auto Trait Implementations§

§

impl<'a> Freeze for Event<'a>

§

impl<'a> RefUnwindSafe for Event<'a>

§

impl<'a> Send for Event<'a>

§

impl<'a> Sync for Event<'a>

§

impl<'a> Unpin for Event<'a>

§

impl<'a> UnsafeUnpin for Event<'a>

§

impl<'a> UnwindSafe for Event<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.