0
# Output Loggers
1
2
Direct file output loggers that bypass standard logging infrastructure for high-performance logging scenarios and simple output requirements. These loggers write directly to files or streams without the overhead of Python's standard logging module.
3
4
## Capabilities
5
6
### Print Logger
7
8
Logger that prints messages to a file using Python's print() function.
9
10
```python { .api }
11
class PrintLogger:
12
"""
13
Logger that prints log messages to a file.
14
15
Uses Python's print() function to write log messages,
16
making it simple but potentially slower than WriteLogger.
17
"""
18
19
def __init__(self, file=None):
20
"""
21
Initialize PrintLogger.
22
23
Args:
24
file (file-like, optional): File object to print to.
25
Defaults to sys.stdout if None.
26
"""
27
28
def msg(self, message: str) -> None:
29
"""
30
Print a log message.
31
32
Args:
33
message (str): Message to print
34
"""
35
36
# Alias methods for different log levels
37
def log(self, message: str) -> None: ...
38
def debug(self, message: str) -> None: ...
39
def info(self, message: str) -> None: ...
40
def warn(self, message: str) -> None: ...
41
def warning(self, message: str) -> None: ...
42
def err(self, message: str) -> None: ...
43
def error(self, message: str) -> None: ...
44
def critical(self, message: str) -> None: ...
45
def fatal(self, message: str) -> None: ...
46
def failure(self, message: str) -> None: ...
47
def exception(self, message: str) -> None: ...
48
49
class PrintLoggerFactory:
50
"""Factory for creating PrintLogger instances."""
51
52
def __init__(self, file=None):
53
"""
54
Initialize PrintLoggerFactory.
55
56
Args:
57
file (file-like, optional): Default file for created loggers
58
"""
59
60
def __call__(self, *args) -> PrintLogger:
61
"""
62
Create a PrintLogger instance.
63
64
Args:
65
*args: Arguments (ignored)
66
67
Returns:
68
PrintLogger: New PrintLogger instance
69
"""
70
```
71
72
### Write Logger
73
74
Logger that writes messages to a file using direct write operations, offering better performance than PrintLogger.
75
76
```python { .api }
77
class WriteLogger:
78
"""
79
Logger that writes log messages directly to a file.
80
81
Uses direct write() calls followed by flush() for better
82
performance compared to PrintLogger.
83
"""
84
85
def __init__(self, file=None):
86
"""
87
Initialize WriteLogger.
88
89
Args:
90
file (file-like, optional): File object to write to.
91
Defaults to sys.stdout if None.
92
"""
93
94
def msg(self, message: str) -> None:
95
"""
96
Write a log message and flush.
97
98
Args:
99
message (str): Message to write
100
"""
101
102
# Alias methods for different log levels
103
def log(self, message: str) -> None: ...
104
def debug(self, message: str) -> None: ...
105
def info(self, message: str) -> None: ...
106
def warn(self, message: str) -> None: ...
107
def warning(self, message: str) -> None: ...
108
def err(self, message: str) -> None: ...
109
def error(self, message: str) -> None: ...
110
def critical(self, message: str) -> None: ...
111
def fatal(self, message: str) -> None: ...
112
def failure(self, message: str) -> None: ...
113
def exception(self, message: str) -> None: ...
114
115
class WriteLoggerFactory:
116
"""Factory for creating WriteLogger instances."""
117
118
def __init__(self, file=None):
119
"""
120
Initialize WriteLoggerFactory.
121
122
Args:
123
file (file-like, optional): Default file for created loggers
124
"""
125
126
def __call__(self, *args) -> WriteLogger:
127
"""
128
Create a WriteLogger instance.
129
130
Args:
131
*args: Arguments (ignored)
132
133
Returns:
134
WriteLogger: New WriteLogger instance
135
"""
136
```
137
138
### Bytes Logger
139
140
Logger that writes byte messages directly to a binary file or stream.
141
142
```python { .api }
143
class BytesLogger:
144
"""
145
Logger that writes log messages as bytes to a file.
146
147
Designed for binary output or when you need to control
148
the exact byte representation of log messages.
149
"""
150
151
def __init__(self, file=None):
152
"""
153
Initialize BytesLogger.
154
155
Args:
156
file (file-like, optional): Binary file object to write to.
157
Defaults to sys.stdout.buffer if None.
158
"""
159
160
def msg(self, message: bytes) -> None:
161
"""
162
Write a log message as bytes.
163
164
Args:
165
message (bytes): Message bytes to write
166
"""
167
168
# Alias methods for different log levels
169
def log(self, message: bytes) -> None: ...
170
def debug(self, message: bytes) -> None: ...
171
def info(self, message: bytes) -> None: ...
172
def warn(self, message: bytes) -> None: ...
173
def warning(self, message: bytes) -> None: ...
174
def err(self, message: bytes) -> None: ...
175
def error(self, message: bytes) -> None: ...
176
def critical(self, message: bytes) -> None: ...
177
def fatal(self, message: bytes) -> None: ...
178
def failure(self, message: bytes) -> None: ...
179
def exception(self, message: bytes) -> None: ...
180
181
class BytesLoggerFactory:
182
"""Factory for creating BytesLogger instances."""
183
184
def __init__(self, file=None):
185
"""
186
Initialize BytesLoggerFactory.
187
188
Args:
189
file (file-like, optional): Default binary file for created loggers
190
"""
191
192
def __call__(self, *args) -> BytesLogger:
193
"""
194
Create a BytesLogger instance.
195
196
Args:
197
*args: Arguments (ignored)
198
199
Returns:
200
BytesLogger: New BytesLogger instance
201
"""
202
```
203
204
## Usage Examples
205
206
### Basic PrintLogger Usage
207
208
```python
209
import structlog
210
from structlog import PrintLoggerFactory, processors
211
import sys
212
213
# Configure with PrintLogger
214
structlog.configure(
215
processors=[
216
processors.TimeStamper(fmt="iso"),
217
processors.JSONRenderer()
218
],
219
wrapper_class=structlog.BoundLogger,
220
logger_factory=PrintLoggerFactory(),
221
)
222
223
logger = structlog.get_logger()
224
logger.info("Application started", version="1.0.0")
225
# Prints JSON to stdout
226
```
227
228
### Writing to a File
229
230
```python
231
import structlog
232
from structlog import WriteLoggerFactory, processors
233
234
# Open log file
235
with open("application.log", "w") as log_file:
236
# Configure with file output
237
structlog.configure(
238
processors=[
239
processors.TimeStamper(),
240
processors.JSONRenderer()
241
],
242
wrapper_class=structlog.BoundLogger,
243
logger_factory=WriteLoggerFactory(file=log_file),
244
)
245
246
logger = structlog.get_logger()
247
logger.info("Starting application", pid=1234)
248
logger.info("Application ready", port=8080)
249
# Messages written directly to file
250
```
251
252
### High-Performance Logging
253
254
```python
255
import structlog
256
from structlog import WriteLoggerFactory, processors
257
import sys
258
259
# Configure for high-performance output
260
structlog.configure(
261
processors=[
262
processors.JSONRenderer() # Minimal processing
263
],
264
wrapper_class=structlog.BoundLogger,
265
logger_factory=WriteLoggerFactory(file=sys.stdout),
266
cache_logger_on_first_use=True, # Cache for performance
267
)
268
269
logger = structlog.get_logger()
270
271
# Fast logging in tight loops
272
for i in range(1000):
273
logger.info("Processing item", item_id=i, batch="A")
274
```
275
276
### Bytes Logger Usage
277
278
```python
279
import structlog
280
from structlog import BytesLoggerFactory, processors
281
import sys
282
283
def bytes_json_renderer(logger, name, event_dict):
284
"""Custom processor that returns bytes."""
285
import json
286
json_str = json.dumps(event_dict)
287
return json_str.encode('utf-8') + b'\n'
288
289
# Configure with BytesLogger
290
structlog.configure(
291
processors=[
292
processors.TimeStamper(),
293
bytes_json_renderer
294
],
295
wrapper_class=structlog.BoundLogger,
296
logger_factory=BytesLoggerFactory(),
297
)
298
299
logger = structlog.get_logger()
300
logger.info("Binary logging", data="test")
301
# Outputs bytes to stdout.buffer
302
```
303
304
### Multiple Output Destinations
305
306
```python
307
import structlog
308
from structlog import WriteLoggerFactory, processors
309
import sys
310
311
class MultiFileLogger:
312
"""Custom logger that writes to multiple files."""
313
314
def __init__(self, files):
315
self.files = files
316
317
def msg(self, message):
318
for file in self.files:
319
file.write(message + '\n')
320
file.flush()
321
322
# Add alias methods
323
def info(self, message): return self.msg(message)
324
def error(self, message): return self.msg(message)
325
def warning(self, message): return self.msg(message)
326
327
class MultiFileLoggerFactory:
328
def __init__(self, files):
329
self.files = files
330
331
def __call__(self, *args):
332
return MultiFileLogger(self.files)
333
334
# Open multiple output files
335
with open("app.log", "w") as app_log, \
336
open("audit.log", "w") as audit_log:
337
338
structlog.configure(
339
processors=[
340
processors.TimeStamper(),
341
processors.JSONRenderer()
342
],
343
wrapper_class=structlog.BoundLogger,
344
logger_factory=MultiFileLoggerFactory([app_log, audit_log, sys.stdout]),
345
)
346
347
logger = structlog.get_logger()
348
logger.info("Message goes to all three destinations")
349
```
350
351
### Error Stream Logging
352
353
```python
354
import structlog
355
from structlog import WriteLoggerFactory, processors
356
import sys
357
358
# Configure to write errors to stderr
359
structlog.configure(
360
processors=[
361
processors.TimeStamper(),
362
processors.add_log_level,
363
processors.JSONRenderer()
364
],
365
wrapper_class=structlog.BoundLogger,
366
logger_factory=WriteLoggerFactory(file=sys.stderr),
367
)
368
369
logger = structlog.get_logger()
370
logger.error("Application error", error_code="E001", component="database")
371
# Error written to stderr
372
```
373
374
### Log Rotation with Output Loggers
375
376
```python
377
import structlog
378
from structlog import WriteLoggerFactory, processors
379
import os
380
from datetime import datetime
381
382
class RotatingFileLogger:
383
"""Logger that rotates files based on size or time."""
384
385
def __init__(self, base_filename, max_bytes=1024*1024):
386
self.base_filename = base_filename
387
self.max_bytes = max_bytes
388
self.current_file = None
389
self.bytes_written = 0
390
self._open_new_file()
391
392
def _open_new_file(self):
393
if self.current_file:
394
self.current_file.close()
395
396
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
397
filename = f"{self.base_filename}.{timestamp}"
398
self.current_file = open(filename, "w")
399
self.bytes_written = 0
400
401
def msg(self, message):
402
message_bytes = len(message.encode('utf-8'))
403
404
if self.bytes_written + message_bytes > self.max_bytes:
405
self._open_new_file()
406
407
self.current_file.write(message + '\n')
408
self.current_file.flush()
409
self.bytes_written += message_bytes + 1
410
411
def info(self, message): return self.msg(message)
412
def error(self, message): return self.msg(message)
413
414
class RotatingLoggerFactory:
415
def __init__(self, base_filename, max_bytes=1024*1024):
416
self.logger = RotatingFileLogger(base_filename, max_bytes)
417
418
def __call__(self, *args):
419
return self.logger
420
421
# Configure with rotating logger
422
structlog.configure(
423
processors=[
424
processors.TimeStamper(),
425
processors.JSONRenderer()
426
],
427
wrapper_class=structlog.BoundLogger,
428
logger_factory=RotatingLoggerFactory("app.log", max_bytes=1024),
429
)
430
431
logger = structlog.get_logger()
432
for i in range(100):
433
logger.info("Log message", iteration=i, data="x" * 50)
434
# Creates multiple rotated log files
435
```
436
437
### Buffered Output Logger
438
439
```python
440
import structlog
441
from structlog import processors
442
import sys
443
import threading
444
import time
445
446
class BufferedLogger:
447
"""Logger that buffers messages and flushes periodically."""
448
449
def __init__(self, file=None, buffer_size=100, flush_interval=5.0):
450
self.file = file or sys.stdout
451
self.buffer = []
452
self.buffer_size = buffer_size
453
self.flush_interval = flush_interval
454
self.lock = threading.Lock()
455
self.last_flush = time.time()
456
457
def msg(self, message):
458
with self.lock:
459
self.buffer.append(message)
460
461
# Flush if buffer is full or enough time has passed
462
now = time.time()
463
if (len(self.buffer) >= self.buffer_size or
464
now - self.last_flush >= self.flush_interval):
465
self._flush()
466
467
def _flush(self):
468
if self.buffer:
469
for message in self.buffer:
470
self.file.write(message + '\n')
471
self.file.flush()
472
self.buffer.clear()
473
self.last_flush = time.time()
474
475
def info(self, message): return self.msg(message)
476
def error(self, message): return self.msg(message)
477
478
class BufferedLoggerFactory:
479
def __init__(self, **kwargs):
480
self.logger = BufferedLogger(**kwargs)
481
482
def __call__(self, *args):
483
return self.logger
484
485
# Configure with buffered logger
486
structlog.configure(
487
processors=[
488
processors.TimeStamper(),
489
processors.JSONRenderer()
490
],
491
wrapper_class=structlog.BoundLogger,
492
logger_factory=BufferedLoggerFactory(buffer_size=10, flush_interval=2.0),
493
)
494
495
logger = structlog.get_logger()
496
for i in range(5):
497
logger.info("Buffered message", count=i)
498
time.sleep(0.5)
499
# Messages are buffered and flushed together
500
```