Python Standard Library Logging: The Foundation of Python Observability
In Python's ecosystem, the standard library's logging module remains the bedrock of application observability. This built-in solution offers a powerful, flexible, and standardized approach to logging that has stood the test of time, continuing to serve as the foundation for Python application logging in 2025.
Why the Standard logging Module Endures as Python's Primary Logging Solution
The logging module has maintained its position as Python's go-to logging framework through several enduring strengths:
- Built-in Availability: No external dependencies required
- Hierarchical Loggers: Organize logs using a parent-child hierarchy
- Handler System: Output logs to multiple destinations simultaneously
- Filter Support: Control which log records are processed
- Formatter Framework: Customize log appearance and structure
- Thread Safety: Safe for use in concurrent applications
- Configurable: Set up via code, dictionaries, files, or environment variables
- Level-based Filtering: Granular control over verbosity
- Exception Information: Automatic inclusion of traceback information
- Extensive Documentation: Comprehensive official documentation
Getting Started with Python's logging Module
Since logging is part of the standard library, no installation is needed:
13456781011131415161819202122import logging# Basic configurationlogging.basicConfig(level=logging.INFO,format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',filename='application.log')# Simple logginglogging.info("Application started")# Different log levelslogging.debug("This won't show unless level is changed to DEBUG")logging.warning("Resource utilization high")logging.error("Failed to connect to database")# With exception informationtry:result = 10 / 0except Exception as e:logging.exception("An error occurred during calculation")
For more advanced usage with logger hierarchies:
12356791011131416171819# Create loggerlogger = logging.getLogger('my_app')logger.setLevel(logging.DEBUG)# Create console handler and set levelconsole_handler = logging.StreamHandler()console_handler.setLevel(logging.INFO)# Create formatterformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')console_handler.setFormatter(formatter)# Add handler to loggerlogger.addHandler(console_handler)# Log messageslogger.debug("Debug message")logger.info("Info message")logger.warning("Warning message")
Enhancing Python's logging with OpenTelemetry for Complete Observability
While the standard logging module provides robust capabilities, modern distributed applications demand a more integrated approach to observability. By combining Python's logging with an OpenTelemetry-native observability platform, you can transform isolated logs into components of a unified monitoring strategy.
This powerful integration enables:
- Trace Context Enrichment: Automatically add trace and span IDs to your log entries
- Log-Trace Correlation: Connect logs directly to distributed traces for context-rich debugging
- Cross-Service Visibility: Track requests across service boundaries with correlated logs
- Unified Monitoring: Manage logs, metrics, and traces through a single platform
- Contextual Analysis: Understand logs within the full application context
Implementing Python logging with OpenTelemetry
Setting up the integration requires minimal configuration:
12345689101112141516171819202122232426272829303132343536373839404142import loggingimport sysfrom opentelemetry import tracefrom opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import BatchSpanProcessorfrom opentelemetry.sdk.trace.export import ConsoleSpanExporter# Configure OpenTelemetrytrace.set_tracer_provider(TracerProvider())tracer = trace.get_tracer(__name__)span_processor = BatchSpanProcessor(ConsoleSpanExporter())trace.get_tracer_provider().add_span_processor(span_processor)# Custom log formatter that includes trace contextclass OpenTelemetryFormatter(logging.Formatter):def format(self, record):span = trace.get_current_span()if span.get_span_context().is_valid:record.trace_id = f"{span.get_span_context().trace_id:032x}"record.span_id = f"{span.get_span_context().span_id:016x}"else:record.trace_id = "undefined"record.span_id = "undefined"return super().format(record)# Configure logginglogger = logging.getLogger("app")logger.setLevel(logging.INFO)handler = logging.StreamHandler(sys.stdout)formatter = OpenTelemetryFormatter('%(asctime)s - %(name)s - [trace_id=%(trace_id)s span_id=%(span_id)s] - %(levelname)s - %(message)s')handler.setFormatter(formatter)logger.addHandler(handler)# Use trace context in logswith tracer.start_as_current_span("operation") as span:logger.info("This log will contain trace context")# Application code herelogger.warning("Warning message with trace context")# Nested spans will correctly propagate through logswith tracer.start_as_current_span("nested_operation") as child_span:logger.info("Log from nested operation")
Analyzing OpenTelemetry Logs in Dash0
Logs can be directly routed into Dash0. Dash0 with OpenTelemetry provides the ability to filter, search, group, and triage within a simple user interface, with full keyboard support. Dash0 also gives full log context by showing trace context, the call and resource that created the log - including details like the Kubernetes Pod, server, and cloud environment.
Log AI also enhanced the logs with more semantical metadata and structure without any manual pattern declaration.
Conclusion
In 2025, Python's standard library logging module continues to be the foundation of Python application logging, offering a robust, well-documented, and universally available solution. Its flexible architecture and broad ecosystem support make it suitable for projects of all sizes and complexities.
By enhancing Python's logging with OpenTelemetry integration, developers can maintain this solid foundation while gaining the advantages of unified observability. This combination delivers powerful insights by connecting logs with traces and metrics, enabling faster problem resolution and better application understanding.
For Python applications that need both reliable logging and comprehensive observability, the standard logging module with OpenTelemetry integration provides an ideal solution that leverages Python's built-in capabilities while embracing modern observability practices.