log-grafana-loki
v0.1.0
Published
Structured logging for Node.js with direct Grafana Loki delivery
Readme
log-grafana-loki
Dependency-free structured logging for Node.js with direct delivery to Grafana Loki. Ships with a provisioned local Loki + Grafana stack and a demo API.
Install
npm install log-grafana-lokiUsage
import { createLogger, withLogContext } from 'log-grafana-loki';
const log = createLogger({
level: 'info',
loki: {
url: 'http://localhost:3100',
batching: { maxBatch: 100, flushIntervalMs: 2000, maxQueueSize: 1000 },
},
labels: { app: 'my-service', env: 'production', service: 'api' },
redact: ['pin'],
console: true,
});
log.info('user signed in', { userId: 42 });
const requestLog = log.child({ requestId: 'req-1' });
requestLog.warn('slow upstream', { ms: 1200 });
await withLogContext({ requestId: 'req-2', traceId: 'trace-9' }, async () => {
log.info('inside request context');
});
await log.flush();
await log.close();Configuration
| Option | Default | Notes |
| --- | --- | --- |
| level | info | debug, info, warn, error, fatal |
| loki.url | required | Loki base URL, http or https |
| loki.timeoutMs | 5000 | Per-request HTTP timeout |
| loki.batching.maxBatch | 100 | Flush when this many entries are queued |
| loki.batching.flushIntervalMs | 2000 | Flush at most this often |
| loki.batching.maxQueueSize | 1000 | Oldest entries dropped beyond this |
| loki.retry.maxAttempts | 3 | Total attempts including the first |
| loki.retry.baseDelayMs | 100 | Jittered exponential backoff base |
| loki.retry.maxDelayMs | 1600 | Backoff cap |
| labels | {} | Only app, env, service are allowed |
| redact | built-ins | Extra keys, dot paths, or RegExps |
| console | false | Mirror entries to stderr |
| shutdownTimeoutMs | 5000 | Flush deadline |
| attachShutdownHandlers | true | Auto-register SIGINT/SIGTERM/beforeExit handlers; set false to own the shutdown sequence |
Built-in redaction keys: password, passwd, secret, token,
authorization, cookie, apiKey, set-cookie.
Only app, env, service, and level become Loki stream labels. Every
other field stays in the JSON log line, which keeps cardinality under control.
Local Grafana + Loki
docker compose -f infra/docker-compose.yml up -d- Loki:
http://localhost:3100 - Grafana:
http://localhost:3000(anonymous admin for local development) - Dashboard:
log-grafana-loki overview
The local stack has no authentication and binds to localhost only. Put Loki behind authenticated ingress before exposing it outside a development machine.
Demo
npm run demoSee examples/demo-api/README.md.
Development
npm install
npm test
npm run typecheck
npm run lint
npm run buildPush failures never throw into application code. They produce console warnings
and the affected batch is dropped; an explicit flush() rejects when retries
are exhausted.
