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 to send evlog wide events to Axiom.
1. Identify which framework I'm using and follow its evlog integration pattern
2. Install evlog if not already installed
3. Import createAxiomDrain from 'evlog/axiom'
4. Wire createAxiomDrain() into my framework's drain configuration
5. Set AXIOM_TOKEN and AXIOM_DATASET environment variables in .env
6. Test by triggering a request and checking the Axiom dataset
Adapter docs: https://www.evlog.dev/adapters/axiom
Framework setup: https://www.evlog.dev/frameworks
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_TOKEN=xaat-your-token-here
AXIOM_DATASET=your-dataset-name
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())
})
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_TOKEN | NUXT_AXIOM_TOKEN | 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: {
token: '', // Set via NUXT_AXIOM_TOKEN
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 |
|---|---|---|---|
token | string | - | API token (required) |
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 token error
[evlog/axiom] Missing dataset or token. Set AXIOM_DATASET and AXIOM_TOKEN
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, {
token: 'xaat-xxx',
dataset: 'logs',
})
// Send multiple events in one request
await sendBatchToAxiom(events, {
token: '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