Dekorator-Logging-Muster
Einführung in Logging-Dekorateure
Logging-Dekorateure bieten eine leistungsstarke und elegante Möglichkeit, Logging-Funktionalität zu Funktionen hinzuzufügen, ohne deren Kernimplementierung zu ändern. Sie ermöglichen es Entwicklern, Logging-Anforderungen von der Geschäftslogik zu trennen.
Grundlegender Logging-Dekorator für Funktionen
import logging
import functools
def log_function_call(logger=None):
"""
Decorator to log function calls with optional custom logger
"""
if logger is None:
logger = logging.getLogger(__name__)
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
logger.info(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")
try:
result = func(*args, **kwargs)
logger.info(f"{func.__name__} returned: {result}")
return result
except Exception as e:
logger.exception(f"Exception in {func.__name__}: {e}")
raise
return wrapper
return decorator
## Example usage
@log_function_call()
def divide(a, b):
return a / b
Logging-Dekorator-Muster
Muster |
Beschreibung |
Anwendungsfall |
Function Call Logger |
Protokolliert den Eintritt, Austritt und die Parameter einer Funktion |
Debugging, Tracing |
Performance Logger |
Misst und protokolliert die Ausführungszeit einer Funktion |
Leistungsmessung |
Error Logger |
Erfasst und protokolliert Ausnahmen |
Fehlerverfolgung |
Conditional Logger |
Protokolliert basierend auf bestimmten Bedingungen |
Selektives Logging |
import time
import logging
import functools
def log_performance(logger=None, threshold=0.1):
"""
Decorator to log function performance
"""
if logger is None:
logger = logging.getLogger(__name__)
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
execution_time = time.time() - start_time
if execution_time > threshold:
logger.warning(
f"Slow function: {func.__name__} "
f"took {execution_time:.4f} seconds"
)
return result
return wrapper
return decorator
Ablauf des Loggings mit Dekoratoren
graph TD
A[Function Call] --> B[Decorator Intercepts Call]
B --> C{Log Function Entry}
C --> D[Execute Original Function]
D --> E{Log Function Result}
E --> F[Return Result]
D --> G{Handle Exceptions}
G --> H[Log Exception]
def log_with_metadata(metadata=None):
"""
Decorator that logs function calls with additional metadata
"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
logger = logging.getLogger(func.__module__)
extra_info = metadata or {}
logger.info(
f"Calling {func.__name__}",
extra={
'metadata': extra_info,
'args': args,
'kwargs': kwargs
}
)
try:
result = func(*args, **kwargs)
return result
except Exception as e:
logger.exception(f"Error in {func.__name__}")
raise
return wrapper
return decorator
Best Practices
- Halten Sie Dekorateure leichtgewichtig.
- Verwenden Sie
functools.wraps
, um die Funktionsmetadaten zu bewahren.
- Behandeln Sie Ausnahmen gracefully.
- Vermeiden Sie einen übermäßigen Logging-Overhead.
- Konfigurieren Sie die Logging-Stufen angemessen.
Indem Entwickler diese Dekorator-Logging-Muster beherrschen, können sie mithilfe der von LabEx empfohlenen Techniken wartbareren und besser beobachtbaren Code erstellen.