docs

Install for your stack

Pick your language or framework and copy the install and config steps that connect it to Unhandled.

Unhandled stores standard OpenTelemetry data, so every stack connects the same way: something in your process exports OTLP over HTTP with the three headers taken from your DSN. What differs is how much of that is done for you.

Setup

The snippets use a sample DSN and the production environment. In the app, Setup instructions on a service row shows the same steps with that service's endpoint and id filled in, and a new service shows them with its full DSN. There you also pick the environment. The last step follows it: development runs the dev server, and staging or production builds the app and starts the built server. /docs/install?stack=<id> opens a stack directly.

AdonisJS has two options. Unhandled agent installs @unhandled/agent-adonisjs. Already using @adonisjs/otel keeps the official package and only sets its exporter variables, as described in Keep @adonisjs/otel.

Unhandled SDKs

OpenTelemetry SDKs

Coding agents

Already on Sentry

Workers Observability exports each invocation's traces and logs over OTLP, with no SDK in your Worker. Guide

  1. 1

    Create two destinations

    text
    Destination name: unhandled-orders-api-traces
    Destination type: Traces
    OTLP endpoint: https://ingest.example.com/v1/traces
    Custom headers:
      x-api-key: uh_live_7Hq2xR9vLp3sKd8mWn4tYb6c
      x-unhandled-service-id: 0b6f3c1e-8d2a-4f7b-9c5e-2a1d4e6f8b3c
      x-unhandled-env: production
    
    Destination name: unhandled-orders-api-logs
    Destination type: Logs
    OTLP endpoint: https://ingest.example.com/v1/logs
    Custom headers:
      x-api-key: uh_live_7Hq2xR9vLp3sKd8mWn4tYb6c
      x-unhandled-service-id: 0b6f3c1e-8d2a-4f7b-9c5e-2a1d4e6f8b3c
      x-unhandled-env: production

    In the Cloudflare dashboard, Observability, Destinations, Add destination. Destinations belong to the account and fix the environment, so each environment needs its own pair.

  2. 2

    Export from the Worker

    wrangler.jsonc
    "observability": {
      "enabled": true,
      "traces": { "enabled": true, "destinations": ["unhandled-orders-api-traces"] },
      "logs": { "enabled": true, "invocation_logs": false, "destinations": ["unhandled-orders-api-logs"] }
    }

    invocation_logs repeats every request as a log line; the root span already carries it.

  3. 3

    Deploy and send a request

    bash
    npx wrangler deploy

    Only deployed Workers export. wrangler dev sends nothing, and data can take a few minutes to arrive.

Set up with an AI agent

Set up with an AI agent gives you a prompt for Claude Code, Cursor, Codex or any agent that edits files and runs commands. Paste it in the project's root. The prompt carries the DSN, the environment and the OTEL_* variables, and tells the agent to:

  1. Detect the stack from the project's manifest files.
  2. Install the matching Unhandled package, or the official OpenTelemetry SDK for other languages.
  3. Set UNHANDLED_DSN and APP_ENV in the env file the app loads.
  4. Hook up error reporting and set user.id from the signed-in user.
  5. Start the app for the chosen environment and send one request.
  6. Confirm the request arrived.

For the last step, connect the MCP server first. The agent then calls list_traces for the service and environment and finds its own request. Without it, the agent asks you to check Last seen on the service.

The DSN and the headers

A DSN such as https://uh_live_…@ingest.example.com/0b6f3c1e-… holds everything a sender needs. The Unhandled SDKs read it from UNHANDLED_DSN. OpenTelemetry SDKs need it split into parts:

From the DSNOpenTelemetry setting
The origin, https://ingest.example.comOTEL_EXPORTER_OTLP_ENDPOINT
The username, the API keyx-api-key in OTEL_EXPORTER_OTLP_HEADERS
The path, the service idx-unhandled-service-id in OTEL_EXPORTER_OTLP_HEADERS
Your deployment's environmentx-unhandled-env in OTEL_EXPORTER_OTLP_HEADERS

The exporters append /v1/traces, /v1/logs and /v1/metrics to the endpoint. Any OpenTelemetry SDK is the full wire contract.

What each stack fills in

Traces, logs, metrics, issues, requests, queries and external calls work from any SDK that follows the OpenTelemetry semantic conventions. A few pages depend on spans that only some instrumentations produce:

PageNeedsWho creates it
EmailsSpans with email.systemThe AdonisJS agent, for @adonisjs/mail. Other stacks add them by hand.
CommandsA root span marked unhandled.entry_point=cli, or an INTERNAL span with process.executable.nameThe AdonisJS agent, for Ace commands. Other stacks follow the OpenTelemetry CLI conventions.
Usersuser.id or enduser.id on request spansYour auth middleware, in any stack.
System metricsRuntime and host metricsNode.js SDKs report the event loop and V8 heap. Other runtimes report CPU and memory.

Check the data

Send a few requests, then open Settings, Services. The service shows events, a Last seen time and a badge with the language and SDK it reports.