Telemetry and redaction¶
Typed in-process events, payload-free by default, plus the redaction registry that keeps secrets out of everything. Concepts: telemetry · credentials and redaction.
Observing¶
anyinfer.Observer ¶
Bases: Protocol
A telemetry sink.
Implementations receive every event the client emits. Keep on_event fast and
non-blocking; queue work elsewhere if it might be slow.
anyinfer.TelemetryEvent
module-attribute
¶
TelemetryEvent = (
RequestStarted
| TargetResolved
| AttemptStarted
| FirstToken
| AttemptCompleted
| RetryScheduled
| FallbackTriggered
| RepairAttempted
| RequestCompleted
| RequestFailed
| ParameterDropped
| UsageEstimated
| ServerLifecycle
| DownloadProgress
| ContextReduced
)
Any event an observer may receive.
Request lifecycle events¶
anyinfer.RequestStarted
dataclass
¶
RequestStarted(
request_id: str,
targets: tuple[Target, ...],
metadata: Mapping[str, str] = dict(),
prompt_text: str | None = None,
)
A generation request entered the router.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
targets |
tuple[Target, ...]
|
The fallback chain as requested, in the order the router will try it. |
metadata |
Mapping[str, str]
|
Caller-supplied labels from the request, passed through untouched. |
prompt_text |
str | None
|
The prompt text; |
anyinfer.TargetResolved
dataclass
¶
TargetResolved(request_id: str, target: ResolvedTarget)
A target string resolved to a concrete provider and model.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
target |
ResolvedTarget
|
The concrete provider and model the target string resolved to. |
anyinfer.AttemptStarted
dataclass
¶
AttemptStarted(
request_id: str,
target: ResolvedTarget,
attempt_number: int,
)
An attempt against one resolved target began.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
target |
ResolvedTarget
|
The resolved target being attempted. |
attempt_number |
int
|
1-based count of attempts against this target; retries increment it, and falling back to a new target restarts it at 1. |
anyinfer.FirstToken
dataclass
¶
FirstToken(
request_id: str, target: ResolvedTarget, at_ms: float
)
The first content delta arrived — the centrally-measured TTFT.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
target |
ResolvedTarget
|
The resolved target that produced the token. |
at_ms |
float
|
Milliseconds from attempt start to the first content delta. |
anyinfer.AttemptCompleted
dataclass
¶
AttemptCompleted(
request_id: str,
target: ResolvedTarget,
usage: Usage,
timing: Timing,
finish_reason: str,
)
An attempt finished successfully.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
target |
ResolvedTarget
|
The resolved target that served the attempt. |
usage |
Usage
|
Token usage for the attempt, merged across every report the provider sent. |
timing |
Timing
|
Centrally-measured attempt timings, comparable across providers. |
finish_reason |
str
|
Normalized reason generation stopped, e.g. |
anyinfer.RetryScheduled
dataclass
¶
RetryScheduled(
request_id: str,
target: ResolvedTarget,
attempt_number: int,
delay_s: float,
error: ErrorInfo,
)
A retryable failure will be retried against the same target after a delay.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
target |
ResolvedTarget
|
The resolved target that will be retried. |
attempt_number |
int
|
The 1-based attempt that just failed; the retry is the next one. |
delay_s |
float
|
Seconds the router sleeps before the retry. |
error |
ErrorInfo
|
Snapshot of the retryable failure. |
anyinfer.FallbackTriggered
dataclass
¶
FallbackTriggered(
request_id: str,
from_target: ResolvedTarget,
to_target: Target,
error: ErrorInfo | None = None,
)
A target was abandoned; the router advanced to the next in the chain.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
from_target |
ResolvedTarget
|
The resolved target that was abandoned. |
to_target |
Target
|
The next target string the router will try, not yet resolved. |
error |
ErrorInfo | None
|
Snapshot of the failure that caused the abandonment, or |
anyinfer.RepairAttempted
dataclass
¶
RepairAttempted(
request_id: str,
target: ResolvedTarget,
attempt_number: int,
mechanism: Mechanism | None,
errors: tuple[str, ...] = (),
raw_text: str | None = None,
)
A schema violation triggered a repair re-prompt.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
target |
ResolvedTarget
|
The resolved target being re-prompted. |
attempt_number |
int
|
1-based count of repair attempts within this generation. |
mechanism |
Mechanism | None
|
The structured-output mechanism in force when validation failed, when one was chosen. |
errors |
tuple[str, ...]
|
The schema-validation messages that triggered the repair. |
raw_text |
str | None
|
The response text that failed validation; |
anyinfer.ParameterDropped
dataclass
¶
ParameterDropped(
request_id: str,
target: ResolvedTarget,
parameter: str,
reason: str,
)
A requested parameter was not sent, because the target cannot accept it.
Dropping a parameter silently is how a caller ends up debugging why temperature=0
had no effect. Every drop is observable instead.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
target |
ResolvedTarget
|
The resolved target the parameter was withheld from. |
parameter |
str
|
Name of the request parameter that was not sent. |
reason |
str
|
Human-readable explanation of why the target cannot accept it. |
anyinfer.ContextReduced
dataclass
¶
ContextReduced(
strategy: str,
representation: str,
candidate_count: int,
selected_count: int,
omitted_count: int,
estimated_tokens: int,
max_tokens: int,
binding_constraints: tuple[str, ...] = (),
calls: int = 0,
)
A context corpus was reduced to fit a budget.
Reduction emulates a larger context window, and emulation is observable rather than silent. Content-free by construction: counts and ceilings only, never paths or document text — a path name can itself be sensitive.
Attributes:
| Name | Type | Description |
|---|---|---|
strategy |
str
|
The strategy requested ( |
representation |
str
|
The strategy actually applied. |
candidate_count |
int
|
Documents offered to the reducer. |
selected_count |
int
|
Documents represented at detail fidelity. |
omitted_count |
int
|
Documents not represented in detail. |
estimated_tokens |
int
|
Planning-side estimate of the rendered envelope. |
max_tokens |
int
|
The budget the reduction was held to. |
binding_constraints |
tuple[str, ...]
|
Which ceilings excluded at least one document. |
calls |
int
|
Generation calls spent; non-zero only for |
anyinfer.UsageEstimated
dataclass
¶
UsageEstimated(
request_id: str,
target: ResolvedTarget,
field_name: str,
method: str,
)
A usage figure was derived rather than reported by the provider.
Estimated and reported numbers must never be indistinguishable downstream; this event is what marks the difference for observers.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
target |
ResolvedTarget
|
The resolved target the estimate applies to. |
field_name |
str
|
The usage field that was estimated, e.g. |
method |
str
|
How the estimate was derived. |
anyinfer.RequestCompleted
dataclass
¶
RequestCompleted(
request_id: str,
target: ResolvedTarget,
usage: Usage,
timing: Timing,
repair_attempts: int = 0,
response_text: str | None = None,
)
A request produced a result.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
target |
ResolvedTarget
|
The resolved target that produced the result. |
usage |
Usage
|
Final token usage for the request. |
timing |
Timing
|
Final centrally-measured timings for the request. |
repair_attempts |
int
|
How many repair re-prompts were needed; |
response_text |
str | None
|
The final response text; |
anyinfer.RequestFailed
dataclass
¶
RequestFailed(request_id: str, error: ErrorInfo)
A request exhausted its route without a result.
Attributes:
| Name | Type | Description |
|---|---|---|
request_id |
str
|
Correlation id shared by every event this request emits. |
error |
ErrorInfo
|
Snapshot of the terminal failure, after every target and retry was spent. |
Local subsystem events¶
anyinfer.DownloadProgress
dataclass
¶
DownloadProgress(
artifact_id: str,
downloaded_bytes: int,
total_bytes: int | None,
done: bool = False,
phase: str = "",
file_index: int = 0,
file_count: int = 0,
filename: str = "",
session_bytes: int = 0,
)
Progress of a model acquisition.
downloaded_bytes and total_bytes are aggregate across the whole acquisition,
which is what their names have always implied. Earlier builds reported them per file,
so a sharded artifact restarted the counter at zero on every shard with no way for an
observer to tell. The remaining fields carry the per-file detail that the aggregate
figures deliberately no longer mix in.
Attributes:
| Name | Type | Description |
|---|---|---|
artifact_id |
str
|
The artifact or catalog variant being acquired. |
downloaded_bytes |
int
|
Bytes present across every file, including bytes that were already on disk before this run — so resuming reports the resumed position. |
total_bytes |
int | None
|
Total expected bytes, or |
done |
bool
|
Whether the acquisition finished. |
phase |
str
|
Which stage emitted this, when the acquisition engine supplied one. |
file_index |
int
|
1-based index of the file that most recently advanced. |
file_count |
int
|
How many files this acquisition covers. |
filename |
str
|
Name of that file. |
session_bytes |
int
|
Bytes this run actually transferred, as opposed to resumed. |
anyinfer.ServerLifecycle
dataclass
¶
ServerLifecycle(
server_id: str,
state: Literal[
"starting",
"ready",
"stopping",
"stopped",
"crashed",
],
detail: str = "",
)
A supervised local server changed state.
Attributes:
| Name | Type | Description |
|---|---|---|
server_id |
str
|
Identifies the supervised server — the key of the model it serves. |
state |
Literal['starting', 'ready', 'stopping', 'stopped', 'crashed']
|
The state the server just entered. |
detail |
str
|
Human-readable context, such as a stop reason or a tail of crash output; empty when there is nothing to add. |
Redaction¶
anyinfer.RedactionRegistry ¶
RedactionRegistry()
A thread-safe set of secrets to strip from outbound strings.
register ¶
register(secret: str | None) -> None
Register a secret for redaction.
Values shorter than MIN_SECRET_LEN are ignored: redacting them would corrupt
unrelated text far more often than it would protect anything.
anyinfer.register_secret ¶
register_secret(secret: str | None) -> None
Register a secret with the process-wide registry.
anyinfer.redact ¶
redact(text: str) -> str
Redact registered secrets from text using the process-wide registry.
OpenTelemetry export¶
The optional [otel] extra maps these events onto OpenTelemetry spans and metrics.
Guide: observability.
anyinfer.otel.install ¶
install(
client: Any, *, record_payloads: bool = False
) -> OTelObserver
Attach an OTelObserver to a client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
Any
|
An |
required |
record_payloads
|
bool
|
Attach prompt and response text to spans. |
False
|
Returns:
| Type | Description |
|---|---|
OTelObserver
|
The observer, so it can be detached later. |
anyinfer.otel.OTelObserver ¶
OTelObserver(
*,
tracer: Any = None,
meter: Any = None,
record_payloads: bool = False,
)
Maps AnyInfer telemetry events onto OpenTelemetry spans and metrics.
One span per request, with attempts as span events. Requests and attempts are
correlated by request_id, so a fallback chain reads as a single trace rather than
several disconnected ones.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tracer
|
Any
|
An OpenTelemetry tracer. Defaults to one from the global provider. |
None
|
meter
|
Any
|
An OpenTelemetry meter. Defaults to one from the global provider. |
None
|
record_payloads
|
bool
|
Attach prompt and response text to spans. Off by default, matching
the payload-free default of the event contract itself. Subscribe with
|
False
|
Raises:
| Type | Description |
|---|---|
ConfigError
|
If |
on_event ¶
on_event(event: TelemetryEvent) -> None
Handle one telemetry event.
Never raises: the dispatcher isolates observer failures, but a telemetry bridge that can break a generation would be a poor trade regardless.
anyinfer.otel.GEN_AI
module-attribute
¶
GEN_AI = 'gen_ai'
Prefix of the GenAI semantic-convention attribute namespace.