| 1 | --- |
| 2 | title: Axiom |
| 3 | description: Observability as resources — OTEL datasets, ingest tokens, monitors, notifiers, and dashboards declared next to the code that emits the data. |
| 4 | --- |
| 5 | |
| 6 | Axiom is an event and observability store for logs, traces, and |
| 7 | metrics. Effect already emits OpenTelemetry, and with alchemy the |
| 8 | receiving end is code too: datasets, ingest tokens, monitors, |
| 9 | notifiers, and dashboards live in the same Stack as the Workers and |
| 10 | Functions they observe, so a threshold change is a reviewable diff. |
| 11 | |
| 12 | New here? [Set up credentials](/axiom/setup) first. |
| 13 | |
| 14 | ## Resources |
| 15 | |
| 16 | A `Dataset` is the top-level container. Pick a `kind` per OTEL |
| 17 | signal — it exposes the OTLP endpoints as outputs: |
| 18 | |
| 19 | ```typescript |
| 20 | const traces = yield* Axiom.Dataset("traces", { name: "app-traces", kind: "otel:traces:v1" }); |
| 21 | const logs = yield* Axiom.Dataset("logs", { name: "app-logs", kind: "otel:logs:v1" }); |
| 22 | const metrics = yield* Axiom.Dataset("metrics", { name: "app-metrics", kind: "otel:metrics:v1" }); |
| 23 | ``` |
| 24 | |
| 25 | :::caution |
| 26 | Renaming a dataset or changing its `kind` is a **replacement** — the |
| 27 | old dataset and all its events are deleted. See |
| 28 | [Datasets & Ingest](/axiom/data/ingest) for details. |
| 29 | ::: |
| 30 | |
| 31 | An `ApiToken` mints a least-privilege ingest credential for your |
| 32 | runtime to ship with: |
| 33 | |
| 34 | ```typescript |
| 35 | const ingest = yield* Axiom.ApiToken("ingest", { |
| 36 | name: "prod-ingest", |
| 37 | datasetCapabilities: { |
| 38 | "app-traces": { ingest: ["create"] }, |
| 39 | }, |
| 40 | }); |
| 41 | ``` |
| 42 | |
| 43 | `Monitor` + `Notifier` turn queries into alerts — see |
| 44 | [Monitors & Alerting](/axiom/guides/alerting) for threshold and |
| 45 | anomaly monitors: |
| 46 | |
| 47 | ```typescript |
| 48 | const slack = yield* Axiom.Notifier("ops-slack", { |
| 49 | name: "ops-channel", |
| 50 | properties: { |
| 51 | slack: { slackUrl: process.env.SLACK_WEBHOOK_URL! }, |
| 52 | }, |
| 53 | }); |
| 54 | |
| 55 | yield* Axiom.Monitor("panics", { |
| 56 | name: "Service panic", |
| 57 | type: "MatchEvent", |
| 58 | aplQuery: `['app-logs'] | where message contains "panic:"`, |
| 59 | intervalMinutes: 1, |
| 60 | rangeMinutes: 1, |
| 61 | notifierIds: [slack.id], |
| 62 | }); |
| 63 | ``` |
| 64 | |
| 65 | Beyond alerts, `Dashboard` declares charts as code, `View` saves an |
| 66 | APL query as a virtual dataset, and `Annotation` marks deploys on |
| 67 | your charts — see [Dashboards as Code](/axiom/guides/dashboards). |
| 68 | `VirtualField` derives computed fields on a dataset at query time. |
| 69 | |
| 70 | ## Compose with your cloud |
| 71 | |
| 72 | Wire the dataset's OTLP endpoints and the ingest token into your |
| 73 | Worker or Lambda's environment, and Effect's OpenTelemetry output |
| 74 | flows into Axiom with no code changes — see |
| 75 | [Observability](/testing/observability) for the exporter-as-a-Layer |
| 76 | pattern: |
| 77 | |
| 78 | ```typescript |
| 79 | vars: { |
| 80 | OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: traces.otelTracesEndpoint, |
| 81 | OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: logs.otelLogsEndpoint, |
| 82 | }, |
| 83 | ``` |
| 84 | |
| 85 | For a full end-to-end walkthrough — dataset, token, Worker wiring, |
| 86 | and a monitor on top — follow |
| 87 | [Observability with Axiom](/cloudflare/observability/axiom-observability). |
| 88 | |
| 89 | ## Reference |
| 90 | |
| 91 | [Dataset](/providers/axiom/dataset) · |
| 92 | [ApiToken](/providers/axiom/apitoken) · |
| 93 | [Monitor](/providers/axiom/monitor) · |
| 94 | [Notifier](/providers/axiom/notifier) · |
| 95 | [Dashboard](/providers/axiom/dashboard) · |
| 96 | [Annotation](/providers/axiom/annotation) · |
| 97 | [View](/providers/axiom/view) · |
| 98 | [VirtualField](/providers/axiom/virtualfield) |