0
# Logging System
1
2
Modern structured logging system with event-based architecture, filtering, and multiple output formats for comprehensive application logging. Twisted provides both legacy and modern logging systems.
3
4
## Capabilities
5
6
### Modern Structured Logging
7
8
Event-based logging system with structured data and flexible formatting.
9
10
```python { .api }
11
class Logger:
12
"""
13
Main logging class for structured event logging.
14
15
Attributes:
16
- namespace: Logger namespace (str)
17
- source: Logger source object
18
"""
19
namespace = None
20
source = None
21
22
def __init__(self, namespace=None, source=None, observer=None):
23
"""
24
Args:
25
namespace (str): Logger namespace
26
source: Source object for logger
27
observer: Log observer (defaults to global)
28
"""
29
30
def debug(self, format=None, **kwargs):
31
"""
32
Log debug message.
33
34
Args:
35
format (str): Message format string
36
**kwargs: Format parameters and metadata
37
"""
38
39
def info(self, format=None, **kwargs):
40
"""
41
Log info message.
42
43
Args:
44
format (str): Message format string
45
**kwargs: Format parameters and metadata
46
"""
47
48
def warn(self, format=None, **kwargs):
49
"""
50
Log warning message.
51
52
Args:
53
format (str): Message format string
54
**kwargs: Format parameters and metadata
55
"""
56
57
def error(self, format=None, **kwargs):
58
"""
59
Log error message.
60
61
Args:
62
format (str): Message format string
63
**kwargs: Format parameters and metadata
64
"""
65
66
def critical(self, format=None, **kwargs):
67
"""
68
Log critical message.
69
70
Args:
71
format (str): Message format string
72
**kwargs: Format parameters and metadata
73
"""
74
75
def failure(self, format=None, failure=None, **kwargs):
76
"""
77
Log failure with traceback.
78
79
Args:
80
format (str): Message format string
81
failure: Failure object (defaults to current exception)
82
**kwargs: Format parameters and metadata
83
"""
84
85
class LogLevel:
86
"""
87
Log level constants and validation.
88
89
Constants:
90
- debug: Debug level
91
- info: Info level
92
- warn: Warning level
93
- error: Error level
94
- critical: Critical level
95
"""
96
debug = LogLevel._levelWithName('debug')
97
info = LogLevel._levelWithName('info')
98
warn = LogLevel._levelWithName('warn')
99
error = LogLevel._levelWithName('error')
100
critical = LogLevel._levelWithName('critical')
101
102
@classmethod
103
def levelWithName(cls, name):
104
"""
105
Get log level by name.
106
107
Args:
108
name (str): Level name
109
110
Returns:
111
LogLevel: Log level object
112
"""
113
114
class LogPublisher:
115
"""
116
Event publishing system for log observers.
117
118
Attributes:
119
- observers: List of registered observers
120
"""
121
observers = None
122
123
def __init__(self, *observers):
124
"""
125
Args:
126
*observers: Initial log observers
127
"""
128
129
def addObserver(self, observer):
130
"""
131
Add log observer.
132
133
Args:
134
observer: Log observer callable
135
"""
136
137
def removeObserver(self, observer):
138
"""
139
Remove log observer.
140
141
Args:
142
observer: Log observer to remove
143
"""
144
145
def msg(self, *message, **kwargs):
146
"""
147
Publish log message.
148
149
Args:
150
*message: Message components
151
**kwargs: Event metadata
152
"""
153
154
# Global logger instance
155
log = Logger()
156
```
157
158
**Modern Logging Usage Example**:
159
160
```python
161
from twisted.logger import Logger
162
163
# Create logger with namespace
164
log = Logger("myapp.module")
165
166
# Basic logging
167
log.info("Server starting on port {port}", port=8080)
168
log.warn("High memory usage: {usage}%", usage=85)
169
log.error("Database connection failed", db_host="localhost")
170
171
# Structured logging with metadata
172
log.info("User login",
173
user_id=12345,
174
ip_address="192.168.1.100",
175
success=True,
176
duration=0.5)
177
178
# Failure logging
179
try:
180
risky_operation()
181
except Exception:
182
log.failure("Operation failed") # Includes traceback
183
184
# Context-specific logging
185
user_log = Logger("myapp.user", source={"user_id": 12345})
186
user_log.info("Profile updated", fields=["email", "name"])
187
```
188
189
### Log Observers
190
191
Output destinations and formatting for log events.
192
193
```python { .api }
194
class FileLogObserver:
195
"""
196
Log observer that writes to files.
197
"""
198
def __init__(self, outFile, formatEvent=None):
199
"""
200
Args:
201
outFile: File-like object to write to
202
formatEvent: Event formatting function
203
"""
204
205
def __call__(self, event):
206
"""
207
Process log event.
208
209
Args:
210
event (dict): Log event data
211
"""
212
213
class FilteringLogObserver:
214
"""
215
Log observer that filters events before forwarding.
216
"""
217
def __init__(self, observer, filters=None, defaultLogLevel=None):
218
"""
219
Args:
220
observer: Target observer
221
filters: List of filter predicates
222
defaultLogLevel: Default level for events without level
223
"""
224
225
def __call__(self, event):
226
"""
227
Filter and forward log event.
228
229
Args:
230
event (dict): Log event data
231
"""
232
233
class LimitedHistoryLogObserver:
234
"""
235
Log observer that keeps recent history in memory.
236
"""
237
def __init__(self, size=100):
238
"""
239
Args:
240
size (int): Maximum number of events to keep
241
"""
242
243
def __call__(self, event):
244
"""
245
Store log event in history.
246
247
Args:
248
event (dict): Log event data
249
"""
250
251
def getHistory(self):
252
"""
253
Get recent log history.
254
255
Returns:
256
list: Recent log events
257
"""
258
259
class LoggingFile:
260
"""
261
File-like object that writes to logger.
262
"""
263
def __init__(self, logger, level=LogLevel.info):
264
"""
265
Args:
266
logger: Logger to write to
267
level: Log level for messages
268
"""
269
270
def write(self, data):
271
"""
272
Write data to logger.
273
274
Args:
275
data (str): Data to log
276
"""
277
278
def flush(self):
279
"""Flush any buffered data."""
280
```
281
282
### Event Formatting
283
284
Functions for formatting log events into human-readable output.
285
286
```python { .api }
287
def formatEvent(event):
288
"""
289
Format log event as string.
290
291
Args:
292
event (dict): Log event data
293
294
Returns:
295
str: Formatted event string
296
"""
297
298
def formatEventAsClassicLogText(event):
299
"""
300
Format event in classic log text format.
301
302
Args:
303
event (dict): Log event data
304
305
Returns:
306
str: Classic format log line
307
"""
308
309
def formatTime(when, timeFormat=None, default="-"):
310
"""
311
Format timestamp for logging.
312
313
Args:
314
when: Timestamp (float seconds since epoch)
315
timeFormat (str): Time format string
316
default (str): Default if formatting fails
317
318
Returns:
319
str: Formatted timestamp
320
"""
321
322
def eventAsText(event, includeTraceback=True):
323
"""
324
Convert log event to text representation.
325
326
Args:
327
event (dict): Log event data
328
includeTraceback (bool): Include traceback if present
329
330
Returns:
331
str: Text representation
332
"""
333
334
def eventFromJSON(jsonText):
335
"""
336
Parse log event from JSON text.
337
338
Args:
339
jsonText (str): JSON event data
340
341
Returns:
342
dict: Log event
343
"""
344
345
def eventAsJSON(event):
346
"""
347
Serialize log event as JSON.
348
349
Args:
350
event (dict): Log event data
351
352
Returns:
353
str: JSON representation
354
"""
355
```
356
357
**Observer Usage Example**:
358
359
```python
360
from twisted.logger import Logger, FileLogObserver, FilteringLogObserver
361
import sys
362
363
# File observer
364
log_file = open("/var/log/myapp.log", "a")
365
file_observer = FileLogObserver(log_file)
366
367
# Filtered observer (only warnings and errors)
368
def warning_filter(event):
369
level = event.get('log_level')
370
return level and level >= LogLevel.warn
371
372
filtered_observer = FilteringLogObserver(
373
observer=file_observer,
374
filters=[warning_filter]
375
)
376
377
# Console observer
378
console_observer = FileLogObserver(sys.stdout)
379
380
# Set up global logging
381
from twisted.logger import globalLogPublisher
382
globalLogPublisher.addObserver(console_observer)
383
globalLogPublisher.addObserver(filtered_observer)
384
385
# Use logger
386
log = Logger("myapp")
387
log.info("This goes to console only")
388
log.error("This goes to both console and file")
389
```
390
391
### Context Management
392
393
Context managers for logging operations and scoped logging.
394
395
```python { .api }
396
class Operation:
397
"""
398
Context manager for logging operations with start/end events.
399
"""
400
def __init__(self, logger, message, level=LogLevel.info, **fields):
401
"""
402
Args:
403
logger: Logger to use
404
message (str): Operation description
405
level: Log level
406
**fields: Additional context fields
407
"""
408
409
def __enter__(self):
410
"""
411
Start operation logging.
412
413
Returns:
414
Operation: Self for chaining
415
"""
416
417
def __exit__(self, exc_type, exc_val, exc_tb):
418
"""
419
End operation logging.
420
421
Args:
422
exc_type: Exception type (if any)
423
exc_val: Exception value
424
exc_tb: Exception traceback
425
"""
426
427
def succeed(self, **fields):
428
"""
429
Mark operation as successful.
430
431
Args:
432
**fields: Success context fields
433
"""
434
435
def fail(self, **fields):
436
"""
437
Mark operation as failed.
438
439
Args:
440
**fields: Failure context fields
441
"""
442
```
443
444
**Context Usage Example**:
445
446
```python
447
from twisted.logger import Logger, Operation
448
449
log = Logger("myapp.database")
450
451
# Operation context manager
452
with Operation(log, "Database migration", version="1.2.3") as op:
453
try:
454
# Perform migration
455
migrate_schema()
456
op.succeed(tables_modified=5)
457
except Exception as e:
458
op.fail(error=str(e))
459
raise
460
461
# Manual operation control
462
op = Operation(log, "User authentication", user_id=12345)
463
op.__enter__()
464
try:
465
if authenticate_user():
466
op.succeed(method="password")
467
else:
468
op.fail(reason="invalid_password")
469
finally:
470
op.__exit__(None, None, None)
471
```
472
473
### Legacy Logging (twisted.python.log)
474
475
Backward-compatible logging system for older Twisted code.
476
477
```python { .api }
478
# Legacy logging functions from twisted.python.log
479
def msg(*message, **kwargs):
480
"""
481
Log a message using legacy system.
482
483
Args:
484
*message: Message components
485
**kwargs: Additional data
486
"""
487
488
def err(failure=None, _why=None):
489
"""
490
Log an error using legacy system.
491
492
Args:
493
failure: Failure object (defaults to current exception)
494
_why (str): Error description
495
"""
496
497
def startLogging(file, setStdout=1):
498
"""
499
Start logging to a file.
500
501
Args:
502
file: File-like object or filename
503
setStdout (bool): Redirect stdout to log
504
"""
505
506
def startLoggingWithObserver(observer, setStdout=1):
507
"""
508
Start logging with custom observer.
509
510
Args:
511
observer: Log observer function
512
setStdout (bool): Redirect stdout to log
513
"""
514
515
def addObserver(observer):
516
"""
517
Add legacy log observer.
518
519
Args:
520
observer: Observer function
521
"""
522
523
def removeObserver(observer):
524
"""
525
Remove legacy log observer.
526
527
Args:
528
observer: Observer function to remove
529
"""
530
531
class FileLogObserver:
532
"""
533
Legacy file log observer.
534
"""
535
def __init__(self, f):
536
"""
537
Args:
538
f: File-like object
539
"""
540
541
def __call__(self, eventDict):
542
"""
543
Process legacy log event.
544
545
Args:
546
eventDict (dict): Legacy event data
547
"""
548
549
class PythonLoggingObserver:
550
"""
551
Observer that forwards to Python's logging module.
552
"""
553
def __init__(self, loggerName='twisted'):
554
"""
555
Args:
556
loggerName (str): Python logger name
557
"""
558
```
559
560
**Legacy Logging Example**:
561
562
```python
563
from twisted.python import log
564
import sys
565
566
# Start legacy logging
567
log.startLogging(sys.stdout)
568
569
# Log messages
570
log.msg("Server starting", port=8080)
571
log.msg("Connection established", client="192.168.1.100")
572
573
# Log errors
574
try:
575
risky_operation()
576
except:
577
log.err() # Logs current exception
578
579
# Custom observer
580
def my_observer(event):
581
print(f"Custom: {event}")
582
583
log.addObserver(my_observer)
584
log.msg("This will go to custom observer too")
585
```
586
587
### Integration with Twisted Components
588
589
Logging integration patterns for Twisted protocols and services.
590
591
```python { .api }
592
# Protocol logging
593
from twisted.internet import protocol
594
from twisted.logger import Logger
595
596
class MyProtocol(protocol.Protocol):
597
def __init__(self):
598
self.log = Logger(self.__class__.__name__, source=self)
599
600
def connectionMade(self):
601
self.log.info("Connection established",
602
peer=str(self.transport.getPeer()))
603
604
def dataReceived(self, data):
605
self.log.debug("Data received",
606
bytes=len(data),
607
data=data[:100]) # Log first 100 bytes
608
609
# Service logging
610
from twisted.application import service
611
612
class MyService(service.Service):
613
def __init__(self):
614
self.log = Logger(self.__class__.__name__)
615
616
def startService(self):
617
service.Service.startService(self)
618
self.log.info("Service started")
619
620
def stopService(self):
621
self.log.info("Service stopping")
622
return service.Service.stopService(self)
623
```
624
625
### Log Analysis and Monitoring
626
627
Utilities for analyzing and monitoring log output.
628
629
```python { .api }
630
# Event filtering
631
def jsonFileLogObserver(outFile):
632
"""
633
Create observer that writes JSON events to file.
634
635
Args:
636
outFile: Output file
637
638
Returns:
639
Observer function
640
"""
641
642
def eventsFromJSONLogFile(inFile):
643
"""
644
Read log events from JSON log file.
645
646
Args:
647
inFile: Input file
648
649
Yields:
650
dict: Log events
651
"""
652
653
# Custom filters
654
def predicateLogObserver(observer, predicate):
655
"""
656
Create filtering observer with custom predicate.
657
658
Args:
659
observer: Target observer
660
predicate: Filter predicate function
661
662
Returns:
663
Filtering observer
664
"""
665
666
def levelLogObserver(observer, level):
667
"""
668
Create observer that filters by log level.
669
670
Args:
671
observer: Target observer
672
level: Minimum log level
673
674
Returns:
675
Filtering observer
676
"""
677
```