================================ Pythonでjson形式のログを出力する ================================ .. list-table:: :widths: 20 80 * - 公開日 - 2024-11-05 16:08 * - トピック - python * - Zenn - https://zenn.dev/fkzwsoftwaredev/articles/753373f302cecd .. _1-loggingモジュール-と-jsonモジュールを使う: 1. loggingモジュール と jsonモジュールを使う -------------------------------------------- ソースコード ~~~~~~~~~~~~ .. code:: python import logging import json class JsonFormatter(logging.Formatter): def format(self, record): # JSONに含めたいフィールドを辞書として定義 log_record = { "timestamp": self.formatTime(record), "logger": record.name, "level": record.levelname, "message": record.getMessage(), } # record.__dict__から追加情報を取得し、log_recordに追加 log_record.update({key: value for key, value in record.__dict__.items() if key not in log_record}) return json.dumps(log_record) # ロガーの設定 logger = logging.getLogger("json_logger") logger.setLevel(logging.DEBUG) # ハンドラーとフォーマッタの設定 handler = logging.StreamHandler() handler.setFormatter(JsonFormatter()) logger.addHandler(handler) # ログ出力(追加情報を渡す例) logger.debug("This is a DEBUG message", extra={"user_id": 123, "transaction_id": "abc123"}) logger.info("This is an INFO message", extra={"user_id": 456, "transaction_id": "def456"}) logger.warning("This is a WARNING message") logger.error("This is an ERROR message", extra={"error_code": 500}) logger.critical("This is a CRITICAL message", extra={"urgent": True}) 出力結果 ~~~~~~~~ .. code:: python {"timestamp": "2024-11-04 22:23:53,338", "logger": "json_logger", "level": "DEBUG", "message": "This is a DEBUG message", "name": "json_logger", "msg": "This is a DEBUG message", "args": [], "levelname": "DEBUG", "levelno": 10, "pathname": "", "filename": "", "module": "", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 28, "funcName": "", "created": 1730726633.338757, "msecs": 338.0, "relativeCreated": 1819.5860385894775, "thread": 8681610752, "threadName": "MainThread", "processName": "MainProcess", "process": 47518, "taskName": null, "user_id": 123, "transaction_id": "abc123"} {"timestamp": "2024-11-04 22:23:53,338", "logger": "json_logger", "level": "INFO", "message": "This is an INFO message", "name": "json_logger", "msg": "This is an INFO message", "args": [], "levelname": "INFO", "levelno": 20, "pathname": "", "filename": "", "module": "", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 29, "funcName": "", "created": 1730726633.338881, "msecs": 338.0, "relativeCreated": 1819.7100162506104, "thread": 8681610752, "threadName": "MainThread", "processName": "MainProcess", "process": 47518, "taskName": null, "user_id": 456, "transaction_id": "def456"} {"timestamp": "2024-11-04 22:23:53,339", "logger": "json_logger", "level": "WARNING", "message": "This is a WARNING message", "name": "json_logger", "msg": "This is a WARNING message", "args": [], "levelname": "WARNING", "levelno": 30, "pathname": "", "filename": "", "module": "", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 30, "funcName": "", "created": 1730726633.3390179, "msecs": 339.0, "relativeCreated": 1819.8468685150146, "thread": 8681610752, "threadName": "MainThread", "processName": "MainProcess", "process": 47518, "taskName": null} {"timestamp": "2024-11-04 22:23:53,339", "logger": "json_logger", "level": "ERROR", "message": "This is an ERROR message", "name": "json_logger", "msg": "This is an ERROR message", "args": [], "levelname": "ERROR", "levelno": 40, "pathname": "", "filename": "", "module": "", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 31, "funcName": "", "created": 1730726633.339106, "msecs": 339.0, "relativeCreated": 1819.9350833892822, "thread": 8681610752, "threadName": "MainThread", "processName": "MainProcess", "process": 47518, "taskName": null, "error_code": 500} {"timestamp": "2024-11-04 22:23:53,339", "logger": "json_logger", "level": "CRITICAL", "message": "This is a CRITICAL message", "name": "json_logger", "msg": "This is a CRITICAL message", "args": [], "levelname": "CRITICAL", "levelno": 50, "pathname": "", "filename": "", "module": "", "exc_info": null, "exc_text": null, "stack_info": null, "lineno": 32, "funcName": "", "created": 1730726633.339234, "msecs": 339.0, "relativeCreated": 1820.0631141662598, "thread": 8681610752, "threadName": "MainThread", "processName": "MainProcess", "process": 47518, "taskName": null, "urgent": true} .. _2-loggingモジュール-と-python-json-loggerモジュールを使う: 2. loggingモジュール と python-json-loggerモジュールを使う ---------------------------------------------------------- - `python-json-logger `__ 2023年2月22日 v2.0.7 リリース以降更新が止まっていそう .. _ソースコード-1: ソースコード ~~~~~~~~~~~~ .. code:: python import logging from pythonjsonlogger import jsonlogger # ロガーの設定 logger = logging.getLogger("json_logger") logger.setLevel(logging.DEBUG) # ハンドラーとフォーマッタの設定 handler = logging.StreamHandler() formatter = jsonlogger.JsonFormatter( fmt="%(asctime)s %(name)s %(levelname)s %(message)s" ) handler.setFormatter(formatter) logger.addHandler(handler) # ログ出力(追加情報を渡す例) logger.debug("This is a DEBUG message", extra={"user_id": 123, "transaction_id": "abc123"}) logger.info("This is an INFO message", extra={"user_id": 456, "transaction_id": "def456"}) logger.warning("This is a WARNING message") logger.error("This is an ERROR message", extra={"error_code": 500}) logger.critical("This is a CRITICAL message", extra={"urgent": True}) .. _出力結果-1: 出力結果 ~~~~~~~~ .. code:: python {"asctime": "2024-11-04 22:32:40,700", "name": "json_logger", "levelname": "DEBUG", "message": "This is a DEBUG message", "taskName": null, "user_id": 123, "transaction_id": "abc123"} {"asctime": "2024-11-04 22:32:40,700", "name": "json_logger", "levelname": "INFO", "message": "This is an INFO message", "taskName": null, "user_id": 456, "transaction_id": "def456"} {"asctime": "2024-11-04 22:32:40,700", "name": "json_logger", "levelname": "WARNING", "message": "This is a WARNING message", "taskName": null} {"asctime": "2024-11-04 22:32:40,700", "name": "json_logger", "levelname": "ERROR", "message": "This is an ERROR message", "taskName": null, "error_code": 500} {"asctime": "2024-11-04 22:32:40,700", "name": "json_logger", "levelname": "CRITICAL", "message": "This is a CRITICAL message", "taskName": null, "urgent": true} .. _3-structlogを使う: 3. structlogを使う ------------------ - `structlog `__ 2024年7月17日 v24.4.0 リリース .. _ソースコード-2: ソースコード ~~~~~~~~~~~~ .. code:: python import structlog import logging # Pythonの標準ログをJSONに出力するための設定 logging.basicConfig(level=logging.DEBUG) structlog.configure( processors=[ structlog.processors.TimeStamper(fmt="iso", utc=False), structlog.processors.JSONRenderer() ], logger_factory=structlog.stdlib.LoggerFactory(), ) # ロガーの取得 logger = structlog.get_logger("json_logger") # ログ出力(追加情報を渡す例) logger.debug("This is a DEBUG message", user_id=123, transaction_id="abc123") logger.info("This is an INFO message", user_id=456, transaction_id="def456") logger.warning("This is a WARNING message") logger.error("This is an ERROR message", error_code=500) logger.critical("This is a CRITICAL message", urgent=True) .. _出力結果-2: 出力結果 ~~~~~~~~ .. code:: python DEBUG:json_logger:{"user_id": 123, "transaction_id": "abc123", "event": "This is a DEBUG message", "timestamp": "2024-11-04T22:37:43.273906"} INFO:json_logger:{"user_id": 456, "transaction_id": "def456", "event": "This is an INFO message", "timestamp": "2024-11-04T22:37:43.274380"} WARNING:json_logger:{"event": "This is a WARNING message", "timestamp": "2024-11-04T22:37:43.274477"} ERROR:json_logger:{"error_code": 500, "event": "This is an ERROR message", "timestamp": "2024-11-04T22:37:43.274561"} CRITICAL:json_logger:{"urgent": true, "event": "This is a CRITICAL message", "timestamp": "2024-11-04T22:37:43.274663"} ソースコード 2 ~~~~~~~~~~~~~~ .. code:: python import structlog import logging from pythonjsonlogger import jsonlogger # 標準の logging の設定 log_handler = logging.StreamHandler() formatter = jsonlogger.JsonFormatter( fmt='%(asctime)s %(name)s %(levelname)s %(message)s' ) log_handler.setFormatter(formatter) logging.basicConfig(handlers=[log_handler], level=logging.DEBUG) # structlog の設定 structlog.configure( processors=[ structlog.processors.TimeStamper(fmt="iso"), structlog.stdlib.add_logger_name, structlog.stdlib.add_log_level, structlog.processors.JSONRenderer() ], wrapper_class=structlog.make_filtering_bound_logger(logging.DEBUG), context_class=dict, logger_factory=structlog.stdlib.LoggerFactory(), cache_logger_on_first_use=True, ) # ロガーの取得 logger = structlog.get_logger("json_logger") # ログ出力例 logger.debug("This is a DEBUG message", user_id=123, transaction_id="abc123") logger.info("This is an INFO message", user_id=456, transaction_id="def456") logger.warning("This is a WARNING message") logger.error("This is an ERROR message", error_code=500) logger.critical("This is a CRITICAL message", urgent=True) 出力結果2 ~~~~~~~~~ .. code:: python {"asctime": "2024-11-04 22:41:59,173", "name": "json_logger", "levelname": "DEBUG", "message": "{\"user_id\": 123, \"transaction_id\": \"abc123\", \"event\": \"This is a DEBUG message\", \"timestamp\": \"2024-11-04T13:41:59.172661Z\", \"logger\": \"json_logger\", \"level\": \"debug\"}", "taskName": null} {"asctime": "2024-11-04 22:41:59,173", "name": "json_logger", "levelname": "INFO", "message": "{\"user_id\": 456, \"transaction_id\": \"def456\", \"event\": \"This is an INFO message\", \"timestamp\": \"2024-11-04T13:41:59.173167Z\", \"logger\": \"json_logger\", \"level\": \"info\"}", "taskName": null} {"asctime": "2024-11-04 22:41:59,173", "name": "json_logger", "levelname": "WARNING", "message": "{\"event\": \"This is a WARNING message\", \"timestamp\": \"2024-11-04T13:41:59.173267Z\", \"logger\": \"json_logger\", \"level\": \"warning\"}", "taskName": null} {"asctime": "2024-11-04 22:41:59,173", "name": "json_logger", "levelname": "ERROR", "message": "{\"error_code\": 500, \"event\": \"This is an ERROR message\", \"timestamp\": \"2024-11-04T13:41:59.173346Z\", \"logger\": \"json_logger\", \"level\": \"error\"}", "taskName": null} {"asctime": "2024-11-04 22:41:59,173", "name": "json_logger", "levelname": "CRITICAL", "message": "{\"urgent\": true, \"event\": \"This is a CRITICAL message\", \"timestamp\": \"2024-11-04T13:41:59.173423Z\", \"logger\": \"json_logger\", \"level\": \"critical\"}", "taskName": null} .. _4-django-structlogを使う: 4. django-structlogを使う ------------------------- - `django-structlog `__ 2024年11月時点でレポジトリ更新されている