Context Managers¶
LogEverything provides powerful context managers that allow you to temporarily modify logging behavior, capture output, and manage logging scope with clean, Pythonic syntax.
Overview¶
Context managers in LogEverything enable:
Temporary Configuration: Modify logger settings within a specific scope
Output Capture: Capture and redirect log output programmatically
Scope Management: Create isolated logging environments
Resource Cleanup: Automatic restoration of previous settings
Basic Context Managers¶
Temporary Level Changes¶
Temporarily change the logging level for a specific code block:
from logeverything import Logger
logger = Logger()
# Normal logging level
logger.info("This will be shown")
logger.debug("This won't be shown (default level is INFO)")
# Temporarily change to DEBUG level
with logger.level("DEBUG"):
logger.info("This will be shown")
logger.debug("Now this will also be shown!")
# Back to original level
logger.debug("This won't be shown again")
Output:
2024-01-15 10:30:15 | INFO | This will be shown
2024-01-15 10:30:15 | INFO | This will be shown
2024-01-15 10:30:15 | DEBUG | Now this will also be shown!
Temporary Format Changes¶
Change the output format temporarily:
from logeverything import Logger
logger = Logger()
logger.info("Default format")
with logger.format("{timestamp} [{level}] {message}"):
logger.info("Custom format")
logger.warning("Another custom format message")
logger.info("Back to default format")
Output Capture¶
String Capture¶
Capture log output as a string:
from logeverything import Logger
logger = Logger()
with logger.capture() as captured:
logger.info("This will be captured")
logger.warning("So will this")
logger.error("And this too")
print("Captured output:")
print(captured.getvalue())
Output:
Captured output:
2024-01-15 10:30:15 | INFO | This will be captured
2024-01-15 10:30:15 | WARN | So will this
2024-01-15 10:30:15 | ERROR | And this too
List Capture¶
Capture log entries as structured data:
from logeverything import Logger
logger = Logger()
with logger.capture_list() as captured:
logger.info("First message")
logger.bind(extra={"user_id": 123}).error("Error message")
logger.debug("Debug info")
for entry in captured:
print(f"Level: {entry.level}, Message: {entry.message}")
if hasattr(entry, 'extra'):
print(f"Extra data: {entry.extra}")
File Capture¶
Capture output to a file temporarily:
from logeverything import Logger
import tempfile
import os
logger = Logger()
with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file:
with logger.capture_to_file(temp_file.name):
logger.info("This goes to the file")
logger.error("So does this")
# Read the captured content
with open(temp_file.name, 'r') as f:
content = f.read()
print("File content:")
print(content)
os.unlink(temp_file.name) # Clean up
Advanced Context Managers¶
Silent Logging¶
Temporarily disable all output:
from logeverything import Logger
logger = Logger()
logger.info("This will be shown")
with logger.silent():
logger.info("This won't be shown")
logger.error("Neither will this")
logger.info("This will be shown again")
Scoped Configuration¶
Create a temporary logger configuration:
from logeverything import Logger
logger = Logger()
config = {
'level': 'DEBUG',
'format': '[{level}] {message}',
'include_timestamp': False
}
logger.info("Original settings")
with logger.configure(**config):
logger.debug("Debug with custom format")
logger.info("Info with custom format")
logger.info("Back to original settings")
Conditional Logging¶
Enable logging only when a condition is met:
from logeverything import Logger
logger = Logger()
debug_mode = True
with logger.when(debug_mode):
logger.debug("This only logs when debug_mode is True")
debug_mode = False
with logger.when(debug_mode):
logger.debug("This won't log now")
Async Context Managers¶
AsyncLogger also supports context managers for async code:
import asyncio
from logeverything import AsyncLogger
async def example():
logger = AsyncLogger()
async with logger.level("DEBUG"):
await logger.info("Async context manager")
await logger.debug("Debug in async context")
async with logger.capture() as captured:
await logger.info("Captured async message")
await logger.error("Async error message")
print("Captured:", captured.getvalue())
asyncio.run(example())
Nested Context Managers¶
Context managers can be nested for complex scenarios:
from logeverything import Logger
logger = Logger()
logger.info("Normal logging")
with logger.level("DEBUG"):
logger.debug("Debug level enabled")
with logger.format("[{level}] {message}"):
logger.debug("Custom format + debug level")
with logger.capture() as captured:
logger.info("Captured with custom format")
logger.debug("Back to default format, still debug level")
logger.debug("Back to original level (won't show)")
logger.info("Normal logging resumed")
Custom Context Managers¶
Create your own context managers for specific use cases:
from logeverything import Logger
from contextlib import contextmanager
logger = Logger()
@contextmanager
def performance_logging():
import time
start_time = time.time()
with logger.level("DEBUG"):
logger.debug("Performance monitoring started")
try:
yield
finally:
duration = time.time() - start_time
logger.info(f"Operation completed in {duration:.2f} seconds")
# Usage
with performance_logging():
# Your code here
import time
time.sleep(1) # Simulate work
Error Handling in Context Managers¶
Context managers handle errors gracefully:
from logeverything import Logger
logger = Logger()
try:
with logger.capture() as captured:
logger.info("Before error")
raise ValueError("Something went wrong")
logger.info("This won't execute")
except ValueError as e:
logger.error(f"Caught error: {e}")
print("Captured before error:", captured.getvalue())
Best Practices¶
Use Specific Scopes: Keep context manager scopes as small as possible
Avoid Deep Nesting: Too many nested context managers can be hard to read
Handle Exceptions: Always consider what happens if code inside the context raises an exception
Resource Cleanup: Context managers automatically restore previous settings
Performance: Context managers have minimal overhead but avoid unnecessary nesting in tight loops
Common Patterns¶
Request Logging¶
Log all operations during a request with correlation ID:
from logeverything import Logger
import uuid
logger = Logger()
def handle_request(data):
request_id = str(uuid.uuid4())[:8]
with logger.extra(request_id=request_id):
logger.bind(extra={"data": data}).info("Request started")
try:
# Process request
result = process_data(data)
logger.info("Request completed successfully")
return result
except Exception as e:
logger.error(f"Request failed: {e}")
raise
Testing with Captured Output¶
Verify log output in tests:
from logeverything import Logger
def test_user_login():
logger = Logger()
with logger.capture_list() as captured:
# Code under test
login_user("john_doe")
# Verify logging
assert len(captured) == 2
assert captured[0].level == "INFO"
assert "login attempt" in captured[0].message
assert captured[1].level == "INFO"
assert "login successful" in captured[1].message
Debugging with Temporary Verbosity¶
Increase verbosity for debugging specific sections:
from logeverything import Logger
logger = Logger()
def complex_operation():
logger.info("Starting complex operation")
# Enable debug logging for this specific part
with logger.level("DEBUG"):
logger.debug("Step 1: Initialize")
step1()
logger.debug("Step 2: Process")
step2()
logger.debug("Step 3: Finalize")
step3()
logger.info("Complex operation completed")
API Reference¶
Logger Context Managers¶
- Logger.level(level)¶
Temporarily change the logging level.
- Parameters:
level (str) – New logging level (“DEBUG”, “INFO”, “WARNING”, “ERROR”, “CRITICAL”)
- Returns:
Context manager
- Return type:
ContextManager
- Logger.format(format_string)¶
Temporarily change the log format.
- Parameters:
format_string (str) – New format string
- Returns:
Context manager
- Return type:
ContextManager
- Logger.capture()¶
Capture log output as a string.
- Returns:
Context manager yielding StringIO object
- Return type:
ContextManager[StringIO]
- Logger.capture_list()¶
Capture log entries as structured data.
- Returns:
Context manager yielding list of log entries
- Return type:
ContextManager[List[LogEntry]]
- Logger.capture_to_file(filename)¶
Capture log output to a file.
- Parameters:
filename (str) – Path to output file
- Returns:
Context manager
- Return type:
ContextManager
- Logger.silent()¶
Temporarily disable all log output.
- Returns:
Context manager
- Return type:
ContextManager
- Logger.configure(**kwargs)¶
Temporarily change multiple configuration options.
- Parameters:
kwargs – Configuration options
- Returns:
Context manager
- Return type:
ContextManager
- Logger.when(condition)¶
Enable logging only when condition is True.
- Parameters:
condition (bool) – Boolean condition
- Returns:
Context manager
- Return type:
ContextManager