Logger
IGNIS gives every helper a scoped ILogger. LoggerFactory builds it from one registered provider - Winston by default, with console, daily-rotating file, and UDP transports built in.
In one example
The smallest real use: get a scoped logger and log with it.
import { LoggerFactory } from '@venizia/ignis-helpers';
const logger = LoggerFactory.getLogger(['UserService']);
logger.info('User created');
// Output: [UserService] User createdLoggerFactory is how BaseHelper creates its internal logger, so every helper in the framework gets a scoped logger the same way, for free.
How it works
- Typed against
ILogger. Every consumer - includingBaseHelper.logger- gets theILoggerinterface, never a concrete class. Winston is the default provider behind it, selected infactory.ts. - Provider-based.
LoggerFactory.use({ provider })selects the app's logger engine once, at the entrypoint. Winston is the default; pino is the throughput option. Every factory-issued logger follows the registration, even one captured at import time. - Scoped and cached.
LoggerFactory.getLogger(scopes)joins the scopes with-and caches the result per scope. The same scope always returns the same instance.BaseHelpercalls this in its constructor, so every helper'sthis.loggercomes pre-scoped. - Custom-backed loggers are the exception.
Logger.get(scope, customWinstonLogger)(from the/winstonsub-path) is NOT cached. Each call returns a fresh wrapper over the instance you passed in. - Method scoping.
.for(methodName)returns a child logger scoped to<scope>-<methodName>(also cached), so each line shows where it came from. - Level floor.
APP_ENV_LOGGER_LEVEL(defaultdebug) sets the logger-level floor. Transports without their own level inherit it. debug()is gated. It emits only whenDEBUG=trueandNODE_ENVis unset or listed inEnvironment.COMMON_ENVS. Extend that set viaAPP_ENV_EXTRA_LOG_ENVS. The check runs once at module load - runtime env changes need a restart.
Log levels
Five levels, each with a direct method: debug, info, warn, error, emerg. The generic .log(level, ...) remains for picking the level dynamically. What each level means, and when to use it, is in the level guide.
Transports
| Transport | Turns on when |
|---|---|
| Console | Always |
| Daily-rotating file | APP_ENV_LOGGER_FOLDER_PATH is set |
UDP (DgramTransport) | All four UDP APP_ENV_LOGGER_DGRAM_* variables are set |
Output shape (plain text or JSON) follows APP_ENV_LOGGER_FORMAT. Color codes appear only on the console, and only in a development NODE_ENV - file and UDP output never carries ANSI escapes. See Color to override.
For extreme hot paths, HfLogger is a separate ring-buffer logger outside this pipeline, with its own usage guide. The Full reference covers everything else, including the ApplicationLogger facade.
Common tasks
Get a scoped logger
Use LoggerFactory.getLogger with an array of scope segments, or ApplicationLogger.get with a single string. Both cache by scope and follow the registered provider.
import { ApplicationLogger, LoggerFactory } from '@venizia/ignis-helpers';
const scoped = LoggerFactory.getLogger(['Payment', 'Stripe']); // [Payment-Stripe]
const direct = ApplicationLogger.get('MyService'); // [MyService]Scope logs to a method
.for() appends a method name to the current scope so every line in that method self-identifies.
class UserService {
private logger = LoggerFactory.getLogger(['UserService']);
async createUser(data: CreateUserDto) {
this.logger.for('createUser').info('Creating user: %j', data);
// Output: [UserService-createUser] Creating user: {...}
}
}Log an Error with %s, never %j
%s routes the error through ErrorPrettier, which projects it down to identity, cause and frames. %j keeps every enumerable own property instead, so a driver error takes its whole query along and a jose error its whole payload. Always pair an Error argument with %s.
logger.error('Failed to create user: %s', error); // prints message + stackA mistaken %j is no longer a silent loss: the formatter projects message and stack in before JSON.stringify runs, which on its own would drop both (they are non-enumerable). It is still the wrong placeholder for an error.
Keep a driver error readable with ErrorPrettier
%s prints the whole object. A pg or drizzle failure carries the statement in message, again in stack, and again in query - one failure floods the log with the same SQL several times. Wrap it:
import { ErrorPrettier } from '@venizia/ignis-helpers';
logger.error('Failed to create user | %s', ErrorPrettier.format({ error }));You get the identity, the root cause with its code, the driver's hint, the full message and the top stack frames - each on its own line, with the message's real newlines intact. The duplicated statement and the noisy driver internals are gone.
Pass includeStack: false when the error is one you raised yourself and the frames add nothing. For a JSON sink, ErrorPrettier.summarize({ error }) returns the same projection as a typed object instead of a string.
Switch the output format
APP_ENV_LOGGER_FORMAT controls plain text (default) vs. JSON output.
APP_ENV_LOGGER_FORMAT=text # 2024-01-11T10:30:00.000Z [APP] info: [UserService] User created
APP_ENV_LOGGER_FORMAT=json # {"level":"info","message":"[UserService] User created", ...}The [APP] label comes from APP_ENV_APPLICATION_NAME (defaults to 'APP').
Enable daily file rotation
Point APP_ENV_LOGGER_FOLDER_PATH at a directory. Rotation frequency, size cap, and retention are also env-driven. Without this variable, no log files are written - console (and UDP, if configured) remain the only outputs.
APP_ENV_LOGGER_FOLDER_PATH=./app_data/logs
APP_ENV_LOGGER_FILE_MAX_FILES=30d| Setting | Default |
|---|---|
| Rotation frequency | 1h |
| Max file size | 100m |
| Retention | 5d |
Full programmatic configuration - custom prefixes, custom retention - is in the Full reference.
Forward logs over UDP
Set all four APP_ENV_LOGGER_DGRAM_* variables - the transport is silently skipped if any one is missing.
APP_ENV_LOGGER_DGRAM_HOST=127.0.0.1
APP_ENV_LOGGER_DGRAM_PORT=5000
APP_ENV_LOGGER_DGRAM_LABEL=my-app
APP_ENV_LOGGER_DGRAM_LEVELS=error,warn,infoSee also
- Full reference - every export, transport option, log level, and edge case
- Services - logging in services
- Controllers - logging in controllers
- Helpers Overview - all available helpers
- Request Tracker Component - request logging
- Winston documentation - underlying logging library
Files:
packages/helpers/src/modules/logger/common/types.ts-ILogger, the contract every consumer types againstpackages/helpers/src/modules/logger/winston/logger.ts-WinstonLogger,Loggeraliaspackages/helpers/src/modules/logger/factory.ts-LoggerFactory,ApplicationLoggerpackages/helpers/src/modules/logger/winston/logger-factory.ts- Winston setup, transports, env configuration