Skip to main content
This is a self-hosting guide. The hosted product at https://www.orcapods.ai needs none of this — sign in and go.

Overview

Every Orca binary ships with three observability pillars out of the box: No instrumentation code is required. The HTTP metrics endpoint is registered by each service process.

Public Status Page

The standalone status service serves the public status page and JSON endpoints under /api/*, including GET /api/status, GET /api/incidents, and GET /api/history. The dashboard sidebar and landing footer show a live status indicator by polling the status endpoint every 60 seconds, then link to the status page. The dashboard reads its status page URL from the VITE_STATUS_URL environment variable; set it to your deployed status service. The landing site reads its status page URL from landing/src/content/site.ts. Browser reads are controlled by the status service’s STATUS_ALLOWED_ORIGINS allowlist. Set it to a comma-separated list of first-party dashboard and landing origins that may read /api/* cross-origin. An empty value allows same-origin reads only, and a literal * restores wildcard CORS.
The poller opens an incident after a component reports degraded or down for INCIDENT_OPEN_AFTER consecutive polls, resolves it after INCIDENT_RESOLVE_AFTER consecutive operational polls, and worsens an open degraded incident when the component becomes down. Defaults are INCIDENT_OPEN_AFTER=2 and INCIDENT_RESOLVE_AFTER=3.

Metrics

The conductor, runner, and standalone VirtualFS server expose Prometheus metrics at /metrics:

Shared Runtime Metrics

These collectors are registered by runner processes and by conductor components that execute runtime work locally.

Conductor Metrics

Planner Metrics

VirtualFS Metrics

These collectors are registered by vfs serve. Dispatcher labels keep mount names and statuses bounded, and HTTP path labels use the matched http.ServeMux pattern instead of raw tenant paths.

Scrape Configuration


Structured Logs

Orca uses go.uber.org/zap for machine-parseable logging. Most Go services emit JSON by default; vfs serve defaults to a compact console log format and switches to JSON with LOG_FORMAT=json. The VirtualFS HTTP API emits an http.request access log for every request with request_id, method, routed path, status, duration, and remote address. Handler error sites also log structured warning or error events with the same request_id, such as auth.unauthorized, exec.executor_failed, cat.dispatch_failed, upload.write_failed, and tree.list_failed, so a failed request can be correlated with the underlying auth, dispatcher, cache, presign, upload, or executor error. The conductor planner emits planner.run_aborted when a workflow run goroutine exits before execution, with plan_id, reason, and error fields. reason is no_tenant when the planner reached storage without tenant context, and store_get for other workflow-store lookup failures. Replay submission failures are logged as planner.replay_submit_failed. The conductor artifact path emits artifacts.bucket_unavailable at fatal level during startup when S3_BUCKET is configured but the bucket cannot be listed with the configured endpoint and credentials. If INTERNAL_S3_BUCKET is configured, the conductor also probes that internal run-event bucket; failures emit internal_artifacts.bucket_unavailable at fatal level, while non-fatal initialization errors emit internal_artifacts.init_failed and fall back to the primary artifact bucket. S3-backed run-event persistence emits runs.s3.events_degraded once per run when writing the JSONL event object fails; the log includes run_id, object key, buffered_bytes, final, and error.

Runner Sandbox Boot Log Lines

Runner startup logs the sandbox manager state so operators can tell whether each provider was registered or skipped: Sandbox provider-event handling emits sandbox_event.unknown_provider or sandbox_event.undecodable when a delivery is ignored, and sandbox_event.invalidated with provider, sandbox_id, kind, and matching leases after an accepted event is applied. sandbox_event.fanout_shed is a warning that the 32 concurrent fan-out slots were full; the webhook still received 202, but cached liveness for those sandboxes stays stale until the next provider probe.

Sandbox Worker Lifecycle Log Lines

A workerMode: "sandbox" session runs a paid sandbox for its whole life, so these lines are the cost and correctness trail for it: A provider auto-stop frees compute but not disk: a stopped cloud sandbox still holds its full disk allocation, and only deletion or archiving releases it. Orphans left by a runner that died without releasing its leases therefore accumulate against the provider’s disk quota and eventually fail every new launch with a quota error, even though nothing is running. WORKER_AUTO_ARCHIVE is what bounds that; see the local-development guide.

VirtualFS Boot Log Lines

vfs serve emits the following structured log events during startup for each backend it attempts to initialize: Per-mount availability is also visible at runtime via GET /vfs/mounts — check the status and reason fields.

Log Fields

Common fields included on structured log entries:

Log Levels

Set LOG_LEVEL=debug on any Go service for verbose output.

Querying Logs with jq


Distributed Tracing

Orca exports OpenTelemetry traces in OTLP format. Configure the exporter endpoint:

Trace Coverage

Traces span the full request lifecycle: Trace context is propagated via standard W3C traceparent headers. VirtualFS adds spans for inbound HTTP requests, dispatcher operations, and Workspace.Execute calls when OTEL_EXPORTER_OTLP_ENDPOINT is set.

Jaeger Docker Compose Integration

Then visit http://localhost:16686 to see traces.

Health Checks

The conductor, runner, VirtualFS, and billing service expose /healthz:
Use these for liveness probes in Kubernetes and load balancer health checks.

Grafana Dashboard

The metrics above compose naturally into a Grafana dashboard against your Prometheus data source (Dashboards → Import, or build from scratch). A useful starting layout includes panels for:
  • Active sessions per runner
  • Run throughput (runs/min)
  • Run duration percentiles (p50, p95, p99)
  • Token usage rate
  • Tool call breakdown
  • Sidecar error rate
  • Plan node throughput and repair counts

Alerting Examples


Centralized Logging (OTLP)

Beyond stdout, every service can export structured logs over OTLP to any OpenTelemetry-compatible backend, such as SigNoz, Grafana, Datadog, or Honeycomb. OTLP log export is additive: stdout logging is never affected, so whatever log collection your platform already does keeps working.

Ingest path

Run an OpenTelemetry Collector between the services and your backend. It gives you one place for batching and attribute transforms, and lets you switch backends without touching service configuration.

Environment variables

Service name values: When OTEL_EXPORTER_OTLP_ENDPOINT is unset or OTEL_LOGS_ENABLED=false, the logs exporter is a no-op and the service continues normally. Stdout is never affected by the flag.

Log-to-trace correlation

When OTEL_LOGS_ENABLED=true, the otelzap bridge attaches the active span’s trace_id and span_id to each log record. Any backend that links logs and traces by these fields (most do) gives you click-through from a log line to its trace without manual correlation queries.

Suggested starting points

  • Build your primary triage view as a saved log query filtering severity_text IN (ERROR, FATAL) grouped by service.name.
  • Retention of around 15 days for logs and 7 days for traces is a reasonable starting point; tune to your volume and budget.