core.structured_logger module
Structured (JSON) logging for the microservices.
JSONFormatter renders each log record as a single-line JSON
object enriched with service name, instance id, and version (plus a
formatted traceback for exceptions), so logs from every service
aggregate cleanly in journald or a downstream log pipeline.
- class core.structured_logger.JSONFormatter(service_name, instance_id, version)[source]
Bases:
FormatterRender standard logging records as single-line JSON with service context.
A
logging.Formattersubclass that turns every log record into one JSON object enriched with the static service name, instance id, and version bound at construction, so that logs from all five microservices aggregate and correlate cleanly in journald or a downstream log pipeline instead of being free-form text. Instances are installed as a handler’s formatter byconfigure_logging(); once installed, the logging framework callsformat()for every emitted record. Constructed byconfigure_logging()in this module and directly in tests.- __init__(service_name, instance_id, version)[source]
Bind the static service context attached to every formatted record.
Calls the base
logging.Formatterinitialiser, then stores the service name, instance id, and version thatformat()injects into each emitted JSON line so logs from every microservice can be told apart and version-correlated in journald or a downstream pipeline. Instantiated byconfigure_logging()in this module (and directly in tests); there are no other internal callers.
- format(record)[source]
Render a log record as a single-line JSON object with service context.
Assembles a dictionary with an ISO-8601 timestamp derived from
record.created, the level, the boundservice/instance_id/versioncaptured in__init__, the logger name, and the rendered message. If the record carries exception info, the full formatted traceback is added underexc_infoviatraceback.format_exception. Any custom fields supplied throughlogger.x(..., extra={...})are then merged in, skipping the standardlogging.LogRecordattributes so only caller-provided context survives. The dict is serialised withjson.dumps. This is called implicitly by the logging framework for every record once an instance is installed as a handler’s formatter (done byconfigure_logging()); there are no direct internal callers.
- core.structured_logger.configure_logging(service_name, instance_id, version, level=20, stream=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>)[source]
Install a JSON formatter on the root logger for the whole process.
Reconfigures Python’s root logger so every record emitted anywhere in the service is rendered as a single-line JSON object carrying the supplied service identity, giving the microservice uniform machine-parseable logs. It removes any pre-existing root handlers first (preventing duplicate output if called more than once), then attaches a fresh
logging.StreamHandleronstreamwhose formatter is aJSONFormatterbound to the given service name, instance id, and version, and sets the root level. Mutates global logging state and writes tostream(stdout by default); performs no Redis or network I/O. Called once at service startup by each microservice entrypoint and exercised by the migration tests intests/core/migration/test_structured_logger.py.- Parameters:
service_name (
str) – Logical service name (e.g."gateway") stamped on every record under theservicekey.instance_id (
str) – Unique per-process identifier emitted underinstance_id.version (
str) – Build or release version string emitted underversion.level (
int) – Root logger threshold; defaults tologging.INFO.stream (
TextIO) – Output stream the handler writes to; defaults tosys.stdout.