The build function creates a Node.js Transform stream that prettifies Pino log lines. It supports both direct streaming usage and Pino v7+ transport protocol with automatic configuration detection.
Creates a transform stream for prettifying logs with automatic Pino configuration handling.
/**
* Constructs a prettifier and transform stream for prettifying logs
* @param opts - Configuration options (extends PrettyOptions with destination)
* @returns Transform stream with OnUnknown interface for handling non-JSON lines
*/
function build(opts?: BuildStreamOpts): PrettyStream;
interface BuildStreamOpts extends PrettyOptions {
destination?: string | number | object | NodeJS.WritableStream;
append?: boolean;
mkdir?: boolean;
sync?: boolean;
}
type PrettyStream = Transform & OnUnknown;Usage Examples:
const pinoPretty = require('pino-pretty');
// Basic stream with default options
const stream = pinoPretty();
// Stream with custom options
const customStream = pinoPretty({
colorize: true,
translateTime: 'SYS:standard',
ignore: 'pid,hostname',
singleLine: false
});
// Stream writing to a file
const fileStream = pinoPretty({
destination: './logs/pretty.log',
mkdir: true,
append: true,
colorize: false
});
// Stream with sonic-boom instance for advanced control
const SonicBoom = require('sonic-boom');
const advancedStream = pinoPretty({
destination: new SonicBoom({
dest: './logs/app.log',
mkdir: true,
sync: false
}),
colorize: false
});Use as a Pino v7+ transport with automatic configuration.
// Transport target usage (Pino automatically calls build)
const pino = require('pino');
const logger = pino({
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'HH:MM:ss',
ignore: 'pid,hostname'
}
}
});Usage Examples:
const pino = require('pino');
// Basic transport
const logger = pino({
transport: {
target: 'pino-pretty'
}
});
// Transport with custom options
const customLogger = pino({
transport: {
target: 'pino-pretty',
options: {
colorize: true,
levelFirst: true,
translateTime: 'SYS:yyyy-mm-dd HH:MM:ss',
messageFormat: '{levelLabel} - {pid} - {msg}',
ignore: 'hostname'
}
}
});
// Multiple transports (pretty + file)
const multiLogger = pino({
transport: {
targets: [
{
target: 'pino-pretty',
options: { colorize: true },
level: 'info'
},
{
target: 'pino/file',
options: { destination: './app.log' },
level: 'trace'
}
]
}
});Use the stream directly with Pino logger instances.
// Create logger with pino-pretty stream
const pino = require('pino');
const pretty = require('pino-pretty');
const stream = pretty(options);
const logger = pino(stream);
// With pino options
const logger = pino(pinoOptions, stream);Usage Examples:
const pino = require('pino');
const pretty = require('pino-pretty');
// Basic logger with pretty stream
const stream = pretty({ colorize: true });
const logger = pino(stream);
logger.info('Hello');
// Logger with pino options
const stream2 = pretty({
colorize: true,
translateTime: 'HH:MM:ss'
});
const logger2 = pino({ level: 'debug' }, stream2);
logger2.debug('Debug message');
// Synchronous stream for testing (e.g., with Jest)
const syncStream = pretty({
sync: true,
colorize: false
});
const testLogger = pino(syncStream);The stream automatically detects and responds to Pino configuration messages.
// When Pino sends PINO_CONFIG message, pino-pretty automatically updates:
// - messageKey from Pino's configuration
// - errorLikeObjectKeys (adds Pino's errorKey)
// - customLevels from Pino's level configuration
// This happens automatically - no code needed
// The stream listens for PINO_CONFIG and reconfigures itselfBehavior:
When used as a Pino transport or stream, pino-pretty listens for special PINO_CONFIG messages from Pino v8.21.0+. When received, it automatically synchronizes:
messageKey - Uses Pino's configured message keyerrorLikeObjectKeys - Merges with Pino's error keycustomLevels - Uses Pino's level configurationThis ensures pino-pretty stays synchronized with Pino's configuration without manual setup.
The destination option supports multiple output types.
/**
* Destination options for prettified output
*/
interface DestinationOptions {
// File descriptor (1 = stdout, 2 = stderr)
destination?: number;
// File path
destination?: string;
// WritableStream instance
destination?: NodeJS.WritableStream;
// SonicBoom instance for advanced control
destination?: object; // SonicBoom instance
}Usage Examples:
const pinoPretty = require('pino-pretty');
// Write to stdout (default)
const stdout = pinoPretty({ destination: 1 });
// Write to stderr
const stderr = pinoPretty({ destination: 2 });
// Write to file path
const fileOut = pinoPretty({
destination: './logs/app.log',
mkdir: true, // Create directory if needed
append: true // Append to existing file
});
// Write to custom writable stream
const fs = require('fs');
const customStream = fs.createWriteStream('./custom.log');
const customOut = pinoPretty({ destination: customStream });
// Async file writing (default)
const asyncFile = pinoPretty({
destination: './logs/async.log',
sync: false // Default
});
// Sync file writing (useful for testing)
const syncFile = pinoPretty({
destination: './logs/sync.log',
sync: true
});The stream handles non-JSON lines by passing them through unchanged.
/**
* OnUnknown interface for handling non-JSON log lines
* Non-JSON lines are written directly to destination with newline
*/
interface OnUnknown {
// Event fired when non-JSON line is encountered
on(event: 'unknown', handler: (line: string) => void): this;
}Behavior:
When the stream encounters a line that:
The line is passed through unchanged with a newline appended, maintaining the original text in the output.
Usage Example:
const pinoPretty = require('pino-pretty');
const stream = pinoPretty({ colorize: true });
// Handle unknown lines manually if needed
stream.on('unknown', (line) => {
console.error('Non-JSON line:', line);
});