File size: 2,003 Bytes
3b993c4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
import logging
import sys
from typing import Any
import structlog
def setup_logging(log_level: str = "INFO", log_file: str | None = None) -> None:
"""
Set up structured logging for the application.
Args:
log_level (str): The logging level. Defaults to "INFO".
log_file (str | None): The path to the log file. If None, logs to stdout.
"""
logging.basicConfig(level=log_level)
processors = [
structlog.contextvars.merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.StackInfoRenderer(),
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.dict_tracebacks,
]
handler: logging.Handler
if log_file:
handler = logging.FileHandler(log_file)
processors.append(structlog.processors.JSONRenderer())
else:
handler = logging.StreamHandler(sys.stdout)
processors.append(structlog.dev.ConsoleRenderer())
structlog.configure(
processors=processors, # type: ignore
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
)
root_logger = logging.getLogger()
root_logger.addHandler(handler)
def get_logger(name: str) -> structlog.stdlib.BoundLogger:
"""
Get a logger instance with the specified name.
Args:
name (str): The name of the logger.
Returns:
structlog.stdlib.BoundLogger: The logger instance.
"""
return structlog.get_logger(name) # type: ignore
def bind_extra(logger: structlog.stdlib.BoundLogger, **kwargs: Any) -> structlog.stdlib.BoundLogger:
"""
Bind extra key-value pairs to the logger.
Args:
logger (structlog.stdlib.BoundLogger): The logger instance.
**kwargs: Key-value pairs to bind to the logger.
Returns:
structlog.stdlib.BoundLogger: The logger with bound extra information.
"""
return logger.bind(**kwargs)
|