Class Breadcrumbs

java.lang.Object
com.tnsai.observability.events.Breadcrumbs

public final class Breadcrumbs extends Object
Per-thread ring buffer of recent operations leading up to a point in time — typically an exception throw.

ErrorReport embeds a snapshot of breadcrumbs so an operator inspecting an error sees the last N framework operations (Agent.chat entered, Tool web_search invoked, LLM gpt-4o called, …) without having to grep neighbouring log lines by timestamp + thread. Patterned after Sentry / Bugsnag / Rollbar breadcrumb concepts.

Lifecycle

Framework entry points add breadcrumbs as they enter:

 Breadcrumbs.add("Agent.chat", Map.of("agent", agentId));
 try (var ignored = AgentContext.enter(ctx)) {
     ...
 }
 
On exception, ErrorReport.from(t) (a follow-up integration) snapshots the current list and embeds it. Tests / consumers can also read with snapshot().

Bounded ring buffer

Default capacity 20. When full, the oldest breadcrumb is evicted. Override per-thread with resizeForCurrentThread(int) (must be called before any add). Cap kept low because the buffer is thread-local and snapshotted on every error — overhead must stay negligible.

Thread-local

Each thread owns its own buffer; no cross-thread sharing. Async propagation is the caller's concern (use AgentContext.wrap(java.lang.Runnable) which currently does NOT propagate breadcrumbs — that's a known limitation, see follow-up for AgentAwareExecutor).
Since:
0.5.0 (issue #90)
  • Field Details

    • DEFAULT_CAPACITY

      public static final int DEFAULT_CAPACITY
      Default ring buffer capacity.
      See Also:
  • Method Details

    • add

      public static void add(String operation, Map<String,Object> attrs)
      Append a breadcrumb to the current thread's buffer. When the buffer is at capacity the oldest entry is evicted.
      Parameters:
      operation - human-readable label, e.g. "Agent.chat entered"
      attrs - supplemental fields; null treated as empty
    • add

      public static void add(String operation)
      Convenience for breadcrumbs without attributes.
    • snapshot

      public static List<Breadcrumbs.Breadcrumb> snapshot()
      Snapshot the current thread's breadcrumb list (oldest-first). Returns an immutable copy — later mutations to the buffer do not affect the snapshot.
    • clear

      public static void clear()
      Drop everything in the current thread's buffer. Called by framework entry points on session boundaries to avoid breadcrumb bleed across unrelated requests reusing the same worker thread.
    • resizeForCurrentThread

      public static void resizeForCurrentThread(int capacity)
      Reset the current thread's buffer to a fresh ring of capacity entries. Existing breadcrumbs are discarded. Must be called before the first add on a thread to take effect for the whole lifetime of that thread (or until clear() + resize again).
    • currentCapacity

      public static int currentCapacity()
      Returns:
      current buffer capacity for this thread (default DEFAULT_CAPACITY).