0
# Streams
1
2
Optimized destination streams and multistream functionality for directing logs to multiple outputs with high performance. Pino provides specialized stream implementations that offer significantly better throughput than standard Node.js streams.
3
4
## Capabilities
5
6
### Destination Streams
7
8
Create high-performance destination streams using Sonic Boom for optimal log writing throughput.
9
10
```typescript { .api }
11
/**
12
* Create a high-performance destination stream
13
* @param dest - File descriptor, path, stream, or options object
14
* @returns SonicBoom stream optimized for log writing
15
*/
16
function destination(
17
dest?: number | string | object | DestinationStream | NodeJS.WritableStream | SonicBoomOpts
18
): SonicBoom;
19
20
interface SonicBoomOpts {
21
/** File descriptor or path for output */
22
dest?: number | string;
23
24
/** Minimum buffer size before flushing */
25
minLength?: number;
26
27
/** Enable synchronous writing */
28
sync?: boolean;
29
30
/** Append to existing file */
31
append?: boolean;
32
33
/** Create directory if needed */
34
mkdir?: boolean;
35
36
/** File mode for created files */
37
mode?: number;
38
39
/** Retry on EMFILE/ENFILE errors */
40
retryEAGAIN?: (err: NodeJS.ErrnoException, writeBufferLen: number, fnName: string) => boolean;
41
42
/** Custom file system module */
43
fsync?: boolean;
44
}
45
46
interface SonicBoom {
47
/** Write data to the stream */
48
write(data: string): boolean;
49
50
/** Flush buffered data */
51
flush(cb?: (err?: Error) => void): void;
52
53
/** End the stream */
54
end(cb?: () => void): void;
55
56
/** Destroy the stream */
57
destroy(): void;
58
59
/** Check if stream was destroyed */
60
destroyed: boolean;
61
62
/** Get current file descriptor */
63
fd: number;
64
65
/** Reopen the file (useful for log rotation) */
66
reopen(file?: string | number): void;
67
}
68
```
69
70
**Usage Examples:**
71
72
```javascript
73
// Default stdout destination
74
const logger = pino(pino.destination());
75
76
// File destination
77
const logger = pino(pino.destination('./logs/app.log'));
78
79
// File destination with options
80
const logger = pino(pino.destination({
81
dest: './logs/app.log',
82
minLength: 4096, // Buffer 4KB before writing
83
sync: false, // Async writing for performance
84
mkdir: true // Create directory if needed
85
}));
86
87
// Async destination for high performance
88
const logger = pino(pino.destination({
89
dest: './logs/app.log',
90
sync: false,
91
minLength: 0 // Write immediately
92
}));
93
94
// Stderr destination
95
const logger = pino(pino.destination(2)); // File descriptor 2 = stderr
96
```
97
98
### Multistream Functionality
99
100
Send logs to multiple destinations with different configurations and level filtering.
101
102
```typescript { .api }
103
/**
104
* Create a multistream that writes to multiple destinations
105
* @param streams - Array of stream entries or single stream
106
* @param opts - Multistream options
107
* @returns Multistream result object
108
*/
109
function multistream<TLevel = Level>(
110
streams: (DestinationStream | StreamEntry<TLevel>)[] | DestinationStream | StreamEntry<TLevel>,
111
opts?: MultiStreamOptions
112
): MultiStreamRes<TLevel>;
113
114
interface StreamEntry<TLevel = Level> {
115
/** Destination stream */
116
stream: DestinationStream;
117
118
/** Minimum level for this stream */
119
level?: TLevel;
120
}
121
122
interface MultiStreamOptions {
123
/** Custom level definitions */
124
levels?: Record<string, number>;
125
126
/** Remove duplicate entries */
127
dedupe?: boolean;
128
}
129
130
interface MultiStreamRes<TOriginLevel = Level> {
131
/** Write data to all appropriate streams */
132
write(data: any): void;
133
134
/** Add a new stream to the multistream */
135
add<TLevel = Level>(dest: StreamEntry<TLevel> | DestinationStream): MultiStreamRes<TOriginLevel & TLevel>;
136
137
/** Flush all streams synchronously */
138
flushSync(): void;
139
140
/** Minimum level across all streams */
141
minLevel: number;
142
143
/** Array of all stream entries */
144
streams: StreamEntry<TOriginLevel>[];
145
146
/** Clone multistream with new level */
147
clone<TLevel = Level>(level: TLevel): MultiStreamRes<TLevel>;
148
}
149
```
150
151
**Usage Examples:**
152
153
```javascript
154
// Multiple destinations with different levels
155
const streams = pino.multistream([
156
{ stream: pino.destination('./logs/info.log'), level: 'info' },
157
{ stream: pino.destination('./logs/error.log'), level: 'error' },
158
{ stream: process.stdout, level: 'debug' }
159
]);
160
161
const logger = pino(streams);
162
163
logger.debug('Debug message'); // Only to stdout
164
logger.info('Info message'); // To info.log and stdout
165
logger.error('Error message'); // To all three streams
166
```
167
168
## Advanced Stream Configuration
169
170
### High-Performance File Streams
171
172
Configure destination streams for maximum throughput in high-volume applications.
173
174
**Usage Examples:**
175
176
```javascript
177
// High-performance async file writing
178
const asyncDest = pino.destination({
179
dest: './logs/high-volume.log',
180
minLength: 4096, // 4KB buffer
181
sync: false, // Async writes
182
mkdir: true
183
});
184
185
// Sync file writing for critical logs
186
const syncDest = pino.destination({
187
dest: './logs/critical.log',
188
sync: true, // Synchronous writes
189
fsync: true // Force flush to disk
190
});
191
192
// Memory-efficient streaming
193
const streamDest = pino.destination({
194
dest: './logs/stream.log',
195
minLength: 0, // Write immediately
196
sync: false
197
});
198
```
199
200
### Stream Events and Error Handling
201
202
Handle stream lifecycle events and errors gracefully.
203
204
**Usage Examples:**
205
206
```javascript
207
const dest = pino.destination('./logs/app.log');
208
209
// Handle stream ready
210
dest.on('ready', () => {
211
console.log('Stream ready for writing');
212
});
213
214
// Handle stream errors
215
dest.on('error', (err) => {
216
console.error('Stream error:', err);
217
// Implement fallback logging strategy
218
});
219
220
// Handle stream close
221
dest.on('close', () => {
222
console.log('Stream closed');
223
});
224
225
// Manual flush
226
dest.flush((err) => {
227
if (err) {
228
console.error('Flush error:', err);
229
} else {
230
console.log('Stream flushed successfully');
231
}
232
});
233
```
234
235
### Log Rotation Support
236
237
Configure streams for log rotation using file reopening.
238
239
**Usage Examples:**
240
241
```javascript
242
const dest = pino.destination('./logs/app.log');
243
244
// Reopen file for log rotation (called by rotation tools)
245
function rotateLog() {
246
dest.reopen('./logs/app.log');
247
}
248
249
// Handle SIGUSR2 for log rotation
250
process.on('SIGUSR2', rotateLog);
251
252
// Manual rotation example
253
setInterval(() => {
254
const timestamp = new Date().toISOString().slice(0, 10);
255
const newFile = `./logs/app-${timestamp}.log`;
256
dest.reopen(newFile);
257
}, 24 * 60 * 60 * 1000); // Daily rotation
258
```
259
260
## Multistream Patterns
261
262
### Level-Based Stream Routing
263
264
Route different log levels to appropriate destinations.
265
266
**Usage Examples:**
267
268
```javascript
269
const streams = pino.multistream([
270
// Debug info to console during development
271
{
272
stream: process.stdout,
273
level: 'debug'
274
},
275
// Application logs to file
276
{
277
stream: pino.destination('./logs/app.log'),
278
level: 'info'
279
},
280
// Errors to separate file for monitoring
281
{
282
stream: pino.destination('./logs/error.log'),
283
level: 'error'
284
},
285
// Critical errors to both file and alerting system
286
{
287
stream: pino.destination('./logs/fatal.log'),
288
level: 'fatal'
289
}
290
]);
291
292
const logger = pino(streams);
293
```
294
295
### Environment-Specific Streaming
296
297
Configure different stream setups for different environments.
298
299
**Usage Examples:**
300
301
```javascript
302
function createStreams() {
303
if (process.env.NODE_ENV === 'production') {
304
return pino.multistream([
305
{
306
stream: pino.destination({
307
dest: './logs/app.log',
308
sync: false,
309
minLength: 4096
310
}),
311
level: 'info'
312
},
313
{
314
stream: pino.destination({
315
dest: './logs/error.log',
316
sync: true // Sync for errors in production
317
}),
318
level: 'error'
319
}
320
]);
321
} else if (process.env.NODE_ENV === 'development') {
322
return pino.multistream([
323
{
324
stream: process.stdout,
325
level: 'debug'
326
},
327
{
328
stream: pino.destination('./logs/dev.log'),
329
level: 'info'
330
}
331
]);
332
} else {
333
// Test environment - minimal logging
334
return pino.destination({
335
dest: './logs/test.log',
336
minLength: 0
337
});
338
}
339
}
340
341
const logger = pino(createStreams());
342
```
343
344
### Dynamic Stream Management
345
346
Add and remove streams dynamically during application runtime.
347
348
**Usage Examples:**
349
350
```javascript
351
let multistream = pino.multistream([
352
{ stream: process.stdout, level: 'info' }
353
]);
354
355
const logger = pino(multistream);
356
357
// Add error file logging when needed
358
function enableErrorLogging() {
359
multistream = multistream.add({
360
stream: pino.destination('./logs/error.log'),
361
level: 'error'
362
});
363
}
364
365
// Add debug logging during troubleshooting
366
function enableDebugLogging() {
367
multistream = multistream.add({
368
stream: pino.destination('./logs/debug.log'),
369
level: 'debug'
370
});
371
}
372
373
// Clone for testing specific scenarios
374
const testMultistream = multistream.clone('trace');
375
const testLogger = pino(testMultistream);
376
```
377
378
## Stream Performance Optimization
379
380
### Buffer Configuration
381
382
Optimize buffering settings for different use cases.
383
384
**Usage Examples:**
385
386
```javascript
387
// High-throughput logging (batch processing)
388
const highThroughputDest = pino.destination({
389
dest: './logs/batch.log',
390
minLength: 65536, // 64KB buffer
391
sync: false
392
});
393
394
// Low-latency logging (real-time processing)
395
const lowLatencyDest = pino.destination({
396
dest: './logs/realtime.log',
397
minLength: 0, // No buffering
398
sync: false
399
});
400
401
// Critical logging (data integrity)
402
const criticalDest = pino.destination({
403
dest: './logs/critical.log',
404
sync: true, // Synchronous writes
405
fsync: true // Force disk sync
406
});
407
```
408
409
### Memory Management
410
411
Configure streams to minimize memory usage in long-running applications.
412
413
**Usage Examples:**
414
415
```javascript
416
// Memory-efficient configuration
417
const dest = pino.destination({
418
dest: './logs/app.log',
419
minLength: 1024, // Small buffer
420
sync: false
421
});
422
423
// Periodic flushing to free memory
424
setInterval(() => {
425
dest.flush();
426
}, 5000); // Flush every 5 seconds
427
428
// Graceful shutdown
429
process.on('SIGTERM', () => {
430
dest.flush(() => {
431
dest.end(() => {
432
process.exit(0);
433
});
434
});
435
});
436
```