Structured logging for Python that emphasizes simplicity, power, and performance
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.
Render structured log events as human-readable, colored console output with alignment and customizable formatting.
class ConsoleRenderer:
"""Render event dictionary as aligned, colored console output."""
def __init__(
self,
pad_event=30,
colors=True,
force_colors=False,
repr_native_str=False,
level_styles=None,
exception_formatter=default_exception_formatter,
sort_keys=True,
event_key="event",
timestamp_key="timestamp",
columns=None,
pad_level=True
):
"""
Args:
pad_event (int): Minimum width for event column
colors (bool): Enable colored output
force_colors (bool): Force colors even when not in terminal
repr_native_str (bool): Use repr() for string values
level_styles (dict, optional): Custom color styles for log levels
exception_formatter (callable): Function to format exceptions
sort_keys (bool): Sort context keys alphabetically
event_key (str): Key name for main event message
timestamp_key (str): Key name for timestamp
columns (list, optional): Custom column configuration
pad_level (bool): Pad log level names for alignment
"""
def __call__(self, logger, name, event_dict) -> str: ...
@staticmethod
def get_default_level_styles(colors=True) -> dict[str, str]:
"""
Get default color styles for log levels.
Args:
colors (bool): Return colored styles if True, empty styles if False
Returns:
dict: Mapping of log level names to ANSI color codes
"""Flexible column-based formatting system for structured console output.
class Column:
"""Column definition for console rendering."""
key: str # Key for which this column is responsible
formatter: ColumnFormatter # Column formatter instance
class KeyValueColumnFormatter:
"""Format key-value pairs with customizable styling."""
def __init__(
self,
key_style,
value_style,
reset_style,
value_repr,
width=0,
prefix="",
postfix=""
):
"""
Args:
key_style (str): ANSI style code for keys
value_style (str): ANSI style code for values
reset_style (str): ANSI reset code
value_repr (callable): Function to convert values to strings
width (int): Minimum column width
prefix (str): Text to prepend to output
postfix (str): Text to append to output
"""
def __call__(self, key, value) -> str: ...
class LogLevelColumnFormatter:
"""Format log level names with level-specific styling."""
def __init__(self, level_styles, reset_style, width=None):
"""
Args:
level_styles (dict): Mapping of level names to style codes
reset_style (str): ANSI reset code
width (int, optional): Fixed width for level column
"""
def __call__(self, key, value) -> str: ...
# Protocol for column formatters
class ColumnFormatter(Protocol):
"""Protocol for column formatter functions."""
def __call__(self, key: str, value: object) -> str: ...Advanced exception and traceback formatting with multiple rendering options.
class RichTracebackFormatter:
"""Rich traceback renderer with syntax highlighting and local variables."""
def __init__(
self,
color_system="truecolor",
show_locals=True,
max_frames=100,
theme=None,
word_wrap=False,
extra_lines=3,
width=100,
indent_guides=True,
locals_max_length=10,
locals_max_string=80,
locals_hide_dunder=True,
locals_hide_sunder=False,
suppress=()
):
"""
Args:
color_system (str): Color system ("truecolor", "256", "standard", "windows")
show_locals (bool): Show local variables in traceback
max_frames (int): Maximum number of frames to show
theme (str, optional): Syntax highlighting theme
word_wrap (bool): Enable word wrapping
extra_lines (int): Extra lines of context around each frame
width (int): Console width for formatting
indent_guides (bool): Show indentation guides
locals_max_length (int): Maximum number of local variables to show
locals_max_string (int): Maximum length of local variable strings
locals_hide_dunder (bool): Hide dunder variables (__var__)
locals_hide_sunder (bool): Hide sunder variables (_var)
suppress (tuple): Modules to suppress in traceback
"""
def __call__(self, sio, exc_info) -> None: ...
def plain_traceback(sio, exc_info) -> None:
"""
Plain traceback formatter function.
Args:
sio: Text stream to write to
exc_info: Exception info tuple (type, value, traceback)
"""
def better_traceback(sio, exc_info) -> None:
"""
Better-exceptions traceback formatter function.
Args:
sio: Text stream to write to
exc_info: Exception info tuple (type, value, traceback)
"""
rich_traceback: RichTracebackFormatter
"""Pre-configured RichTracebackFormatter instance."""Processor for automatically setting exception info in log events.
def set_exc_info(logger, method_name, event_dict) -> EventDict:
"""
Set exc_info=True for exception-related log methods.
Automatically adds exception information when logging methods
like 'exception', 'error', etc. are called.
Args:
logger: Logger instance
method_name (str): Name of the logger method being called
event_dict (dict): Event dictionary
Returns:
dict: Event dictionary with exc_info set if appropriate
"""ANSI color code constants for custom styling.
RESET_ALL: str # Reset all formatting
BRIGHT: str # Bright/bold text
DIM: str # Dim text
# Foreground colors
RED: str
BLUE: str
CYAN: str
MAGENTA: str
YELLOW: str
GREEN: str
# Background colors
RED_BACK: strimport structlog
from structlog import dev, processors
structlog.configure(
processors=[
processors.TimeStamper(fmt="iso"),
dev.ConsoleRenderer(
colors=True,
exception_formatter=dev.rich_traceback
)
],
wrapper_class=structlog.BoundLogger,
)
logger = structlog.get_logger()
logger.info("Application started", version="1.0.0", debug=True)import structlog
from structlog import dev, processors
# Custom level styles
custom_styles = {
"debug": dev.CYAN,
"info": dev.GREEN,
"warning": dev.YELLOW,
"error": dev.RED,
"critical": dev.RED_BACK
}
console_renderer = dev.ConsoleRenderer(
colors=True,
level_styles=custom_styles,
pad_event=40,
sort_keys=False,
event_key="message",
timestamp_key="ts"
)
structlog.configure(
processors=[
processors.TimeStamper(key="ts"),
console_renderer
],
wrapper_class=structlog.BoundLogger,
)
logger = structlog.get_logger()
logger.warning("Custom styling", component="auth", user_count=42)import structlog
from structlog import dev, processors
# Define custom columns
timestamp_column = dev.Column(
key="timestamp",
formatter=dev.KeyValueColumnFormatter(
key_style="", # No styling for timestamp key
value_style=dev.DIM,
reset_style=dev.RESET_ALL,
value_repr=str,
width=25
)
)
level_column = dev.Column(
key="level",
formatter=dev.LogLevelColumnFormatter(
level_styles=dev.ConsoleRenderer.get_default_level_styles(),
reset_style=dev.RESET_ALL,
width=8
)
)
console_renderer = dev.ConsoleRenderer(
columns=[timestamp_column, level_column],
colors=True
)
structlog.configure(
processors=[
processors.TimeStamper(),
processors.add_log_level,
console_renderer
],
wrapper_class=structlog.BoundLogger,
)import structlog
from structlog import dev, processors
# Configure rich traceback formatter
rich_formatter = dev.RichTracebackFormatter(
show_locals=True,
max_frames=20,
locals_max_length=5,
locals_max_string=50,
color_system="truecolor",
theme="monokai"
)
structlog.configure(
processors=[
processors.TimeStamper(),
dev.set_exc_info, # Automatically set exc_info for exceptions
dev.ConsoleRenderer(
exception_formatter=rich_formatter,
colors=True
)
],
wrapper_class=structlog.BoundLogger,
)
logger = structlog.get_logger()
def problematic_function():
local_var = "important data"
raise ValueError("Something went wrong")
try:
problematic_function()
except ValueError:
logger.exception("Function failed", context="processing_data")
# Will show rich traceback with local variablesimport os
import structlog
from structlog import dev, processors
def configure_logging():
if os.getenv("ENVIRONMENT") == "development":
# Development: colored console output
structlog.configure(
processors=[
processors.TimeStamper(fmt="%H:%M:%S"),
processors.add_log_level,
dev.ConsoleRenderer(
colors=True,
exception_formatter=dev.rich_traceback,
repr_native_str=True
)
],
wrapper_class=structlog.BoundLogger,
)
else:
# Production: JSON output
structlog.configure(
processors=[
processors.TimeStamper(fmt="iso"),
processors.add_log_level,
processors.format_exc_info,
processors.JSONRenderer()
],
wrapper_class=structlog.BoundLogger,
)
configure_logging()
logger = structlog.get_logger()import structlog
from structlog import dev, processors
import traceback
def custom_exception_formatter(sio, exc_info):
"""Custom exception formatter that adds extra context."""
sio.write(f"\n{'='*50}\n")
sio.write("EXCEPTION OCCURRED:\n")
sio.write(f"{'='*50}\n")
# Use standard traceback formatting
traceback.print_exception(*exc_info, file=sio)
sio.write(f"{'='*50}\n")
structlog.configure(
processors=[
processors.TimeStamper(),
dev.ConsoleRenderer(
exception_formatter=custom_exception_formatter,
colors=True
)
],
wrapper_class=structlog.BoundLogger,
)
logger = structlog.get_logger()
try:
raise RuntimeError("Custom exception handling demo")
except RuntimeError:
logger.exception("Demonstrating custom formatter")import sys
import structlog
from structlog import dev, processors
# Enable colors only if stdout is a terminal
use_colors = sys.stdout.isatty()
structlog.configure(
processors=[
processors.TimeStamper(),
processors.add_log_level,
dev.ConsoleRenderer(
colors=use_colors,
force_colors=False # Respect terminal detection
)
],
wrapper_class=structlog.BoundLogger,
)
logger = structlog.get_logger()
logger.info("Colors enabled" if use_colors else "No colors", terminal=use_colors)Install with Tessl CLI
npx tessl i tessl/pypi-structlog