Observability
SandboxHooks lifecycle callbacks and OpenTelemetry tracing with @alineo-labs/otel.
SandboxHooks
SandboxHooks is a set of lifecycle callbacks you can pass to client.sandbox() to observe what's happening during a run. All hooks are optional.
import type { SandboxHooks } from "@alineo-labs/sandbox";
const hooks: SandboxHooks = {
onSandboxCreated(sandboxId, name) {
console.log(`[sandbox] created: ${name} (${sandboxId})`);
},
onExecStart(sandboxId, seq, cmd) {
console.log(`[exec:${seq}] start: ${cmd.slice(0, 80)}`);
},
onExecComplete(sandboxId, seq, result) {
console.log(`[exec:${seq}] done: exit ${result.exitCode}`);
},
onCheckpoint(sandboxId, snapshotId, name) {
console.log(`[checkpoint] ${name ?? ""} → ${snapshotId}`);
},
onSandboxClosed(sandboxId) {
console.log(`[sandbox] closed: ${sandboxId}`);
},
onSandboxFailed(sandboxId, error) {
console.error(`[sandbox] failed: ${error.message}`);
},
};
const sb = await client.sandbox({
image: "ubuntu:22.04",
resources: { cpu: "500m", memory: "256Mi" },
hooks,
});Hook signatures
| Hook | When | Arguments |
|---|---|---|
onSandboxCreated | Container created and running | (sandboxId, name) |
onExecStart | sb.exec() called | (sandboxId, seq, cmd) |
onExecComplete | exec finished | (sandboxId, seq, ExecResult) |
onCheckpoint | sb.checkpoint() completed | (sandboxId, snapshotId, name?) |
onSandboxClosed | sb.close() completed | (sandboxId) |
onSandboxFailed | sandbox creation or boot failed | (sandboxId, error) |
OpenTelemetry with @alineo-labs/otel
@alineo-labs/otel provides an otelHooks() factory that produces SandboxHooks emitting OTEL traces:
bun add @alineo-labs/otel @opentelemetry/apiimport { otelHooks } from "@alineo-labs/otel";
import { trace } from "@opentelemetry/api";
const tracer = trace.getTracer("my-app");
const sb = await client.sandbox({
image: "node:22",
resources: { cpu: "500m", memory: "512Mi" },
hooks: otelHooks(tracer),
});Span structure
sandbox.run ← root span (alineo.sandbox.id, alineo.sandbox.name)
sandbox.exec ← child per exec (alineo.exec.cmd, alineo.exec.seq, process.exit_code)
sandbox.checkpoint ← child per checkpoint (alineo.snapshot.id, alineo.checkpoint.name)OtelHooksOptions
| Option | Type | Default | Description |
|---|---|---|---|
recordExitCode | boolean | true | Add process.exit_code attribute to exec spans |
const hooks = otelHooks(tracer, { recordExitCode: false });Setting up OTEL
otelHooks uses the @opentelemetry/api package — it integrates with whatever OTEL SDK you have configured in your application. Example with the Node SDK:
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { trace } from "@opentelemetry/api";
import { otelHooks } from "@alineo-labs/otel";
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({ url: "http://localhost:4318/v1/traces" }),
});
sdk.start();
const tracer = trace.getTracer("my-app");
const sb = await client.sandbox({
image: "ubuntu:22.04",
resources: { cpu: "500m", memory: "256Mi" },
hooks: otelHooks(tracer),
});