55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
"""结构化日志:JSON 行日志,含时间、级别、服务、任务 id、事件。
|
|
|
|
只用标准库 logging。日志绝不写任何密钥、API key、环境变量值:
|
|
调用方只传任务 id、状态、事件名这类非敏感字段。
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
import sys
|
|
import time
|
|
|
|
|
|
class JsonFormatter(logging.Formatter):
|
|
"""把每条记录格式化成一行 JSON,方便后续按字段过滤聚合。"""
|
|
|
|
def format(self, record):
|
|
payload = {
|
|
"ts": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(record.created)),
|
|
"level": record.levelname,
|
|
"service": "cloud-control-plane",
|
|
"logger": record.name,
|
|
"message": record.getMessage(),
|
|
}
|
|
for key in ("task_id", "project_id", "event", "status"):
|
|
if hasattr(record, key):
|
|
payload[key] = getattr(record, key)
|
|
if record.exc_info and record.exc_info[0] is not None:
|
|
payload["error_type"] = record.exc_info[0].__name__
|
|
return json.dumps(payload, ensure_ascii=False)
|
|
|
|
|
|
def setup_logging(level=logging.INFO, stream=None):
|
|
"""配置根 logger 为 JSON 行日志;重复调用不重复加 handler。"""
|
|
handler = logging.StreamHandler(stream or sys.stderr)
|
|
handler.setFormatter(JsonFormatter())
|
|
root = logging.getLogger()
|
|
root.handlers = [handler]
|
|
root.setLevel(level)
|
|
return root
|
|
|
|
|
|
def get_logger(name="cloud"):
|
|
return logging.getLogger(name)
|
|
|
|
|
|
def log_event(logger, event, task_id=None, project_id=None, status=None,
|
|
message=None):
|
|
"""记一条结构化事件日志;message 默认就是事件名。"""
|
|
logger.info(message or event, extra={
|
|
"event": event,
|
|
"task_id": task_id,
|
|
"project_id": project_id,
|
|
"status": status,
|
|
})
|