0
# Log Processors
1
2
Extensible pipeline of functions that transform, filter, and format log events as they flow through the structlog system. Processors can add data, remove data, change formats, or perform side effects like writing to files or sending to external systems.
3
4
## Capabilities
5
6
### Timestamp Processors
7
8
Add timestamp information to log events with configurable formatting and timezone handling.
9
10
```python { .api }
11
class TimeStamper:
12
"""Add timestamp to event dictionary."""
13
14
def __init__(self, fmt=None, utc=True, key="timestamp"):
15
"""
16
Args:
17
fmt (str, optional): Timestamp format ("iso", datetime format string, or None for epoch)
18
utc (bool): Use UTC timezone (default: True)
19
key (str): Key name for timestamp in event dict (default: "timestamp")
20
"""
21
22
def __call__(self, logger, name, event_dict) -> EventDict: ...
23
24
class MaybeTimeStamper:
25
"""Add timestamp only if the timestamp key doesn't already exist."""
26
27
def __init__(self, fmt=None, utc=True, key="timestamp"):
28
"""
29
Args:
30
fmt (str, optional): Timestamp format
31
utc (bool): Use UTC timezone
32
key (str): Key name for timestamp
33
"""
34
35
def __call__(self, logger, name, event_dict) -> EventDict: ...
36
```
37
38
### Rendering Processors
39
40
Transform structured event dictionaries into formatted strings for output.
41
42
```python { .api }
43
class JSONRenderer:
44
"""Render event dictionary as JSON string."""
45
46
def __init__(self, serializer=json.dumps, **dumps_kw):
47
"""
48
Args:
49
serializer (callable): JSON serialization function (default: json.dumps)
50
**dumps_kw: Additional keyword arguments for serializer
51
"""
52
53
def __call__(self, logger, name, event_dict) -> str | bytes: ...
54
55
class KeyValueRenderer:
56
"""Render event dictionary as key=value pairs."""
57
58
def __init__(self, sort_keys=False, key_order=None, drop_missing=False, repr_native_str=True):
59
"""
60
Args:
61
sort_keys (bool): Sort keys alphabetically
62
key_order (list, optional): Specific key ordering
63
drop_missing (bool): Drop keys with None values
64
repr_native_str (bool): Use repr() for string values
65
"""
66
67
def __call__(self, logger, method_name, event_dict) -> str: ...
68
69
class LogfmtRenderer:
70
"""Render event dictionary in logfmt format."""
71
72
def __init__(self, sort_keys=False, key_order=None, drop_missing=False, bool_as_flag=True):
73
"""
74
Args:
75
sort_keys (bool): Sort keys alphabetically
76
key_order (list, optional): Specific key ordering
77
drop_missing (bool): Drop keys with None values
78
bool_as_flag (bool): Render True as flag, False as key=false
79
"""
80
81
def __call__(self, logger, method_name, event_dict) -> str: ...
82
```
83
84
### Text Processing Processors
85
86
Handle text encoding, decoding, and formatting operations.
87
88
```python { .api }
89
class UnicodeEncoder:
90
"""Encode unicode values in event dictionary."""
91
92
def __init__(self, encoding="utf-8", errors="backslashreplace"):
93
"""
94
Args:
95
encoding (str): Text encoding to use
96
errors (str): Error handling strategy
97
"""
98
99
def __call__(self, logger, name, event_dict) -> EventDict: ...
100
101
class UnicodeDecoder:
102
"""Decode byte string values in event dictionary."""
103
104
def __init__(self, encoding="utf-8", errors="replace"):
105
"""
106
Args:
107
encoding (str): Text encoding to use
108
errors (str): Error handling strategy for decode errors
109
"""
110
111
def __call__(self, logger, name, event_dict) -> EventDict: ...
112
```
113
114
### Exception Handling Processors
115
116
Process and format exception information in log events.
117
118
```python { .api }
119
class ExceptionRenderer:
120
"""Replace exc_info tuple with formatted exception string."""
121
122
def __init__(self, exception_formatter=_format_exception):
123
"""
124
Args:
125
exception_formatter (callable): Function to format exceptions
126
"""
127
128
def __call__(self, logger, name, event_dict) -> EventDict: ...
129
130
class ExceptionPrettyPrinter:
131
"""Pretty print exceptions and remove exc_info from event dict."""
132
133
def __init__(self, file=None, exception_formatter=_format_exception):
134
"""
135
Args:
136
file (file-like, optional): File to write exceptions to
137
exception_formatter (callable): Function to format exceptions
138
"""
139
140
def __call__(self, logger, name, event_dict) -> EventDict: ...
141
```
142
143
### Stack Information Processors
144
145
Add stack frame and call site information to log events.
146
147
```python { .api }
148
class StackInfoRenderer:
149
"""Add stack information to event dictionary."""
150
151
def __init__(self, additional_ignores=None):
152
"""
153
Args:
154
additional_ignores (list, optional): Additional modules to ignore in stack traces
155
"""
156
157
def __call__(self, logger, name, event_dict) -> EventDict: ...
158
159
class CallsiteParameterAdder:
160
"""Add call site parameters (filename, line number, etc.) to event dictionary."""
161
162
def __init__(self, parameters=CallsiteParameter.all_parameters, additional_ignores=None):
163
"""
164
Args:
165
parameters (list): List of CallsiteParameter enum values to include
166
additional_ignores (list, optional): Additional modules to ignore
167
"""
168
169
def __call__(self, logger, name, event_dict) -> EventDict: ...
170
171
class CallsiteParameter(Enum):
172
"""Enumeration of available call site parameters."""
173
PATHNAME = "pathname"
174
FILENAME = "filename"
175
MODULE = "module"
176
FUNC_NAME = "funcName"
177
LINENO = "lineno"
178
THREAD = "thread"
179
THREAD_NAME = "threadName"
180
PROCESS = "process"
181
PROCESS_NAME = "processName"
182
```
183
184
### Utility Processors
185
186
General-purpose processors for common transformations and operations.
187
188
```python { .api }
189
class EventRenamer:
190
"""Rename the event key to a different name."""
191
192
def __init__(self, to: str, replace_by=None):
193
"""
194
Args:
195
to (str): New name for the event key
196
replace_by (str, optional): Replace event value if key already exists
197
"""
198
199
def __call__(self, logger, name, event_dict) -> EventDict: ...
200
201
def add_log_level(logger, method_name, event_dict) -> EventDict:
202
"""
203
Add log level name to event dictionary.
204
205
Args:
206
logger: Logger instance
207
method_name (str): Logger method name
208
event_dict (dict): Event dictionary
209
210
Returns:
211
dict: Event dictionary with 'level' key added
212
"""
213
```
214
215
### Pre-built Processor Instances
216
217
Common processor instances ready for use in configuration.
218
219
```python { .api }
220
format_exc_info: ExceptionRenderer
221
"""Pre-configured ExceptionRenderer instance for formatting exceptions."""
222
223
dict_tracebacks: ExceptionRenderer
224
"""Pre-configured ExceptionRenderer instance for structured traceback dictionaries."""
225
```
226
227
## Usage Examples
228
229
### Basic Processor Chain
230
231
```python
232
import structlog
233
from structlog import processors
234
235
structlog.configure(
236
processors=[
237
processors.TimeStamper(fmt="iso"),
238
processors.add_log_level,
239
processors.JSONRenderer()
240
],
241
wrapper_class=structlog.BoundLogger,
242
)
243
244
logger = structlog.get_logger()
245
logger.info("Test message")
246
# Output: {"timestamp": "2023-10-01T12:00:00Z", "level": "info", "event": "Test message"}
247
```
248
249
### Custom Formatting Chain
250
251
```python
252
import structlog
253
from structlog import processors
254
255
structlog.configure(
256
processors=[
257
processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S", utc=False),
258
processors.add_log_level,
259
processors.KeyValueRenderer(sort_keys=True, key_order=["timestamp", "level", "event"])
260
],
261
wrapper_class=structlog.BoundLogger,
262
)
263
264
logger = structlog.get_logger()
265
logger.info("Test message", user_id=123)
266
# Output: timestamp='2023-10-01 12:00:00' level='info' event='Test message' user_id=123
267
```
268
269
### Exception Processing
270
271
```python
272
import structlog
273
from structlog import processors
274
275
structlog.configure(
276
processors=[
277
processors.TimeStamper(),
278
processors.ExceptionRenderer(),
279
processors.JSONRenderer()
280
],
281
wrapper_class=structlog.BoundLogger,
282
)
283
284
logger = structlog.get_logger()
285
286
try:
287
1 / 0
288
except ZeroDivisionError:
289
logger.exception("Division by zero occurred")
290
# Exception information will be formatted and included in JSON output
291
```
292
293
### Stack Information
294
295
```python
296
import structlog
297
from structlog import processors
298
299
structlog.configure(
300
processors=[
301
processors.CallsiteParameterAdder(
302
parameters=[
303
processors.CallsiteParameter.FILENAME,
304
processors.CallsiteParameter.LINENO,
305
processors.CallsiteParameter.FUNC_NAME
306
]
307
),
308
processors.JSONRenderer()
309
],
310
wrapper_class=structlog.BoundLogger,
311
)
312
313
logger = structlog.get_logger()
314
logger.info("Debug message")
315
# Output includes filename, line number, and function name
316
```
317
318
### Text Processing
319
320
```python
321
import structlog
322
from structlog import processors
323
324
structlog.configure(
325
processors=[
326
processors.UnicodeEncoder(encoding="utf-8"),
327
processors.KeyValueRenderer()
328
],
329
wrapper_class=structlog.BoundLogger,
330
)
331
332
logger = structlog.get_logger()
333
logger.info("Message with unicode", text="Hello 世界")
334
```
335
336
### Custom Processor
337
338
```python
339
import structlog
340
from structlog import processors
341
342
def add_hostname_processor(logger, method_name, event_dict):
343
"""Custom processor to add hostname to every log entry."""
344
import socket
345
event_dict["hostname"] = socket.gethostname()
346
return event_dict
347
348
structlog.configure(
349
processors=[
350
processors.TimeStamper(),
351
add_hostname_processor,
352
processors.JSONRenderer()
353
],
354
wrapper_class=structlog.BoundLogger,
355
)
356
357
logger = structlog.get_logger()
358
logger.info("Test message")
359
# Output includes hostname field
360
```
361
362
### Conditional Processing
363
364
```python
365
import structlog
366
from structlog import processors
367
368
def sensitive_data_filter(logger, method_name, event_dict):
369
"""Remove sensitive data from logs."""
370
sensitive_keys = ["password", "token", "secret"]
371
for key in sensitive_keys:
372
if key in event_dict:
373
event_dict[key] = "[REDACTED]"
374
return event_dict
375
376
structlog.configure(
377
processors=[
378
sensitive_data_filter,
379
processors.TimeStamper(),
380
processors.JSONRenderer()
381
],
382
wrapper_class=structlog.BoundLogger,
383
)
384
385
logger = structlog.get_logger()
386
logger.info("User login", username="alice", password="secret123")
387
# Output: password field will show "[REDACTED]"
388
```
389
390
### Processor with Configuration
391
392
```python
393
import structlog
394
from structlog import processors
395
396
# Configure timestamp processor
397
timestamper = processors.TimeStamper(
398
fmt="iso",
399
utc=True,
400
key="@timestamp" # Use custom key for timestamp
401
)
402
403
# Configure JSON renderer with custom options
404
json_renderer = processors.JSONRenderer(
405
sort_keys=True,
406
ensure_ascii=False,
407
separators=(',', ':')
408
)
409
410
structlog.configure(
411
processors=[
412
timestamper,
413
processors.add_log_level,
414
json_renderer
415
],
416
wrapper_class=structlog.BoundLogger,
417
)
418
```