Files
HSAP/platform/as_platform/agents/trace.py

63 lines
1.9 KiB
Python
Raw Normal View History

"""LangSmith 式 tracemanifests/trace_log.jsonl"""
from __future__ import annotations
import json
import uuid
from contextlib import contextmanager
from datetime import datetime, timezone
from typing import Any, Iterator
from as_platform.config import TRACE_LOG, MANIFESTS
_current_trace: str | None = None
def _now() -> str:
return datetime.now(timezone.utc).isoformat()
def start_trace(name: str, **meta: Any) -> str:
global _current_trace
trace_id = f"trace-{uuid.uuid4().hex[:12]}"
_current_trace = trace_id
_append({"type": "trace_start", "trace_id": trace_id, "name": name, "ts": _now(), **meta})
return trace_id
def _append(entry: dict[str, Any]) -> None:
MANIFESTS.mkdir(parents=True, exist_ok=True)
if not TRACE_LOG.is_file():
TRACE_LOG.write_text("", encoding="utf-8")
with TRACE_LOG.open("a", encoding="utf-8") as f:
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
@contextmanager
def trace_span(span_type: str, **fields: Any) -> Iterator[None]:
span_id = f"span-{uuid.uuid4().hex[:8]}"
_append({"type": span_type, "span_id": span_id, "trace_id": _current_trace, "ts": _now(), **fields})
try:
yield
finally:
_append({"type": f"{span_type}_end", "span_id": span_id, "trace_id": _current_trace, "ts": _now()})
def get_trace(trace_id: str) -> list[dict[str, Any]]:
if not TRACE_LOG.is_file():
return []
return [json.loads(l) for l in TRACE_LOG.read_text().strip().splitlines() if l.strip() and trace_id in l]
def list_traces(limit: int = 50) -> list[str]:
if not TRACE_LOG.is_file():
return []
ids = []
for line in TRACE_LOG.read_text().strip().splitlines():
try:
o = json.loads(line)
if o.get("type") == "trace_start" and o.get("trace_id"):
ids.append(o["trace_id"])
except json.JSONDecodeError:
pass
return list(reversed(ids[-limit:]))