Skip to main content

rig_tap/
lib.rs

1//! Backend-agnostic observability event schema and taps for [Rig](https://crates.io/crates/rig-core).
2//!
3//! See the crate [README](../README.md) for the full schema and consumer
4//! recipe. The two consumer-facing types are:
5//!
6//! - [`TelemetryHook`] — implements [`rig::agent::PromptHook`] and emits
7//!   `prompt.*` and `tool.*` events.
8//! - [`ObservedMemory`] — wraps any [`rig::memory::ConversationMemory`] and
9//!   emits `context.sampled` on every load.
10//!
11//! Plus [`ChainedHook`] for composing two `PromptHook`s on a single agent.
12//!
13//! # Wire format
14//!
15//! All events are emitted as a single `tracing::info!` event on the
16//! [`EVENT_TARGET`] target (`"rig_tap"`) with a single
17//! string field `event` carrying the JSON-encoded
18//! [`ObservabilityEvent`]. Consumers attach a `tracing_subscriber::Layer`
19//! filtered to that target.
20//!
21//! # Subscriber sizing
22//!
23//! Emission is synchronous: every event runs serde + the registered
24//! layers on the calling task. Per-request hot paths (every prompt, every
25//! tool call, every memory load) call into the tracing dispatcher
26//! directly. For production deployments — especially ones that ship
27//! events off-host — wire a non-blocking sink (e.g.
28//! `tracing_appender::non_blocking` or a bounded channel feeding an
29//! async exporter) so a slow consumer can't backpressure the agent.
30//! In-process counters and the bundled doc-test layer are fine
31//! synchronous.
32//!
33//! # Example
34//!
35//! ```no_run
36//! use rig_tap::{TelemetryHook, ObservedMemory};
37//! use rig::memory::InMemoryConversationMemory;
38//!
39//! # fn build<M: rig::completion::CompletionModel>() -> TelemetryHook<M> {
40//! let memory = ObservedMemory::new(InMemoryConversationMemory::new());
41//! let hook = TelemetryHook::<M>::with_defaults("gpt-4o", "thread-1");
42//! // agent.memory(memory).with_hook(hook)
43//! # hook }
44//! ```
45
46#![deny(missing_docs)]
47
48pub mod extract;
49
50mod chained;
51#[cfg(feature = "compose")]
52mod dispatch;
53pub mod emit;
54mod error;
55mod event;
56mod hook;
57mod observed_memory;
58#[cfg(feature = "subscriber")]
59mod subscriber;
60
61pub use chained::ChainedHook;
62#[cfg(feature = "compose")]
63pub use dispatch::DispatchObserveHook;
64pub use emit::{EVENT_TARGET, build_event, emit, emit_kind, try_emit};
65pub use error::Error;
66pub use event::{
67    EventKind, ObservabilityEvent, PAYLOAD_TRUNCATE_BYTES, SCHEMA_VERSION, truncate_utf8,
68};
69pub use extract::extract_event;
70pub use hook::{ConversationIdResolver, ModelResolver, TelemetryHook, TelemetryHookConfig};
71pub use observed_memory::ObservedMemory;
72#[cfg(feature = "subscriber")]
73pub use subscriber::CapturingLayer;