Super fast, all natural JSON logger with exceptional performance for structured logging applications.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Create specialized logger instances that inherit parent settings while adding contextual bindings. Child loggers provide a way to add consistent metadata to related log messages without repeating the same data in every log call.
Create a child logger that inherits parent configuration and adds specific bindings.
/**
* Creates a child logger with additional bindings
* @param bindings - Key-value pairs to include in all child logger messages
* @param options - Optional child-specific configuration overrides
* @returns New logger instance that inherits parent settings
*/
child(bindings: Bindings, options?: ChildLoggerOptions): Logger;
type Bindings = Record<string, any>;
interface ChildLoggerOptions {
/** Override log level for this child */
level?: string;
/** Additional or override serializers */
serializers?: { [key: string]: SerializerFn };
/** Custom levels for this child */
customLevels?: { [level: string]: number };
/** Child-specific formatters */
formatters?: {
level?: (label: string, number: number) => object;
bindings?: (bindings: Bindings) => object;
log?: (object: object) => object;
};
/** Child-specific redaction rules */
redact?: string[] | RedactOptions;
/** Message prefix for this child */
msgPrefix?: string;
}Usage Examples:
const logger = pino();
// Simple child with user context
const userLogger = logger.child({ userId: 123, module: 'auth' });
userLogger.info('User logged in');
// Output: {"level":30,"time":...,"msg":"User logged in","userId":123,"module":"auth",...}
// Child with request context
const requestLogger = logger.child({
requestId: 'req-456',
method: 'POST',
path: '/api/users'
});
requestLogger.info('Processing request');
requestLogger.error({ error: 'ValidationError' }, 'Request validation failed');
// Child with options override
const debugLogger = logger.child(
{ component: 'database' },
{ level: 'debug' }
);
debugLogger.debug('Executing query');Create child loggers from other child loggers to build hierarchical context.
// Child loggers can create their own child loggersUsage Examples:
const logger = pino();
// Parent child for request context
const requestLogger = logger.child({ requestId: 'req-789' });
// Child of child for specific operation
const dbLogger = requestLogger.child({ operation: 'user-lookup' });
const cacheLogger = requestLogger.child({ operation: 'cache-check' });
dbLogger.info('Querying user table');
cacheLogger.info('Cache miss');
// All include both requestId and operation in outputRetrieve and modify bindings on existing logger instances.
/**
* Returns current logger bindings
* @returns Object containing all current bindings
*/
bindings(): Bindings;
/**
* Adds new bindings to existing logger
* Note: Does not overwrite existing bindings, may result in duplicate keys
* @param bindings - Additional key-value pairs to bind
*/
setBindings(bindings: Bindings): void;Usage Examples:
const logger = pino();
const child = logger.child({ userId: 123, module: 'auth' });
// Get current bindings
const currentBindings = child.bindings();
console.log(currentBindings); // { userId: 123, module: 'auth' }
// Add more bindings
child.setBindings({ sessionId: 'sess-456', ip: '192.168.1.100' });
child.info('Action performed');
// Output includes: userId, module, sessionId, ipChild loggers inherit all configuration from their parent logger.
Inherited Properties:
Usage Examples:
const parentLogger = pino({
level: 'debug',
name: 'my-app',
serializers: {
user: (user) => ({ id: user.id, name: user.name })
}
});
// Child inherits debug level, name, and serializers
const child = parentLogger.child({ module: 'payments' });
child.debug('Processing payment'); // Will output (inherits debug level)
child.info({ user: userObject }, 'Payment completed'); // Uses inherited serializerChild loggers can have independent log levels from their parents.
Usage Examples:
const logger = pino({ level: 'info' });
// Child with more verbose logging
const debugChild = logger.child(
{ component: 'auth' },
{ level: 'debug' }
);
// Child with less verbose logging
const errorChild = logger.child(
{ component: 'external-api' },
{ level: 'error' }
);
logger.debug('Parent debug'); // Not logged (parent is 'info')
debugChild.debug('Child debug'); // Logged (child is 'debug')
errorChild.info('Child info'); // Not logged (child is 'error')Hook into child logger creation for custom initialization.
interface LoggerOptions {
/** Callback executed when child logger is created */
onChild?: OnChildCallback;
}
type OnChildCallback = (child: Logger) => void;
interface Logger {
/** Current callback for child creation */
onChild: OnChildCallback;
}Usage Examples:
const logger = pino({
onChild: (child) => {
// Add automatic tracking
child.setBindings({
childCreatedAt: new Date().toISOString(),
parentName: logger.bindings().name || 'root'
});
}
});
const child = logger.child({ userId: 123 });
// Automatically includes childCreatedAt and parentNameCreate child loggers for request tracking in web applications.
Usage Examples:
// Express middleware example
app.use((req, res, next) => {
req.logger = logger.child({
requestId: generateRequestId(),
method: req.method,
path: req.path,
userAgent: req.get('User-Agent')
});
next();
});
// Use in route handlers
app.post('/users', (req, res) => {
req.logger.info('Creating new user');
// Service layer inherits request context
const serviceLogger = req.logger.child({ service: 'user-service' });
serviceLogger.debug('Validating user data');
// Database layer adds more context
const dbLogger = serviceLogger.child({ operation: 'user-insert' });
dbLogger.info('Inserting user record');
});Organize logging by application modules using child loggers.
Usage Examples:
// Application setup
const rootLogger = pino({ name: 'my-app' });
// Module loggers
const authLogger = rootLogger.child({ module: 'authentication' });
const dbLogger = rootLogger.child({ module: 'database' });
const apiLogger = rootLogger.child({ module: 'api' });
// Sub-module loggers
const userAuthLogger = authLogger.child({ submodule: 'user-auth' });
const sessionLogger = authLogger.child({ submodule: 'session' });
// Usage maintains hierarchy
userAuthLogger.info('User login attempt');
sessionLogger.info('Session created');
// Both include module: 'authentication' plus their submoduleUse child loggers to maintain error context through async operations.
Usage Examples:
async function processOrder(orderId, logger = rootLogger) {
const orderLogger = logger.child({ orderId, operation: 'process-order' });
try {
orderLogger.info('Starting order processing');
// Each step maintains order context
await validateOrder(orderLogger);
await chargePayment(orderLogger);
await updateInventory(orderLogger);
orderLogger.info('Order processing completed');
} catch (error) {
orderLogger.error({ error }, 'Order processing failed');
throw error;
}
}
async function validateOrder(logger) {
const validationLogger = logger.child({ step: 'validation' });
validationLogger.debug('Validating order data');
// Any errors here include orderId, operation, and step context
}Install with Tessl CLI
npx tessl i tessl/npm-pino