Skip to content

What is Axiom?

Axiom stores the events your systems emit, logs, traces and metrics, and lets you query them fast and cheaply, however many there are. You send it OpenTelemetry, which Effect already produces, and query it with APL. On top of the data, monitors alert you, and dashboards show you what’s happening.

Take one setup: a Worker sending its traces and logs to Axiom, with a monitor that pages you on panics. The Worker sends telemetry with an ingest token. Axiom stores it in datasets. A monitor queries a dataset every minute and notifies Slack when it matches.

Organization acmetraceslogsAPLAPLnotifiesWorkeringest tokenapp-tracesDatasetappDashboardapp-logsDatasetpanicsMonitorops-slackNotifier
Everything lives in an organization. Telemetry lands in datasets. Dashboards and monitors query them with APL, and a monitor alerts you through a notifier.

An organization holds your datasets, monitors and dashboards, and your bill. An API token grants specific capabilities: ingest into one dataset, query another, manage monitors. A personal token acts as you, and is what Alchemy deploys with.

Connect it once, in Setup.

A dataset is a collection of events, the unit you send to and query from. An OpenTelemetry dataset has a kind, one per signal: traces, logs or metrics. It exposes the endpoint to send that signal to.

alchemy.run.ts
const traces = yield* Axiom.Dataset("traces", { name: "app-traces", kind: "otel:traces:v1" });

Renaming a dataset or changing its kind replaces it, and its events go with it.

See Datasets & ingest.

Your app sends events over OTLP, OpenTelemetry’s protocol, to a dataset’s endpoint, with a token that may ingest into it. Effect’s tracer and logger already speak OpenTelemetry, so connecting them to Axiom is configuration, not code.

Give your runtime a token that can only ingest, and only into its own datasets:

alchemy.run.ts
const ingest = yield* Axiom.ApiToken("ingest", {
name: "prod-ingest",
datasetCapabilities: { "app-traces": { ingest: ["create"] } },
});

See Observability for exporting from Effect.

APL, Axiom’s query language, filters, aggregates and charts events, in a pipeline that reads left to right:

['app-logs'] | where message contains "panic:" | summarize count() by bin(_time, 1m)

Every monitor, dashboard chart and view is an APL query.

A monitor runs a query on a schedule and fires when its result crosses a line: a count over a threshold, a value outside its usual range, or any event matching at all. A notifier is where it sends the alert: Slack, email, PagerDuty, a webhook.

See Monitors & alerting.

A dashboard is a set of charts, each a query. A view saves a query as a virtual dataset, so others can query its results by name. An annotation marks a moment on your charts, like a deploy, so you can see what changed when.

See Dashboards as code and Annotations.

How @alchemy.run/axiom models these concepts

Section titled “How @alchemy.run/axiom models these concepts”

Each of these concepts is something your Stack declares.

Your token picks the organization, and Axiom.providers() deploys into it. Datasets, tokens, monitors, notifiers, dashboards, views and annotations are resources, in the same Stack as the Workers and Functions they observe. A dataset’s endpoints and a token’s value are outputs you pass to your runtime’s environment. So a new alert, or a changed threshold, is a reviewed change in a pull request.

Next, follow Observability with Axiom for a complete setup on Cloudflare.