63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
|
|
"""LangSmith 式 trace:manifests/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:]))
|