0
# Child Loggers
1
2
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.
3
4
## Capabilities
5
6
### Child Logger Creation
7
8
Create a child logger that inherits parent configuration and adds specific bindings.
9
10
```typescript { .api }
11
/**
12
* Creates a child logger with additional bindings
13
* @param bindings - Key-value pairs to include in all child logger messages
14
* @param options - Optional child-specific configuration overrides
15
* @returns New logger instance that inherits parent settings
16
*/
17
child(bindings: Bindings, options?: ChildLoggerOptions): Logger;
18
19
type Bindings = Record<string, any>;
20
21
interface ChildLoggerOptions {
22
/** Override log level for this child */
23
level?: string;
24
25
/** Additional or override serializers */
26
serializers?: { [key: string]: SerializerFn };
27
28
/** Custom levels for this child */
29
customLevels?: { [level: string]: number };
30
31
/** Child-specific formatters */
32
formatters?: {
33
level?: (label: string, number: number) => object;
34
bindings?: (bindings: Bindings) => object;
35
log?: (object: object) => object;
36
};
37
38
/** Child-specific redaction rules */
39
redact?: string[] | RedactOptions;
40
41
/** Message prefix for this child */
42
msgPrefix?: string;
43
}
44
```
45
46
**Usage Examples:**
47
48
```javascript
49
const logger = pino();
50
51
// Simple child with user context
52
const userLogger = logger.child({ userId: 123, module: 'auth' });
53
userLogger.info('User logged in');
54
// Output: {"level":30,"time":...,"msg":"User logged in","userId":123,"module":"auth",...}
55
56
// Child with request context
57
const requestLogger = logger.child({
58
requestId: 'req-456',
59
method: 'POST',
60
path: '/api/users'
61
});
62
requestLogger.info('Processing request');
63
requestLogger.error({ error: 'ValidationError' }, 'Request validation failed');
64
65
// Child with options override
66
const debugLogger = logger.child(
67
{ component: 'database' },
68
{ level: 'debug' }
69
);
70
debugLogger.debug('Executing query');
71
```
72
73
### Nested Child Loggers
74
75
Create child loggers from other child loggers to build hierarchical context.
76
77
```typescript { .api }
78
// Child loggers can create their own child loggers
79
```
80
81
**Usage Examples:**
82
83
```javascript
84
const logger = pino();
85
86
// Parent child for request context
87
const requestLogger = logger.child({ requestId: 'req-789' });
88
89
// Child of child for specific operation
90
const dbLogger = requestLogger.child({ operation: 'user-lookup' });
91
const cacheLogger = requestLogger.child({ operation: 'cache-check' });
92
93
dbLogger.info('Querying user table');
94
cacheLogger.info('Cache miss');
95
96
// All include both requestId and operation in output
97
```
98
99
### Bindings Management
100
101
Retrieve and modify bindings on existing logger instances.
102
103
```typescript { .api }
104
/**
105
* Returns current logger bindings
106
* @returns Object containing all current bindings
107
*/
108
bindings(): Bindings;
109
110
/**
111
* Adds new bindings to existing logger
112
* Note: Does not overwrite existing bindings, may result in duplicate keys
113
* @param bindings - Additional key-value pairs to bind
114
*/
115
setBindings(bindings: Bindings): void;
116
```
117
118
**Usage Examples:**
119
120
```javascript
121
const logger = pino();
122
const child = logger.child({ userId: 123, module: 'auth' });
123
124
// Get current bindings
125
const currentBindings = child.bindings();
126
console.log(currentBindings); // { userId: 123, module: 'auth' }
127
128
// Add more bindings
129
child.setBindings({ sessionId: 'sess-456', ip: '192.168.1.100' });
130
131
child.info('Action performed');
132
// Output includes: userId, module, sessionId, ip
133
```
134
135
## Child Logger Inheritance
136
137
### Settings Inheritance
138
139
Child loggers inherit all configuration from their parent logger.
140
141
**Inherited Properties:**
142
- Log level (unless overridden)
143
- Serializers (merged with child-specific ones)
144
- Formatters (merged with child-specific ones)
145
- Transport configuration
146
- Redaction rules (merged with child-specific ones)
147
- Base properties
148
- Hooks
149
- All other configuration options
150
151
**Usage Examples:**
152
153
```javascript
154
const parentLogger = pino({
155
level: 'debug',
156
name: 'my-app',
157
serializers: {
158
user: (user) => ({ id: user.id, name: user.name })
159
}
160
});
161
162
// Child inherits debug level, name, and serializers
163
const child = parentLogger.child({ module: 'payments' });
164
165
child.debug('Processing payment'); // Will output (inherits debug level)
166
child.info({ user: userObject }, 'Payment completed'); // Uses inherited serializer
167
```
168
169
### Level Control
170
171
Child loggers can have independent log levels from their parents.
172
173
**Usage Examples:**
174
175
```javascript
176
const logger = pino({ level: 'info' });
177
178
// Child with more verbose logging
179
const debugChild = logger.child(
180
{ component: 'auth' },
181
{ level: 'debug' }
182
);
183
184
// Child with less verbose logging
185
const errorChild = logger.child(
186
{ component: 'external-api' },
187
{ level: 'error' }
188
);
189
190
logger.debug('Parent debug'); // Not logged (parent is 'info')
191
debugChild.debug('Child debug'); // Logged (child is 'debug')
192
errorChild.info('Child info'); // Not logged (child is 'error')
193
```
194
195
## Child Logger Callbacks
196
197
### On Child Creation
198
199
Hook into child logger creation for custom initialization.
200
201
```typescript { .api }
202
interface LoggerOptions {
203
/** Callback executed when child logger is created */
204
onChild?: OnChildCallback;
205
}
206
207
type OnChildCallback = (child: Logger) => void;
208
209
interface Logger {
210
/** Current callback for child creation */
211
onChild: OnChildCallback;
212
}
213
```
214
215
**Usage Examples:**
216
217
```javascript
218
const logger = pino({
219
onChild: (child) => {
220
// Add automatic tracking
221
child.setBindings({
222
childCreatedAt: new Date().toISOString(),
223
parentName: logger.bindings().name || 'root'
224
});
225
}
226
});
227
228
const child = logger.child({ userId: 123 });
229
// Automatically includes childCreatedAt and parentName
230
```
231
232
## Advanced Child Logger Patterns
233
234
### Request-Scoped Logging
235
236
Create child loggers for request tracking in web applications.
237
238
**Usage Examples:**
239
240
```javascript
241
// Express middleware example
242
app.use((req, res, next) => {
243
req.logger = logger.child({
244
requestId: generateRequestId(),
245
method: req.method,
246
path: req.path,
247
userAgent: req.get('User-Agent')
248
});
249
next();
250
});
251
252
// Use in route handlers
253
app.post('/users', (req, res) => {
254
req.logger.info('Creating new user');
255
256
// Service layer inherits request context
257
const serviceLogger = req.logger.child({ service: 'user-service' });
258
serviceLogger.debug('Validating user data');
259
260
// Database layer adds more context
261
const dbLogger = serviceLogger.child({ operation: 'user-insert' });
262
dbLogger.info('Inserting user record');
263
});
264
```
265
266
### Module-Based Logging
267
268
Organize logging by application modules using child loggers.
269
270
**Usage Examples:**
271
272
```javascript
273
// Application setup
274
const rootLogger = pino({ name: 'my-app' });
275
276
// Module loggers
277
const authLogger = rootLogger.child({ module: 'authentication' });
278
const dbLogger = rootLogger.child({ module: 'database' });
279
const apiLogger = rootLogger.child({ module: 'api' });
280
281
// Sub-module loggers
282
const userAuthLogger = authLogger.child({ submodule: 'user-auth' });
283
const sessionLogger = authLogger.child({ submodule: 'session' });
284
285
// Usage maintains hierarchy
286
userAuthLogger.info('User login attempt');
287
sessionLogger.info('Session created');
288
// Both include module: 'authentication' plus their submodule
289
```
290
291
### Error Context Preservation
292
293
Use child loggers to maintain error context through async operations.
294
295
**Usage Examples:**
296
297
```javascript
298
async function processOrder(orderId, logger = rootLogger) {
299
const orderLogger = logger.child({ orderId, operation: 'process-order' });
300
301
try {
302
orderLogger.info('Starting order processing');
303
304
// Each step maintains order context
305
await validateOrder(orderLogger);
306
await chargePayment(orderLogger);
307
await updateInventory(orderLogger);
308
309
orderLogger.info('Order processing completed');
310
} catch (error) {
311
orderLogger.error({ error }, 'Order processing failed');
312
throw error;
313
}
314
}
315
316
async function validateOrder(logger) {
317
const validationLogger = logger.child({ step: 'validation' });
318
validationLogger.debug('Validating order data');
319
// Any errors here include orderId, operation, and step context
320
}
321
```