90 lines
2.3 KiB
Python
90 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
import logging
|
|
import time
|
|
from typing import Any, Dict, Optional
|
|
|
|
|
|
def build_trace_id(*parts: str) -> str:
|
|
raw = "|".join(str(p or "") for p in parts)
|
|
digest = hashlib.md5(raw.encode("utf-8")).hexdigest()
|
|
return digest[:16]
|
|
|
|
|
|
def emit_activity(
|
|
logger: logging.Logger,
|
|
*,
|
|
event: str,
|
|
trace_id: str = "",
|
|
customer_id: str = "",
|
|
result: str = "ok",
|
|
latency_ms: Optional[int] = None,
|
|
**fields: Any,
|
|
) -> None:
|
|
payload: Dict[str, Any] = {
|
|
"trace_id": trace_id or "-",
|
|
"customer_id": customer_id or "-",
|
|
"event": event,
|
|
"result": result,
|
|
}
|
|
if latency_ms is not None:
|
|
payload["latency_ms"] = int(max(0, latency_ms))
|
|
for k, v in (fields or {}).items():
|
|
if isinstance(v, str):
|
|
payload[k] = v[:400]
|
|
else:
|
|
payload[k] = v
|
|
try:
|
|
logger.info(f"[ACTIVITY] {json.dumps(payload, ensure_ascii=False)}")
|
|
except Exception:
|
|
logger.info(f"[ACTIVITY] {payload}")
|
|
|
|
|
|
class ActivityTimer:
|
|
def __init__(
|
|
self,
|
|
*,
|
|
logger: logging.Logger,
|
|
event: str,
|
|
trace_id: str = "",
|
|
customer_id: str = "",
|
|
**fields: Any,
|
|
):
|
|
self.logger = logger
|
|
self.event = event
|
|
self.trace_id = trace_id
|
|
self.customer_id = customer_id
|
|
self.fields = fields
|
|
self.start = time.monotonic()
|
|
|
|
def ok(self, **fields: Any) -> None:
|
|
elapsed_ms = int((time.monotonic() - self.start) * 1000)
|
|
merged = dict(self.fields)
|
|
merged.update(fields)
|
|
emit_activity(
|
|
self.logger,
|
|
event=self.event,
|
|
trace_id=self.trace_id,
|
|
customer_id=self.customer_id,
|
|
result="ok",
|
|
latency_ms=elapsed_ms,
|
|
**merged,
|
|
)
|
|
|
|
def fail(self, error: str, **fields: Any) -> None:
|
|
elapsed_ms = int((time.monotonic() - self.start) * 1000)
|
|
merged = dict(self.fields)
|
|
merged.update(fields)
|
|
emit_activity(
|
|
self.logger,
|
|
event=self.event,
|
|
trace_id=self.trace_id,
|
|
customer_id=self.customer_id,
|
|
result="error",
|
|
latency_ms=elapsed_ms,
|
|
error=error,
|
|
**merged,
|
|
)
|