Background Jobs
Log cron jobs, queue consumers and scripts through every sink
runJob runs a function outside a request and writes one final line for it, through transports, the file sink and redaction, the same as a request gets.
import logixlysia from 'logixlysia'
const logs = logixlysia({
config: { service: 'billing', requestId: true }
})
await logs.runJob('nightly-sync', async log => {
const rows = await loadRows()
log.mergeContext({ rows: rows.length })
await pushRows(rows)
})
async function loadRows(): Promise<string[]> {
return ['a', 'b', 'c']
}
async function pushRows(_rows: string[]): Promise<void> {}
The line is labelled JOB, the job name is its path, and it carries the duration and the accumulated context:
JOB /nightly-sync 200 412ms
Outcome
- The final line is always written, even when the job logs lines of its own. A request’s custom log replaces its access line; a job’s does not.
- A job that returns gets status
200. The valuefnreturns is the valuerunJobreturns. - A job that throws gets status
500: logixlysia writes the error line, then rethrows the same error, so your scheduler still sees the failure. - An empty or non-string name rejects with a
TypeErrorbeforefnruns.
Inside helpers
useLogger() returns the job’s logger anywhere under fn, across awaits, without setting useAsyncLocalStorage. After the job settles it is a no-op again.
import { useLogger } from 'logixlysia'
export const markSynced = (count: number): void => {
useLogger().mergeContext({ synced: count })
}
Scripts
A script exits as soon as the job returns, and a batching transport has no other chance to send. End the script with flushLogixlysia, passing the same options object you gave the plugin:
import logixlysia, { flushLogixlysia } from 'logixlysia'
import type { Options } from 'logixlysia'
const options: Options = { config: { service: 'billing' } }
const logs = logixlysia(options)
await logs.runJob('backfill', log => {
log.mergeContext({ batch: 7 })
})
await flushLogixlysia(options)
Sampling
A successful job is head sampled like any other INFO line. With sampling.head: { INFO: 0 } it writes nothing, so give the jobs you care about a tail.paths rule:
sampling: { head: { INFO: 0 }, tail: { paths: ['/nightly-sync'] } }
A job that throws is kept by the ERROR line, along with the lines it buffered. See sampling.