Skip to content

API reference · 05 of 8

Events and observation

The structured events a run emits, and the hooks that receive them.

Read from Cuprum 0.2.0-beta2 at a4089878

function

observe

cuprum/context/registration.py, the source of observe
def observe(hook: ExecHook) -> HookRegistration

Register a structured execution event hook in the current context.

Parameters

hook
Callable invoked with ExecEvent values as Cuprum executes commands and pipelines.

Returns

HookRegistration
A handle that can be detached or used as a context manager.
class

ExecEvent

cuprum/events.py, the source of ExecEvent
class ExecEvent(
    phase: ExecPhase,
    program: Program,
    argv: tuple[str, ...],
    cwd: Path | None,
    env: EnvOverlay | None,
    pid: int | None,
    timestamp: float,
    line: str | None,
    exit_code: int | None,
    duration_s: float | None,
    tags: cabc.Mapping[str, object],
    note: str | None = None,
    byte_count: int | None = None,
    operation: str | None = None,
    error_type: str | None = None,
    exec_id: ExecId | None = None,
    project: str | None = None,
    timeout_s: float | None = None,
    timeout_mode: TimeoutMode | None = None,
    stage_index: int | None = None,
    stage_count: int | None = None,
    eof_grace_s: float | None = None,
    pending_readers: int | None = None,
    max_rss_bytes: int | None = None,
    user_cpu_seconds: float | None = None,
    system_cpu_seconds: float | None = None,
    resource_usage_mode: ResourceUsageMode | None = None,
    env_mode: EnvMode | None = None,
    resolved_path: str | None = dc.field(default=None, kw_only=True),
    capture_mode: CaptureMode | None = dc.field(default=None, kw_only=True),
    owns_group: bool | None = dc.field(default=None, kw_only=True),
    error_category: StdioFailureCategory | None = dc.field(default=None, kw_only=True),
    group_outcome: GroupTeardownOutcome | None = dc.field(default=None, kw_only=True),
    settle_s: float | None = dc.field(default=None, kw_only=True),
    terminal_outcome: TerminalOutcome | None = None,
)

A structured execution event emitted by Cuprum.

Attributes

phase
Event phase. See ExecPhase. Both timeout and teardown_error are ancillary diagnostics that never displace a lifecycle phase. pipeline_fail_fast reports the pipeline coordinator's decision before the failing stage's own exit event. settled is the single definitive terminal event for every execution that emitted plan. It carries terminal_outcome, an optional pid, and exec_id. exit_code is a real child status only when one is available; it stays None for spawn failure and cancellation paths that do not produce a command result. The event never carries an exception payload. Catalogue lookup failures raised as UnknownProgramError in catalogue and allowlist failures from _enforce_allowlist happen before exec_id is minted and are outside this terminal-event contract. timeout marks a run that exceeded its deadline, and is emitted before the existing exit event and the public TimeoutExpired, both of which are preserved. teardown_error marks a stream consumer that drained with an unexpected error during cleanup. capture_eof_grace_expired marks a capturing drain whose bounded EOF grace elapsed while one or two readers remained pending. Neither ancillary diagnostic carries an ordering guarantee. Cleanup also runs on external cancellation and on an unexpected stdin-writer failure, and on those paths the original exception propagates unchanged: no exit event follows and no TimeoutExpired is raised, so an ancillary diagnostic may be the last event a consumer sees for that execution. stdio_error is the best-effort counterpart to stdin_error for the standard-stream boundaries that fail *outside* the stdin writer's own pipe operations: the caller's producer, an invalid chunk, the encoder, opening a cuprum-owned target file, and flushing a caller's borrowed file object. It is emitted where the failing boundary is known, and never in place of the caller-visible exception — a producer failure still raises StdinSourceError with the producer's own exception chained, and a failed owned-path open still raises the OSError _open_owned_path builds. It carries error_category rather than an exception message, because several of these boundaries raise the same exception type and the category is what separates them.
program
The allowlisted program that is executing.
argv
Full argv including program name as the first element. Empty for the sanitized pipeline_fail_fast decision event.
cwd
Working directory for the subprocess, when set. Absent from the sanitized pipeline_fail_fast decision event.
env
Environment overlay provided for this execution, when set. Absent from the sanitized pipeline_fail_fast decision event.
pid
Process identifier for the running subprocess, when reported. plan always carries None. A settled event can also carry None when startup failed before a process existed or cancellation ended the run before a result was available.
timestamp
Wall-clock timestamp (seconds since epoch) when the phase occurred.
line
Output line for stdout / stderr phases. Line terminators are omitted.
exit_code
Real child exit code for exit and, when available, settled phases, and the failing stage's exit code for pipeline_fail_fast. It is None when no child status is available, including spawn failure and cancellation paths that do not produce a command result.
duration_s
Elapsed duration in seconds from start to subprocess exit (not including output drain after process termination). For pipeline_fail_fast this is how long the failing stage ran before its completion was observed.
tags
Arbitrary, JSON-like metadata associated with this execution. Empty on the sanitized pipeline_fail_fast decision event.
project
Trusted project name configured for the command. Unlike tags, this value is not caller supplied and therefore remains available on the sanitized pipeline_fail_fast decision event.
note
Optional human-readable diagnostic string for ancillary events such as stdin_error.
byte_count
Number of bytes written for byte-counted phases such as stdin.
operation
For failure and lifecycle events, the operation involved. For stdin_error this is the pipe operation that failed (for example write or close); for timeout it is wait; for teardown_error it is drain.
error_type
For failure events such as stdin_error, timeout, and teardown_error, the class name of the raised exception (for example OSError, TimeoutError). For teardown_error this is the comma-joined class names of the consumer drain failures.
exec_id
Stable per-execution correlation token, minted once per execution and shared by every lifecycle event for that execution. It is the reliable way to correlate an execution's events, because a process identifier (pid) can be recycled by the operating system across executions. None for legacy or manually constructed events that predate the token; such events cannot be safely correlated by consumers.
terminal_outcome
Closed category carried by settled: exit_zero, exit_nonzero, timeout, cancelled, or error. It is None for every other phase and contains no exception details.
timeout_s
For the timeout phase, the configured wall-clock timeout in seconds that was exceeded. None for other phases.
timeout_mode
For the timeout phase, the reason the deadline expired: "elapsed_deadline" when a positive wall-clock deadline elapsed, or "non_positive_immediate" when a non-positive (timeout <= 0) deadline expired immediately without awaiting the process. None for other phases.
stage_index
Zero-based pipeline position of the failing stage for pipeline_fail_fast. This typed field is not derived from tags, which callers may shadow.
stage_count
Pipeline width for pipeline_fail_fast.
eof_grace_s
Fixed capture EOF grace duration for capture_eof_grace_expired.
pending_readers
Number of readers (one or two) still pending when the capture EOF grace elapsed. None for other phases.
max_rss_bytes
Maximum resident set size attributable to this execution's own child, in bytes, as reported by wait4. Carried on the terminal exit event of a direct command on Linux and macOS. None on Windows, on platforms whose child-specific interface is unavailable, on pipeline stages whose concurrently reaped children cannot be separated, and on the aggregate CPU-only fallback — whose RUSAGE_CHILDREN high-water mark spans every reaped child and cannot be attributed to this one. Also None on a timeout terminal event, where the child was signalled rather than reaped by its owner.
user_cpu_seconds
User CPU time in seconds attributable to this execution's child. Populated from the same wait4 result as max_rss_bytes on the attributable path, and from the clamped RUSAGE_CHILDREN delta on the CPU-only fallback. None where neither source applies.
system_cpu_seconds
System CPU time in seconds attributable to this execution's child, from the same sources and under the same conditions as user_cpu_seconds.
resource_usage_mode
How the resource fields above were obtained. See ResourceUsageMode. It is carried so a consumer can tell an attributable measurement from the aggregate fallback and from a platform that measures nothing, without inferring that from a None in max_rss_bytes alone. Every terminal exit event carries a mode: wait4_child or aggregate_cpu_delta where a source produced figures, and unavailable where none did — Windows, a platform without the child-specific interface, a pipeline stage, and the timeout path, which signals its child rather than reaping it. An unavailable terminal event therefore still distinguishes a platform that cannot measure from one whose samples went missing, which a bare None cannot. The mode is None on every non-terminal phase.
env_mode
The effective environment policy for this execution, once the active context and any per-call policy have been composed. Carried on every phase, because it is known before the child is spawned and describes the whole execution rather than one measurement. A replacement boundary is the reason the field exists: a REPLACE policy discards the live parent environment, so a child that omits PATH can fail to resolve a bare program name before it ever starts. Without the mode, a consumer sees an ordinary spawn failure and cannot tell it apart from an overlay run. None only on legacy or manually constructed events; the execution paths always resolve a mode.
owns_group
Whether the teardown that produced a group_teardown event was signalling the child's whole process group rather than the direct child alone. None for other phases. Carried because the same outcome means different things on the two routes: a group left holding members is a failure the ownership policy introduced, while a direct-child signal that could not be delivered is the behaviour every run had before it.
group_outcome
Closed category for a group_teardown event. See GroupTeardownOutcome. It is this field, rather than note or error_type, that a bounded metric is labelled from, so no pid, path, or error string can reach a metric label. None for other phases.
settle_s
How long the group-settlement wait had run when it expired, carried by a settlement_timeout event. None on the other outcomes, so an absent figure is not read as an instant one.
resolved_path
The executable this execution actually ran, when a scope bound the program's logical identity to a specific path. None when no binding applied, in which case the child ran under the name in argv[0].
error_category
Bounded category naming which failure boundary produced a diagnostic event. See StdioFailureCategory, also re-exported here. Carried on stdio_error; None for every other phase, including the pre-existing stdin_error events, whose operation already names its boundary. It is a typed field rather than part of note because error_type cannot carry it, and the value is low-cardinality, so it is the one failure attribute safe to attach to a metric series. It is the *executable*, not the command: argv still carries the arguments, and program still carries the catalogue identity that policy was checked against. Keeping all three means a consumer can see what was permitted, what was asked for, and what ran, without having to infer one from another. The path is a string rather than a resolved file identity, so a replaced binary is not detected; see the TOCTOU note in cuprum.executable_binding.
capture_mode
The mode this run reports its captures in, carried on every phase for the reason env_mode is: it is decided before the child spawns and describes the whole execution rather than one measurement. Without it a byte-exact run and a text run of the same command emit the same counters and span attributes, so a timeout, teardown failure, or terminal failure cannot be attributed to the mode that hit it. None only on legacy or hand-built events; see CaptureMode.

A field appended to this declaration preserves an existing positional slot only if nothing is inserted *ahead* of that slot: inserting one ahead of exec_id would silently rebind existing positional arguments, handing the correlation token to the new field and leaving exec_id=None — which consumers such as TracingHook treat as uncorrelatable and drop. Nor is appending enough by itself, because declaration follows insertion: terminal_outcome is pinned as the tail by test_terminal_outcome_public_api yet holds a positional slot of its own, so a later field is declared kw_only and inserted immediately before it. That keeps both the pinned tail and every pre-existing slot exactly where they were.

35 members

field ExecEvent.phase

phase: ExecPhase

field ExecEvent.program

program: Program

field ExecEvent.argv

argv: tuple[str, ...]

field ExecEvent.cwd

cwd: Path | None

field ExecEvent.env

env: EnvOverlay | None

field ExecEvent.pid

pid: int | None

field ExecEvent.timestamp

timestamp: float

field ExecEvent.line

line: str | None

field ExecEvent.exit_code

exit_code: int | None

field ExecEvent.duration_s

duration_s: float | None

field ExecEvent.tags

tags: cabc.Mapping[str, object]

field ExecEvent.note

note: str | None

field ExecEvent.byte_count

byte_count: int | None

field ExecEvent.operation

operation: str | None

field ExecEvent.error_type

error_type: str | None

field ExecEvent.exec_id

exec_id: ExecId | None

field ExecEvent.project

project: str | None

field ExecEvent.timeout_s

timeout_s: float | None

field ExecEvent.timeout_mode

timeout_mode: TimeoutMode | None

field ExecEvent.stage_index

stage_index: int | None

field ExecEvent.stage_count

stage_count: int | None

field ExecEvent.eof_grace_s

eof_grace_s: float | None

field ExecEvent.pending_readers

pending_readers: int | None

field ExecEvent.max_rss_bytes

max_rss_bytes: int | None

field ExecEvent.user_cpu_seconds

user_cpu_seconds: float | None

field ExecEvent.system_cpu_seconds

system_cpu_seconds: float | None

field ExecEvent.resource_usage_mode

resource_usage_mode: ResourceUsageMode | None

field ExecEvent.env_mode

env_mode: EnvMode | None

field ExecEvent.resolved_path

resolved_path: str | None

field ExecEvent.capture_mode

capture_mode: CaptureMode | None

field ExecEvent.owns_group

owns_group: bool | None

field ExecEvent.error_category

error_category: StdioFailureCategory | None

field ExecEvent.group_outcome

group_outcome: GroupTeardownOutcome | None

field ExecEvent.settle_s

settle_s: float | None

field ExecEvent.terminal_outcome

terminal_outcome: TerminalOutcome | None
module

cuprum.events

cuprum/events.py, the source of cuprum.events
from cuprum import events

Structured execution events for observability integrations.

Cuprum surfaces an optional stream of structured events describing command and pipeline execution. These are intended for logging, metrics, tracing, and auditing integrations without coupling Cuprum to a specific telemetry stack.

9 exports

class cuprum.events.CaptureMode

CaptureMode

How a run's captured output is reported by the telemetry adapters.

A closed set, like ResourceUsageMode: the mode is a metric label and a log extra operators filter on, so a typo at a new call site would miss their filters rather than raise. It rides each event as a trusted field rather than an observation tag, for the reason env_mode does: a caller may shadow any tag key, and a mode a consumer cannot rely on is pointless.

new type cuprum.events.ExecId

ExecId = typ.NewType('ExecId', uuid.UUID)

type alias cuprum.events.ExecPhase

ExecPhase = typ.Literal['plan', 'start', 'stdout', 'stderr', 'exit', 'settled', 'stdin', 'stdin_error', 'stdio_error', 'timeout', 'teardown_error', 'capture_eof_grace_expired', 'pipeline_fail_fast', 'group_teardown']

class cuprum.events.GroupTeardownOutcome

GroupTeardownOutcome

Why a teardown could not establish settlement.

A closed vocabulary because these values label a metric: an operator filters on the set of reasons a group was left behind, so every member is a stable, low-cardinality string that no runtime value can reach.

SIGNAL_REFUSED is the one outcome emitted on both routes: it reports a signal the kernel refused rather than a count of surviving members.

UNSIGNALABLE and SETTLEMENT_TIMEOUT both leave members running, and what separates them is what can still be done about it. An unsignalable group is outside this run's authority: nothing it sends reaches those members, so the teardown stops rather than waiting out a process it can never end. A settlement timeout was within reach in principle — the members were compelled with SIGKILL — and the capped wait expired because something outside this run owns their reaping. The first is a permissions fact about the group; the second is a race with an init process, and only the second is worth retrying.

class cuprum.events.ResourceUsageMode

ResourceUsageMode

How a terminal exit event obtained the resource figures it carries.

A closed set, like RustPumpDeclineReason: the value is a metric label and a log extra that operators filter on, so a typo at a new call site would produce a value their filters silently miss. As an enum it is a type error instead.

Members are str, so the observe event, the cuprum_ log extras, the span attributes, and the metrics label all keep carrying plain strings — the constant this replaced was a Literal of exactly these three values, and a member formats as its own value.

Examples
The member value is the string consumers see::

    assert ResourceUsageMode.WAIT4_CHILD == "wait4_child"

class cuprum.events.StdioFailureCategory

StdioFailureCategory

Which standard-stream boundary produced a diagnostic failure.

Members are str, so the observe event, the cuprum_ log extras, the span attributes, and the metrics label all carry plain strings.

Examples
The member value is the string consumers see::

    assert StdioFailureCategory.INVALID_CHUNK == "invalid_chunk"

class cuprum.events.TerminalOutcome

TerminalOutcome

Why an observed execution reached its definitive terminal event.

The values are shared with presentation sinks, so execution telemetry and output adapters classify the same outcome with the same bounded labels.

type alias cuprum.events.TimeoutMode

TimeoutMode = typ.Literal['elapsed_deadline', 'non_positive_immediate']

function cuprum.events.new_exec_id

def new_exec_id() -> ExecId

Return a fresh, process-unique execution correlation token.

Returns
ExecId
A new ExecId wrapping a random UUID (uuid.uuid4), distinct on every call, used to correlate all lifecycle events of a single execution.
function

logging_hook

cuprum/logging_hooks.py, the source of logging_hook
def logging_hook(
    *,
    logger: logging.Logger | None = None,
    start_level: int = logging.INFO,
    exit_level: int = logging.INFO,
    redaction: RedactionPolicy | None = None,
) -> LoggingHookRegistration

Register paired hooks that log start and exit events.

Parameters

logger
Logger instance to emit records to. Defaults to logging.getLogger( "cuprum") when omitted.
start_level
Logging level for the start event (default logging.INFO).
exit_level
Logging level for the exit event (default logging.INFO).
redaction
Optional policy applied to the logged argument vector. Defaults to None. Executed arguments and captured results remain unchanged.

Returns

LoggingHookRegistration
Handle for detaching the hooks manually or via context manager usage.
class

LoggingHookRegistration

cuprum/logging_hooks.py, the source of LoggingHookRegistration
class LoggingHookRegistration(
    start_registration: HookRegistration | None,
    exit_registration: HookRegistration | None,
    _detached: bool = False,
)

Bases: _ScopeRegistration

Registration handle for paired logging hooks.

Detaches both the start (before) and exit (after) hooks together to avoid leaking state across tests or calling code. Detach order is reversed from registration to respect ContextVar token stacking.

3 members

field LoggingHookRegistration.start_registration

start_registration: HookRegistration | None

field LoggingHookRegistration.exit_registration

exit_registration: HookRegistration | None

method LoggingHookRegistration.detach

def detach() -> None

Release the registration, exactly once.

function

observe_control

cuprum/control_observation.py, the source of observe_control
def observe_control(hook: ControlHook) -> ControlHookRegistration

Register a hook for owned-handle control events.

Parameters

hook
Synchronous callable invoked once for each completed control operation. It must not raise; a failure is logged and swallowed so it cannot replace the control operation's own outcome.

Returns

ControlHookRegistration
A context-local registration handle that supports detach() and context-manager use.
class

ControlEvent

cuprum/control_events.py, the source of ControlEvent
class ControlEvent(
    operation: ControlOperation,
    outcome: ControlOutcome,
    duration_s: float,
    exec_id: ExecId | None = None,
    signal_number: int | None = None,
    pid: int | None = None,
)

Aggregate telemetry for one completed control operation.

Attributes

operation
Closed operation kind, distinguishing a caller-named signal from a graceful stop and from a forced one.
outcome
Closed completion outcome. escalated identifies a stop that had to send the forced signal after the grace window elapsed.
duration_s
Monotonic elapsed seconds from operation start through completion.
exec_id
The owning run's correlation token, when the handle safely provides one. None for a control operation attempted on a handle whose run carried no token.
signal_number
The POSIX signal the caller named, for signal operations. None for the stop operations, which choose their own signal and report which one ended the child through the settled outcome instead.
pid
The child's process identifier, when the handle had one. It travels on the event so an operator reading a trace can name the process a control operation was aimed at; it must never become a metric label, because a label domain keyed on a PID grows without bound and a recycled PID would fold two unrelated children into one series.
6 members

field ControlEvent.operation

operation: ControlOperation

field ControlEvent.outcome

outcome: ControlOutcome

field ControlEvent.duration_s

duration_s: float

field ControlEvent.exec_id

exec_id: ExecId | None

field ControlEvent.signal_number

signal_number: int | None

field ControlEvent.pid

pid: int | None
class

ControlHookRegistration

cuprum/control_observation.py, the source of ControlHookRegistration
class ControlHookRegistration(hook: ControlHook) -> None

Bases: _IdentityTupleRegistration['ControlHook']

Registration handle for a control observation hook.

Detach removes only this handle's own hook by identity rather than restoring a captured token, so detaching out of last-in-first-out order cannot resurrect a hook someone already removed.

1 member

method ControlHookRegistration.detach

def detach() -> None

Release the registration, exactly once.

class

ControlOperation

cuprum/control_events.py, the source of ControlOperation
ControlOperation

Bases: enum.StrEnum

Closed kinds of control operation an owned handle performs.

3 members

member ControlOperation.SIGNAL

SIGNAL = 'signal'

member ControlOperation.TERMINATE

TERMINATE = 'terminate'

member ControlOperation.KILL

KILL = 'kill'
class

ControlOutcome

cuprum/control_events.py, the source of ControlOutcome
ControlOutcome

Bases: enum.StrEnum

Closed terminal outcomes for one control operation.

DELIVERED and ESCALATED describe a child that was asked to stop and did — the first without needing the forced signal, the second only after it. REFUSED_EXITED and REFUSED_UNSUPPORTED describe the two things that can keep a control operation from being delivered at all, and they are kept apart because the caller's remedy differs: an exited child is a race the caller simply lost, while an unsupported platform is a limitation no retry can fix.

4 members

member ControlOutcome.DELIVERED

DELIVERED = 'delivered'

member ControlOutcome.ESCALATED

ESCALATED = 'escalated'

member ControlOutcome.REFUSED_EXITED

REFUSED_EXITED = 'refused_exited'

member ControlOutcome.REFUSED_UNSUPPORTED

REFUSED_UNSUPPORTED = 'refused_unsupported'
function

observe_line_stream

cuprum/line_stream_observation.py, the source of observe_line_stream
def observe_line_stream(
    hook: LineStreamHook,
) -> LineStreamHookRegistration

Register a synchronous lifecycle observer for SafeCmd.lines().

Observer failures are logged and do not alter subprocess results, timeout translation, or cancellation. Prefer a with block so registration is restored in the same context that installed it.

Parameters

hook
A synchronous callable that receives each LineStreamEvent in the active context.

Returns

LineStreamHookRegistration
A scoped registration that detaches the hook on scope exit or explicit LineStreamHookRegistration.detach.
class

LineStreamEvent

cuprum/line_stream_events.py, the source of LineStreamEvent
class LineStreamEvent(
    phase: LineStreamPhase,
    exec_id: ExecId,
    pid: int | None,
    stream: LineStreamName | None = None,
    sink: LineStreamSink | None = None,
    queue_size: int | None = None,
    queue_capacity: int | None = None,
    error_type: str | None = None,
)

One line-stream lifecycle boundary for operational observers.

queue_size and queue_capacity describe bounded backpressure only in structured event data. Metrics adapters use only the closed phase, stream, and sink vocabularies, never identifiers, payloads, or exception types.

Attributes

phase
One bounded lifecycle state from LineStreamPhase.
exec_id
The execution identifier shared with the corresponding ExecEvent lifecycle.
pid
The child process identifier once spawning has completed.
stream
The output stream related to a queue or sink event, when applicable.
sink
The bounded callback or queue destination related to a sink failure.
queue_size
The queue depth at a saturation boundary, recorded as event data only.
queue_capacity
The finite queue capacity at a saturation boundary.
error_type
The exception class name from a sink failure, never a metric label.
8 members

field LineStreamEvent.phase

phase: LineStreamPhase

field LineStreamEvent.exec_id

exec_id: ExecId

field LineStreamEvent.pid

pid: int | None

field LineStreamEvent.stream

stream: LineStreamName | None

field LineStreamEvent.sink

sink: LineStreamSink | None

field LineStreamEvent.queue_size

queue_size: int | None

field LineStreamEvent.queue_capacity

queue_capacity: int | None

field LineStreamEvent.error_type

error_type: str | None
class

LineStreamHookRegistration

cuprum/line_stream_observation.py, the source of LineStreamHookRegistration
class LineStreamHookRegistration(hook: LineStreamHook) -> None

Bases: _IdentityTupleRegistration['LineStreamHook']

Scoped registration handle for one line-stream lifecycle hook.

Detach removes exactly the hook this handle registered, by identity, so detaching out of last-in-first-out order cannot resurrect a stale hook that was already removed.

1 member

method LineStreamHookRegistration.detach

def detach() -> None

Release the registration, exactly once.

class

LineStreamPhase

cuprum/line_stream_events.py, the source of LineStreamPhase
LineStreamPhase

Bases: enum.StrEnum

The bounded lifecycle vocabulary for LineStreamEvent.

Attributes

SPAWNED
The subprocess and its consumers are ready.
QUEUE_SATURATED
A line sink is waiting for bounded queue capacity.
SINK_FAILED
A callback or queue sink raised while receiving a line.
TIMEOUT
The command deadline expired.
CANCELLED
Iteration or line delivery was cancelled.
TEARDOWN_STARTED
Shared child-process teardown began.
TEARDOWN_COMPLETED
Shared teardown and consumer drainage completed.
COMPLETED
The command result was assembled and is ready to publish.
8 members

member LineStreamPhase.SPAWNED

SPAWNED = 'spawned'

member LineStreamPhase.QUEUE_SATURATED

QUEUE_SATURATED = 'queue_saturated'

member LineStreamPhase.SINK_FAILED

SINK_FAILED = 'sink_failed'

member LineStreamPhase.TIMEOUT

TIMEOUT = 'timeout'

member LineStreamPhase.CANCELLED

CANCELLED = 'cancelled'

member LineStreamPhase.TEARDOWN_STARTED

TEARDOWN_STARTED = 'teardown_started'

member LineStreamPhase.TEARDOWN_COMPLETED

TEARDOWN_COMPLETED = 'teardown_completed'

member LineStreamPhase.COMPLETED

COMPLETED = 'completed'
function

observe_echo

cuprum/echo_observation.py, the source of observe_echo
def observe_echo(hook: EchoHook) -> EchoHookRegistration

Register a hook for stream-echo failure events in the current context.

Parameters

hook
Synchronous callable invoked with each EchoEvent.

Returns

EchoHookRegistration
A handle that can be detached or used as a context manager.

Examples

Count echo failures into a metrics collector::

    from cuprum.adapters.metrics_adapter import InMemoryMetrics
    from cuprum.adapters.echo_metrics import EchoMetricsHook

    metrics = InMemoryMetrics()
    with observe_echo(EchoMetricsHook(metrics)):
        pipeline.run_sync()
class

EchoEvent

cuprum/echo_events.py, the source of EchoEvent
class EchoEvent(
    stream: EchoStream,
    error_category: EchoErrorCategory,
    dropped_bytes: int | None = None,
)

A stream-echo event reported to registered echo hooks.

Attributes

stream
Which output stream the failing echo belonged to.
error_category
The closed-set category naming why the event occurred.
dropped_bytes
Child-output bytes omitted from a successfully truncated echo line, otherwise None.

Examples

A stdout echo that could not encode its payload::

    event = EchoEvent(
        stream=EchoStream.STDOUT,
        error_category=EchoErrorCategory.UNICODE_ENCODE,
    )
    assert event.stream == "stdout"
3 members

field EchoEvent.stream

stream: EchoStream

field EchoEvent.error_category

error_category: EchoErrorCategory

field EchoEvent.dropped_bytes

dropped_bytes: int | None
type alias

EchoHook

cuprum/echo_events.py, the source of EchoHook
EchoHook = cabc.Callable[[EchoEvent], None]

A synchronous consumer of EchoEvent values.

Echo hooks are synchronous by contract: the emission site sits inline in the echo write path, between two writes to the same sink, and there is no point at which awaiting a hook could be ordered against the chunk being echoed.

class

EchoHookRegistration

cuprum/echo_observation.py, the source of EchoHookRegistration
class EchoHookRegistration(hook: EchoHook) -> None

Bases: _TokenTupleRegistration['EchoHook']

Registration handle for a stream-echo observation hook.

Supports detach() and context-manager use. The handle captures a contextvars.Token when it installs the extended hook tuple, and detach restores the exact tuple that was current when the handle was created — the same discipline PumpHookRegistration applies. Detach in the contextvars.Context that created the registration; resetting a ContextVar with a token from another context raises ValueError.

Prefer with blocks, which detach in last-in-first-out order; detaching out of order restores a tuple that discards later registrations.

1 member

method EchoHookRegistration.detach

def detach() -> None

Release the registration, exactly once.

class

EchoStream

cuprum/echo_events.py, the source of EchoStream
EchoStream

Bases: enum.StrEnum

Which subprocess output stream an echo event describes.

A closed set rather than free text: operators aggregate the stream metric label, so an unbounded sink object name would create one series per sink type and a caller-controlled value would be a disclosure risk.

Examples

The member value is the string operators see::

    assert EchoStream.STDOUT == "stdout"
2 members

member EchoStream.STDOUT

STDOUT = 'stdout'

member EchoStream.STDERR

STDERR = 'stderr'
class

EchoErrorCategory

cuprum/echo_events.py, the source of EchoErrorCategory
EchoErrorCategory

Bases: enum.StrEnum

Why an echo event occurred, as a closed set of categories.

Examples

The member value is the string operators see::

    assert EchoErrorCategory.UNICODE_ENCODE == "unicode_encode"
    assert EchoErrorCategory.BROKEN_PIPE == "broken_pipe"
3 members

member EchoErrorCategory.UNICODE_ENCODE

UNICODE_ENCODE = 'unicode_encode'

member EchoErrorCategory.BROKEN_PIPE

BROKEN_PIPE = 'broken_pipe'

member EchoErrorCategory.TRUNCATED

TRUNCATED = 'truncated'
class

RelayFallback

cuprum/echo_events.py, the source of RelayFallback
class RelayFallback(
    stream: EchoStream,
    error_category: EchoErrorCategory,
)

One handled echo-disablement recorded on a command's result.

A text-only echo sink rejected the subprocess output, or reported a broken pipe the caller asked to tolerate, so the echo for that stream's drain was disabled while the stream itself kept being consumed and, when enabled, captured. One record describes one handled disablement for one stream: later chunks and the final decoder flush never re-enter the failed write, so a drain contributes at most one record.

Attributes

stream
Which output stream the handled echo disablement belonged to. The value is the closed-set EchoStream, not free text.
error_category
The closed-set EchoErrorCategory naming why the echo write failed. It is categorical only: the sink's type, its encoding, any exception text, and the subprocess payload never reach the record.

Examples

A stdout echo that could not encode its payload::

    fallback = RelayFallback(
        stream=EchoStream.STDOUT,
        error_category=EchoErrorCategory.UNICODE_ENCODE,
    )
    assert fallback.stream == "stdout"
2 members

field RelayFallback.stream

stream: EchoStream

field RelayFallback.error_category

error_category: EchoErrorCategory
module

cuprum.stream_observation

cuprum/stream_observation.py, the source of cuprum.stream_observation
from cuprum import stream_observation

Registration and fail-open emission for aggregate stream-operation events.

3 exports

class cuprum.stream_observation.StreamOperationHookRegistration

class StreamOperationHookRegistration(hook: StreamOperationHook) -> None

Registration handle for a stream-operation observation hook.

Detach removes only this handle's own hook by identity rather than restoring a captured token, so detaching out of last-in-first-out order cannot resurrect a hook someone already removed.

function cuprum.stream_observation.current_stream_operation_hooks

def current_stream_operation_hooks() -> tuple[StreamOperationHook, ...]

Return stream-operation hooks registered in the current context.

function cuprum.stream_observation.observe_stream_operation

def observe_stream_operation(
    hook: StreamOperationHook,
) -> StreamOperationHookRegistration

Register a hook for aggregate stream-operation completion events.

Parameters
hook
Synchronous callable invoked once for each completed registered stream operation.
Returns
StreamOperationHookRegistration
A context-local registration handle that supports detach() and context-manager use.