Appearance
Node
Install
sh
npm install simpledatalogs
npx simpledatalogs init # adds SIMPLEDATALOGS_KEY to .env and writes simpledatalogs.js (.mjs in CommonJS projects)Use a secret key (sdl_sec_…) on servers.
Add it
js
// simpledatalogs.js
import { init } from 'simpledatalogs'
export const sdl = init({ key: process.env.SIMPLEDATALOGS_KEY, autocapture: true })js
import { sdl } from './simpledatalogs.js'
sdl.track('job_finished', { queue: 'emails', duration_ms: 812 })
sdl.log('error', 'Payment failed', { order_id: 7 })
process.on('SIGTERM', async () => {
await sdl.shutdown() // sends the last batch
process.exit(0)
})In Node, autocapture: true means one thing: an uncaught exception is sent as a critical log line with its stack, then the process exits with code 1, as Node would have. Leave it out to send only your own calls. There are no page views or sessions on a server.
pino
A second stream turns each pino line into a log line:
js
import pino from 'pino'
import { Writable } from 'node:stream'
import { sdl } from './simpledatalogs.js'
// pino's numeric levels to simpledatalogs levels.
const levelNames = { 10: 'debug', 20: 'debug', 30: 'info', 40: 'warning', 50: 'error', 60: 'critical' }
const toSimpleDataLogs = new Writable({
write(chunk, _encoding, callback) {
const { level, msg, time, pid, hostname, ...fields } = JSON.parse(chunk)
sdl.log(levelNames[level] ?? 'info', msg ?? '', fields)
callback()
},
})
export const logger = pino({}, pino.multistream([{ stream: process.stdout }, { stream: toSimpleDataLogs }]))winston
js
import winston from 'winston'
import Transport from 'winston-transport'
import { sdl } from './simpledatalogs.js'
// winston's npm levels to simpledatalogs levels.
const levelNames = { error: 'error', warn: 'warning', info: 'info', http: 'debug', verbose: 'debug', debug: 'debug', silly: 'debug' }
class SimpleDataLogsTransport extends Transport {
log(info, callback) {
const { level, message, ...fields } = info
sdl.log(levelNames[level] ?? 'info', message, fields)
callback()
}
}
export const logger = winston.createLogger({ transports: [new winston.transports.Console(), new SimpleDataLogsTransport()] })Both recipes go through the SDK, so lines batch, retry and carry an event_id. Fields must be strings, numbers or booleans; nested objects are skipped with one warning.
In the first minute
- Your
track()events on the dashboard, and log lines on the Logs tab. - With
autocapture: true, a crash shows up as acriticalline withstack. - Lines go out every 10 seconds (5 with
NODE_ENV=development) or at 50;await sdl.flush()sends them now.
Autocapture defaults (Node)
| Feature | autocapture: true |
|---|---|
| Uncaught exceptions | on: logged, flushed for up to 2 s, then exit code 1 |
| Page views, sessions, browser errors | not in Node |