37 lines
2.2 KiB
Python
37 lines
2.2 KiB
Python
"""
|
||
فرمتکنندهی سبکِ 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)
|