Migration Guide¶
obslog interoperates with existing logging rather than demanding a rewrite. You can adopt it incrementally.
From the standard library logging¶
Keep your existing handlers and route obslog through them, or route stdlib logs into
obslog. Both directions live in obslog.integrations (no extra required).
import logging
import obslog
from obslog.integrations import LoggingSink, ObslogHandler
# obslog -> logging: obslog records flow through your existing logging config
obslog.configure(sinks=[LoggingSink(logging.getLogger("app"))])
# logging -> obslog: third-party library logs become obslog records
logging.getLogger().addHandler(ObslogHandler())
Translation of concepts:
stdlib logging |
obslog |
|---|---|
logger.info("user %s", uid) |
log.info("user.action", user_id=uid) |
logging.getLogger(__name__) |
obslog.get_logger(__name__) |
extra={...} |
keyword fields (land under metadata) |
levels DEBUG..CRITICAL |
TRACE, DEBUG, INFO, WARNING, ERROR, CRITICAL |
dictConfig |
configure_from_file / configure_from_env |
From structlog¶
# structlog
log = structlog.get_logger().bind(request_id=rid)
log.info("order_completed", order_id=7)
# obslog
log = obslog.get_logger(__name__).bind(request_id=rid)
log.info("order.completed", order_id=7)
bind()works the same (immutable) and returns a new logger.- structlog's
contextvarsbinding maps toobslog.context(...). - The processor pipeline maps to obslog
processorsinside aPipelinesink.
From loguru¶
# loguru
from loguru import logger
logger.bind(order_id=7).info("Order completed")
# obslog
obslog.get_logger(__name__).info("order.completed", order_id=7)
- loguru's single global
loggerbecomesget_logger(...); obslog additionally supports isolated providers so libraries never fight over global state. logger.contextualize(...)maps toobslog.context(...).- Prefer stable event names over human sentences — the human message is optional
(
message=), the event name is the machine key.
Tips¶
- Reach for event names (
order.completed) rather than sentences; put the varying data in fields, not string interpolation. - Use
error_code=for a stable identifier the moment you have a known failure mode.