""" فرمت‌کننده‌ی سبکِ JSON برای خروجیِ logging — آماده‌سازیِ پروژه برای جمع‌آوریِ متمرکزِ لاگ (مثلاً یک agentِ بیرونی مثلِ Promtail/Filebeat که stdout رو می‌خونه و به Loki/ELK می‌فرسته) در آینده. ⚠️ توجه (محدوده‌ی این تغییر): - این فایل فقط *فرمتِ* خروجیِ همون لاگ‌های موجودِ اپلیکیشن رو عوض می‌کنه (یک شیِ JSON در هر خط، به‌جای متنِ ساده‌ی قبلی)؛ هیچ eventِ لاگِ جدیدی اضافه نمی‌کنه و هیچ loggerِ موجودی رو تغییر نمی‌ده. - فقط از فیلدهای استانداردِ خودِ LogRecord (زمان، سطح، نامِ logger، پیامِ از قبل ساخته‌شده، و traceback در صورتِ وجود) استفاده می‌شه؛ یعنی همون محافظت‌های حساسیتیِ قبلی (بدون OTP/token/رمزعبور/بدنه‌ی خامِ provider و غیره در پیام‌ها) دست‌نخورده می‌مونه — این فرمت‌کننده چیزی به پیام اضافه نمی‌کنه، فقط قالب‌بندیِ همون پیامِ از قبل امن رو تغییر می‌ده. - هیچ وابستگیِ جدید (Elasticsearch/Loki/Grafana client) یا appِ جدید یا ذخیره‌سازیِ دیتابیسی/APIِ لاگ اضافه نمی‌کنه؛ فقط stdlibِ logging + json. """ import json import logging from datetime import datetime, timezone class JSONLogFormatter(logging.Formatter): """هر LogRecord رو به یک خطِ JSON (سازگار با collectorهای سبکِ Loki/ELK) تبدیل می‌کنه.""" def format(self, record: logging.LogRecord) -> str: payload = { 'timestamp': datetime.fromtimestamp(record.created, tz=timezone.utc).isoformat(), 'level': record.levelname, 'logger': record.name, 'message': record.getMessage(), } if record.exc_info: payload['exception'] = self.formatException(record.exc_info) return json.dumps(payload, ensure_ascii=False)