0
# Development Tools
1
2
Rich console output, colored logging, column formatting, and advanced traceback rendering designed for development environments and debugging. These tools provide human-readable output optimized for development workflows.
3
4
## Capabilities
5
6
### Console Rendering
7
8
Render structured log events as human-readable, colored console output with alignment and customizable formatting.
9
10
```python { .api }
11
class ConsoleRenderer:
12
"""Render event dictionary as aligned, colored console output."""
13
14
def __init__(
15
self,
16
pad_event=30,
17
colors=True,
18
force_colors=False,
19
repr_native_str=False,
20
level_styles=None,
21
exception_formatter=default_exception_formatter,
22
sort_keys=True,
23
event_key="event",
24
timestamp_key="timestamp",
25
columns=None,
26
pad_level=True
27
):
28
"""
29
Args:
30
pad_event (int): Minimum width for event column
31
colors (bool): Enable colored output
32
force_colors (bool): Force colors even when not in terminal
33
repr_native_str (bool): Use repr() for string values
34
level_styles (dict, optional): Custom color styles for log levels
35
exception_formatter (callable): Function to format exceptions
36
sort_keys (bool): Sort context keys alphabetically
37
event_key (str): Key name for main event message
38
timestamp_key (str): Key name for timestamp
39
columns (list, optional): Custom column configuration
40
pad_level (bool): Pad log level names for alignment
41
"""
42
43
def __call__(self, logger, name, event_dict) -> str: ...
44
45
@staticmethod
46
def get_default_level_styles(colors=True) -> dict[str, str]:
47
"""
48
Get default color styles for log levels.
49
50
Args:
51
colors (bool): Return colored styles if True, empty styles if False
52
53
Returns:
54
dict: Mapping of log level names to ANSI color codes
55
"""
56
```
57
58
### Column Formatting
59
60
Flexible column-based formatting system for structured console output.
61
62
```python { .api }
63
class Column:
64
"""Column definition for console rendering."""
65
66
key: str # Key for which this column is responsible
67
formatter: ColumnFormatter # Column formatter instance
68
69
class KeyValueColumnFormatter:
70
"""Format key-value pairs with customizable styling."""
71
72
def __init__(
73
self,
74
key_style,
75
value_style,
76
reset_style,
77
value_repr,
78
width=0,
79
prefix="",
80
postfix=""
81
):
82
"""
83
Args:
84
key_style (str): ANSI style code for keys
85
value_style (str): ANSI style code for values
86
reset_style (str): ANSI reset code
87
value_repr (callable): Function to convert values to strings
88
width (int): Minimum column width
89
prefix (str): Text to prepend to output
90
postfix (str): Text to append to output
91
"""
92
93
def __call__(self, key, value) -> str: ...
94
95
class LogLevelColumnFormatter:
96
"""Format log level names with level-specific styling."""
97
98
def __init__(self, level_styles, reset_style, width=None):
99
"""
100
Args:
101
level_styles (dict): Mapping of level names to style codes
102
reset_style (str): ANSI reset code
103
width (int, optional): Fixed width for level column
104
"""
105
106
def __call__(self, key, value) -> str: ...
107
108
# Protocol for column formatters
109
class ColumnFormatter(Protocol):
110
"""Protocol for column formatter functions."""
111
112
def __call__(self, key: str, value: object) -> str: ...
113
```
114
115
### Exception Formatting
116
117
Advanced exception and traceback formatting with multiple rendering options.
118
119
```python { .api }
120
class RichTracebackFormatter:
121
"""Rich traceback renderer with syntax highlighting and local variables."""
122
123
def __init__(
124
self,
125
color_system="truecolor",
126
show_locals=True,
127
max_frames=100,
128
theme=None,
129
word_wrap=False,
130
extra_lines=3,
131
width=100,
132
indent_guides=True,
133
locals_max_length=10,
134
locals_max_string=80,
135
locals_hide_dunder=True,
136
locals_hide_sunder=False,
137
suppress=()
138
):
139
"""
140
Args:
141
color_system (str): Color system ("truecolor", "256", "standard", "windows")
142
show_locals (bool): Show local variables in traceback
143
max_frames (int): Maximum number of frames to show
144
theme (str, optional): Syntax highlighting theme
145
word_wrap (bool): Enable word wrapping
146
extra_lines (int): Extra lines of context around each frame
147
width (int): Console width for formatting
148
indent_guides (bool): Show indentation guides
149
locals_max_length (int): Maximum number of local variables to show
150
locals_max_string (int): Maximum length of local variable strings
151
locals_hide_dunder (bool): Hide dunder variables (__var__)
152
locals_hide_sunder (bool): Hide sunder variables (_var)
153
suppress (tuple): Modules to suppress in traceback
154
"""
155
156
def __call__(self, sio, exc_info) -> None: ...
157
158
def plain_traceback(sio, exc_info) -> None:
159
"""
160
Plain traceback formatter function.
161
162
Args:
163
sio: Text stream to write to
164
exc_info: Exception info tuple (type, value, traceback)
165
"""
166
167
def better_traceback(sio, exc_info) -> None:
168
"""
169
Better-exceptions traceback formatter function.
170
171
Args:
172
sio: Text stream to write to
173
exc_info: Exception info tuple (type, value, traceback)
174
"""
175
176
rich_traceback: RichTracebackFormatter
177
"""Pre-configured RichTracebackFormatter instance."""
178
```
179
180
### Exception Info Processing
181
182
Processor for automatically setting exception info in log events.
183
184
```python { .api }
185
def set_exc_info(logger, method_name, event_dict) -> EventDict:
186
"""
187
Set exc_info=True for exception-related log methods.
188
189
Automatically adds exception information when logging methods
190
like 'exception', 'error', etc. are called.
191
192
Args:
193
logger: Logger instance
194
method_name (str): Name of the logger method being called
195
event_dict (dict): Event dictionary
196
197
Returns:
198
dict: Event dictionary with exc_info set if appropriate
199
"""
200
```
201
202
### Color Constants
203
204
ANSI color code constants for custom styling.
205
206
```python { .api }
207
RESET_ALL: str # Reset all formatting
208
BRIGHT: str # Bright/bold text
209
DIM: str # Dim text
210
211
# Foreground colors
212
RED: str
213
BLUE: str
214
CYAN: str
215
MAGENTA: str
216
YELLOW: str
217
GREEN: str
218
219
# Background colors
220
RED_BACK: str
221
```
222
223
## Usage Examples
224
225
### Basic Development Configuration
226
227
```python
228
import structlog
229
from structlog import dev, processors
230
231
structlog.configure(
232
processors=[
233
processors.TimeStamper(fmt="iso"),
234
dev.ConsoleRenderer(
235
colors=True,
236
exception_formatter=dev.rich_traceback
237
)
238
],
239
wrapper_class=structlog.BoundLogger,
240
)
241
242
logger = structlog.get_logger()
243
logger.info("Application started", version="1.0.0", debug=True)
244
```
245
246
### Custom Console Styling
247
248
```python
249
import structlog
250
from structlog import dev, processors
251
252
# Custom level styles
253
custom_styles = {
254
"debug": dev.CYAN,
255
"info": dev.GREEN,
256
"warning": dev.YELLOW,
257
"error": dev.RED,
258
"critical": dev.RED_BACK
259
}
260
261
console_renderer = dev.ConsoleRenderer(
262
colors=True,
263
level_styles=custom_styles,
264
pad_event=40,
265
sort_keys=False,
266
event_key="message",
267
timestamp_key="ts"
268
)
269
270
structlog.configure(
271
processors=[
272
processors.TimeStamper(key="ts"),
273
console_renderer
274
],
275
wrapper_class=structlog.BoundLogger,
276
)
277
278
logger = structlog.get_logger()
279
logger.warning("Custom styling", component="auth", user_count=42)
280
```
281
282
### Column-Based Formatting
283
284
```python
285
import structlog
286
from structlog import dev, processors
287
288
# Define custom columns
289
timestamp_column = dev.Column(
290
key="timestamp",
291
formatter=dev.KeyValueColumnFormatter(
292
key_style="", # No styling for timestamp key
293
value_style=dev.DIM,
294
reset_style=dev.RESET_ALL,
295
value_repr=str,
296
width=25
297
)
298
)
299
300
level_column = dev.Column(
301
key="level",
302
formatter=dev.LogLevelColumnFormatter(
303
level_styles=dev.ConsoleRenderer.get_default_level_styles(),
304
reset_style=dev.RESET_ALL,
305
width=8
306
)
307
)
308
309
console_renderer = dev.ConsoleRenderer(
310
columns=[timestamp_column, level_column],
311
colors=True
312
)
313
314
structlog.configure(
315
processors=[
316
processors.TimeStamper(),
317
processors.add_log_level,
318
console_renderer
319
],
320
wrapper_class=structlog.BoundLogger,
321
)
322
```
323
324
### Rich Exception Formatting
325
326
```python
327
import structlog
328
from structlog import dev, processors
329
330
# Configure rich traceback formatter
331
rich_formatter = dev.RichTracebackFormatter(
332
show_locals=True,
333
max_frames=20,
334
locals_max_length=5,
335
locals_max_string=50,
336
color_system="truecolor",
337
theme="monokai"
338
)
339
340
structlog.configure(
341
processors=[
342
processors.TimeStamper(),
343
dev.set_exc_info, # Automatically set exc_info for exceptions
344
dev.ConsoleRenderer(
345
exception_formatter=rich_formatter,
346
colors=True
347
)
348
],
349
wrapper_class=structlog.BoundLogger,
350
)
351
352
logger = structlog.get_logger()
353
354
def problematic_function():
355
local_var = "important data"
356
raise ValueError("Something went wrong")
357
358
try:
359
problematic_function()
360
except ValueError:
361
logger.exception("Function failed", context="processing_data")
362
# Will show rich traceback with local variables
363
```
364
365
### Development vs Production Configuration
366
367
```python
368
import os
369
import structlog
370
from structlog import dev, processors
371
372
def configure_logging():
373
if os.getenv("ENVIRONMENT") == "development":
374
# Development: colored console output
375
structlog.configure(
376
processors=[
377
processors.TimeStamper(fmt="%H:%M:%S"),
378
processors.add_log_level,
379
dev.ConsoleRenderer(
380
colors=True,
381
exception_formatter=dev.rich_traceback,
382
repr_native_str=True
383
)
384
],
385
wrapper_class=structlog.BoundLogger,
386
)
387
else:
388
# Production: JSON output
389
structlog.configure(
390
processors=[
391
processors.TimeStamper(fmt="iso"),
392
processors.add_log_level,
393
processors.format_exc_info,
394
processors.JSONRenderer()
395
],
396
wrapper_class=structlog.BoundLogger,
397
)
398
399
configure_logging()
400
logger = structlog.get_logger()
401
```
402
403
### Custom Exception Formatter
404
405
```python
406
import structlog
407
from structlog import dev, processors
408
import traceback
409
410
def custom_exception_formatter(sio, exc_info):
411
"""Custom exception formatter that adds extra context."""
412
sio.write(f"\n{'='*50}\n")
413
sio.write("EXCEPTION OCCURRED:\n")
414
sio.write(f"{'='*50}\n")
415
416
# Use standard traceback formatting
417
traceback.print_exception(*exc_info, file=sio)
418
419
sio.write(f"{'='*50}\n")
420
421
structlog.configure(
422
processors=[
423
processors.TimeStamper(),
424
dev.ConsoleRenderer(
425
exception_formatter=custom_exception_formatter,
426
colors=True
427
)
428
],
429
wrapper_class=structlog.BoundLogger,
430
)
431
432
logger = structlog.get_logger()
433
434
try:
435
raise RuntimeError("Custom exception handling demo")
436
except RuntimeError:
437
logger.exception("Demonstrating custom formatter")
438
```
439
440
### Conditional Coloring
441
442
```python
443
import sys
444
import structlog
445
from structlog import dev, processors
446
447
# Enable colors only if stdout is a terminal
448
use_colors = sys.stdout.isatty()
449
450
structlog.configure(
451
processors=[
452
processors.TimeStamper(),
453
processors.add_log_level,
454
dev.ConsoleRenderer(
455
colors=use_colors,
456
force_colors=False # Respect terminal detection
457
)
458
],
459
wrapper_class=structlog.BoundLogger,
460
)
461
462
logger = structlog.get_logger()
463
logger.info("Colors enabled" if use_colors else "No colors", terminal=use_colors)
464
```