Axiom Adapter
Axiom is a cloud-native logging platform with powerful querying capabilities. The evlog Axiom adapter sends your wide events directly to Axiom datasets.
Add the Axiom drain adapter
Installation
The Axiom adapter comes bundled with evlog:
import { createAxiomDrain } from 'evlog/axiom'
Quick Start
1. Get your Axiom credentials
- Create an Axiom account
- Create a dataset for your logs
- Generate an API token with ingest permissions
2. Set environment variables
AXIOM_API_KEY=xaat-your-token-here
AXIOM_DATASET=your-dataset-name
xaat-...). evlog names the config field apiKey for consistency across adapters. Legacy token / AXIOM_TOKEN still work until the next major release.3. Wire the drain to your framework
// server/plugins/evlog-drain.ts
import { createAxiomDrain } from 'evlog/axiom'
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('evlog:drain', createAxiomDrain())
})
// lib/evlog.ts
import { createEvlog } from 'evlog/next'
import { createAxiomDrain } from 'evlog/axiom'
export const { withEvlog, useLogger, log, createError } = createEvlog({
service: 'my-app',
drain: createAxiomDrain(),
})
import { createAxiomDrain } from 'evlog/axiom'
app.use(evlog({ drain: createAxiomDrain() }))
import { createAxiomDrain } from 'evlog/axiom'
app.use(evlog({ drain: createAxiomDrain() }))
import { createAxiomDrain } from 'evlog/axiom'
await app.register(evlog, { drain: createAxiomDrain() })
import { createAxiomDrain } from 'evlog/axiom'
app.use(evlog({ drain: createAxiomDrain() }))
import { createAxiomDrain } from 'evlog/axiom'
EvlogModule.forRoot({ drain: createAxiomDrain() })
import { createAxiomDrain } from 'evlog/axiom'
initLogger({ drain: createAxiomDrain() })
That's it! Your logs will now appear in Axiom.
Configuration
The adapter reads configuration from multiple sources (highest priority first):
- Overrides passed to
createAxiomDrain() - Runtime config at
runtimeConfig.axiom(Nuxt/Nitro only) - Environment variables (
AXIOM_*orNUXT_AXIOM_*)
Environment Variables
| Variable | Nuxt alias | Description |
|---|---|---|
AXIOM_API_KEY | NUXT_AXIOM_API_KEY | Axiom API token with ingest permissions |
AXIOM_DATASET | NUXT_AXIOM_DATASET | Dataset name to ingest logs into |
AXIOM_ORG_ID | NUXT_AXIOM_ORG_ID | Organization ID (required for Personal Access Tokens) |
AXIOM_EDGE_URL | NUXT_AXIOM_EDGE_URL | Edge base URL for ingest/query (for edge deployments) |
AXIOM_URL | NUXT_AXIOM_URL | API base URL (legacy/default ingest endpoint) |
NUXT_ prefix so values are available via useRuntimeConfig(). In all other frameworks, use the unprefixed variables.Runtime Config (Nuxt only)
Configure via nuxt.config.ts for type-safe configuration:
export default defineNuxtConfig({
runtimeConfig: {
axiom: {
apiKey: '', // Set via NUXT_AXIOM_API_KEY
dataset: '', // Set via NUXT_AXIOM_DATASET
},
},
})
Override Options
Pass options directly to override any configuration:
const drain = createAxiomDrain({
dataset: 'production-logs',
timeout: 10000,
})
Full Configuration Reference
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | - | Axiom API token (required) |
token | string | - | Deprecated. Use apiKey instead |
dataset | string | - | Dataset name (required) |
orgId | string | - | Organization ID (for PAT tokens) |
edgeUrl | string | - | Edge URL for ingest. Uses /v1/ingest/{dataset} when no path is provided; custom paths are used as-is (trailing slash trimmed). Mutually exclusive with baseUrl |
baseUrl | string | https://api.axiom.co | API base URL (/v1/datasets/{dataset}/ingest), mutually exclusive with edgeUrl |
timeout | number | 5000 | Request timeout in milliseconds |
Querying Logs in Axiom
evlog sends structured wide events that are perfect for Axiom's APL query language:
// Find slow requests
['your-dataset']
| where duration > 1000
| project timestamp, path, duration, status
// Error rate by endpoint
['your-dataset']
| where level == "error"
| summarize count() by path
| order by count_ desc
// Request volume over time
['your-dataset']
| summarize count() by bin(timestamp, 1h)
| render timechart
Troubleshooting
Missing dataset or apiKey error
[evlog/axiom] Missing dataset or apiKey. Set NUXT_AXIOM_API_KEY/NUXT_AXIOM_DATASET env vars or pass to createAxiomDrain()
Make sure your environment variables are set and the server was restarted after adding them.
401 Unauthorized
Your token may be invalid or expired. Generate a new token in the Axiom dashboard with Ingest permissions.
403 Forbidden with PAT tokens
Personal Access Tokens require an organization ID:
AXIOM_ORG_ID=your-org-id
Direct API Usage
For advanced use cases, you can use the lower-level functions:
import { sendToAxiom, sendBatchToAxiom } from 'evlog/axiom'
// Send a single event
await sendToAxiom(event, {
apiKey: 'xaat-xxx',
dataset: 'logs',
})
// Send multiple events in one request
await sendBatchToAxiom(events, {
apiKey: 'xaat-xxx',
dataset: 'logs',
})
Next Steps
- OTLP Adapter - Send logs via OpenTelemetry Protocol
- PostHog Adapter - Send logs to PostHog
- Custom Adapters - Build your own adapter
- Best Practices - Security and production tips