Skip to content

Logging

By default, Restura logs to the console. You can swap in any logger by passing an adapter to restura.init() or by calling setLogger() before your app starts:

await restura.init(app, authHandler, pool, {
logger: myAdapter
});
// or, before restura.init():
setLogger(myAdapter);

Your adapter must satisfy this interface, exported from @restura/core:

import type { LogLevel } from '@restura/core';
interface ResturaLogger {
readonly level: LogLevel; // 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace'
fatal(msg: unknown, ...args: unknown[]): void;
error(msg: unknown, ...args: unknown[]): void;
warn(msg: unknown, ...args: unknown[]): void;
info(msg: unknown, ...args: unknown[]): void;
debug(msg: unknown, ...args: unknown[]): void;
trace(msg: unknown, ...args: unknown[]): void;
}

Winston uses npm log levels and doesn’t have fatal or trace, so map them to the nearest equivalents:

import winston from 'winston';
import { type ResturaLogger, type LogLevel } from '@restura/core';
const LEVEL_MAP: Record<LogLevel, string> = {
fatal: 'error',
error: 'error',
warn: 'warn',
info: 'info',
debug: 'debug',
trace: 'silly'
};
function createWinstonAdapter(level: LogLevel = 'info'): ResturaLogger {
const win = winston.createLogger({
level: LEVEL_MAP[level],
format: winston.format.json(),
transports: [new winston.transports.Console()]
});
return {
level,
fatal: (msg, ...args) => win.error(String(msg), ...args),
error: (msg, ...args) => win.error(String(msg), ...args),
warn: (msg, ...args) => win.warn(String(msg), ...args),
info: (msg, ...args) => win.info(String(msg), ...args),
debug: (msg, ...args) => win.debug(String(msg), ...args),
trace: (msg, ...args) => win.silly(String(msg), ...args)
};
}
await restura.init(app, authHandler, pool, {
logger: createWinstonAdapter('debug')
});

Existing Projects (importing logger from @restura/core)

Section titled “Existing Projects (importing logger from @restura/core)”

If your project already imports logger directly from @restura/core, call createLogger and setLogger at the very top of your app.ts (immediately after imports) so the logger is configured before anything else runs:

// app.ts
import { createLogger } from '@restura/logger';
import { setLogger } from '@restura/core';
const logger = createLogger({ level: 'info' });
setLogger(logger);
// rest of your app setup...

For new projects, create a dedicated logger.ts file local to your project and import from that everywhere — instead of reaching into @restura/core for a logger instance:

// src/logger.ts
import { createLogger } from '@restura/logger';
export const logger = createLogger({ level: 'info' });

Then import it in your app.ts and pass it to restura.init():

// app.ts
import { logger } from './logger';
await restura.init(app, authHandler, pool, { logger });

Both the default console logger and @restura/logger respect the RESTURA_LOG_LEVEL environment variable. This lets you change log verbosity without modifying code — useful for production deployments or debugging in specific environments:

Terminal window
RESTURA_LOG_LEVEL=debug node server.js

Valid values are fatal, error, warn, info, debug, and trace. The default is info if the variable is not set or contains an invalid value.

When using @restura/logger, an explicit level passed to createLogger always takes priority over the environment variable:

// uses 'warn' regardless of RESTURA_LOG_LEVEL
createLogger({ level: 'warn' });
// uses RESTURA_LOG_LEVEL if set, otherwise 'info'
createLogger();