cloud: production gaps (worker loop + true cancel, task result columns + migration, DB interface migration, metrics + backup)
This commit is contained in:
1 parent
07ef869267
commit
631580beab
14 files changed
+956
-29
No files matched your search
@@ -0,0 +1,54 @@
|
||||
"""结构化日志: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,
|
||||
})
|
||||
Reference in new issue
Block a user