sandbox-agent/docs/observability.mdx
Nathan Flurry febe8601f6
feat: add process management support (#207)
* feat: improve inspector UI for processes and fix PTY terminal

- Simplify ProcessRunTab layout: compact form with collapsible Advanced section for timeout/maxOutputBytes
- Rewrite ProcessesTab: collapsible create form, lightweight list items with status dots, clean detail panel with tabs
- Extract error details: use problem.detail instead of generic "Stream Error" title for better error messages
- Fix GhosttyTerminal binary frame parsing: handle server's binary ArrayBuffer control frames (ready/exit/error)
- Enable WebSocket proxying in Vite dev server with ws: true
- Set TERM=xterm-256color default for TTY processes so tools like tmux, vim, htop work out of the box
- Remove orange gradient background from terminal container for cleaner look
- Remove orange left border from selected process list items
- Update inspector CSS with new process/terminal styles

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* fix: address review issues and add processes documentation

- Fix unstable onExit callback in ProcessesTab (useCallback)
- Fix SSE follow stream race condition (subscribe before history read)
- Update inspector.mdx with new process management features
- Change observability icon to avoid conflict with processes
- Add docs/processes.mdx covering the full process management API

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: simplify processes doc — rename sections, remove low-level protocol

- Rename "Interactive terminals" to "Terminals" with "Connect to a terminal" sub-heading
- Add TTY process creation step at top of Terminals section
- Remove low-level WebSocket protocol table and raw WebSocket example
- Keep browser terminal emulator reference with Ghostty link

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update GhosttyTerminal permalink to latest commit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: use main branch permalink for GhosttyTerminal reference

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: refine process API — WebSocket binary protocol, SDK terminal session, updated tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update GhosttyTerminal permalink to 636eefb

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* inspector: use websocket terminal API

* sdk: restore high-level terminal session

* docs: update inspector terminal permalink

* inspector: update run once placeholder

* Fix lazy install v1 API test fixture

* Add reusable React terminal component

* Fix terminal WebSocket ready state checks

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-07 17:58:31 -08:00

64 lines
1.8 KiB
Text

---
title: "Observability"
description: "Track session activity with OpenTelemetry."
icon: "chart-line"
---
Use OpenTelemetry to instrument session traffic, then ship telemetry to your collector/backend.
## Common collectors and backends
- [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/)
- [Jaeger](https://www.jaegertracing.io/)
- [Grafana Tempo](https://grafana.com/oss/tempo/)
- [Honeycomb](https://www.honeycomb.io/)
- [Datadog APM](https://docs.datadoghq.com/tracing/)
## Example: trace a prompt round-trip
Wrap `session.prompt()` in a span to measure the full round-trip, then log individual events as span events.
Assumes your OTEL provider/exporter is already configured.
```ts
import { trace } from "@opentelemetry/api";
import { SandboxAgent } from "sandbox-agent";
const tracer = trace.getTracer("my-app/sandbox-agent");
const sdk = await SandboxAgent.connect({
baseUrl: process.env.SANDBOX_URL!,
});
const session = await sdk.createSession({ agent: "mock" });
// Log each event as an OTEL span event on the active span
const unsubscribe = session.onEvent((event) => {
const activeSpan = trace.getActiveSpan();
if (!activeSpan) return;
activeSpan.addEvent("session.event", {
"sandbox.sender": event.sender,
"sandbox.event_index": event.eventIndex,
});
});
// The span covers the full prompt round-trip
await tracer.startActiveSpan("sandbox_agent.prompt", async (span) => {
span.setAttribute("sandbox.session_id", session.id);
try {
const result = await session.prompt([
{ type: "text", text: "Summarize this repository." },
]);
span.setAttribute("sandbox.stop_reason", result.stopReason);
} catch (error) {
span.recordException(error as Error);
throw error;
} finally {
span.end();
}
});
unsubscribe();
```