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

HookWhenArguments
onSandboxCreatedContainer created and running(sandboxId, name)
onExecStartsb.exec() called(sandboxId, seq, cmd)
onExecCompleteexec finished(sandboxId, seq, ExecResult)
onCheckpointsb.checkpoint() completed(sandboxId, snapshotId, name?)
onSandboxClosedsb.close() completed(sandboxId)
onSandboxFailedsandbox 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/api
import { 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

OptionTypeDefaultDescription
recordExitCodebooleantrueAdd 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),
});