Guides

Logging

Cronbake logs to the console by default. Pass your own logger to the baker or to a single job.

On this page

The Logger interface

A logger is any object with these four methods.

interface Logger {
  info(message: any, ...args: any[]): void;
  warn(message: any, ...args: any[]): void;
  error(message: any, ...args: any[]): void;
  debug(message: any, ...args: any[]): void;
}

Setting a logger

Set one for the whole baker, and override it for any job that needs its own.

import Baker, { type Logger } from "cronbake";

const logger: Logger = {
  info: (message, ...args) => console.log(`[cron] ${message}`, ...args),
  warn: (message, ...args) => console.warn(`[cron] ${message}`, ...args),
  error: (message, ...args) => console.error(`[cron] ${message}`, ...args),
  debug: (message, ...args) => console.debug(`[cron] ${message}`, ...args),
};

const baker = Baker.create({ logger });

baker.add({
  name: "charge-cards",
  cron: "@hourly",
  logger: paymentsLogger, // this job logs here instead
  callback: chargeCards,
});

A job’s logger is used for messages about that job. Messages about saving and restoring state always go to the baker’s logger.

What gets logged

Cronbake logs very little, and only warn and info are used at the moment.

Level Message
warn A callback failed and no onError handler is set
warn onTick, onComplete or onError threw
warn State couldn’t be saved or restored, or a saved job was invalid
warn A restored job ran with its placeholder callback
info Restored 3 cron jobs from persistence

Structured loggers

Cronbake calls each method with a message string, followed by extra values such as the error: logger.warn("Failed to save state:", error). Libraries differ in what they do with those extra values. Pino, for example, only uses them to fill in placeholders, so the error would be lost. A thin adapter fixes that by passing the error under the key Pino serializes.

import { type Logger } from "cronbake";

const fields = (args: unknown[]) => ({ err: args.find((arg) => arg instanceof Error) });

const logger: Logger = {
  info: (message, ...args) => pinoLogger.info(fields(args), String(message)),
  warn: (message, ...args) => pinoLogger.warn(fields(args), String(message)),
  error: (message, ...args) => pinoLogger.error(fields(args), String(message)),
  debug: (message, ...args) => pinoLogger.debug(fields(args), String(message)),
};

Silencing it

Pass a logger that does nothing. Failures still appear in the metrics and still reach any onError handler.

const noop = () => {};

const baker = Baker.create({
  logger: { info: noop, warn: noop, error: noop, debug: noop },
});
esc

Try overlap, restore or timezone.