feat: add more logging

This commit is contained in:
h
2026-05-22 22:45:44 +02:00
parent 21dc26810b
commit d05c8dd613
3 changed files with 321 additions and 13 deletions
+83 -2
View File
@@ -19,6 +19,7 @@ from __future__ import annotations
import asyncio
import contextlib
import json
import logging
import os
import tempfile
import uuid
@@ -27,6 +28,8 @@ from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Literal, Self
_log = logging.getLogger("claude_code_api.backend")
from claude_code_api.errors import MessageParseError
from claude_code_api.events import (
AssistantMessage,
@@ -171,31 +174,84 @@ class ClaudeCodeBackend:
async with self._lock:
prior = list(messages[:-1])
fp_prior = hash_history(prior)
_log.info(
"complete: n_msgs=%d prior_fp=%s last_text_len=%d pool_size=%d",
len(messages),
fp_prior[:12],
len(last_text),
len(self._sessions),
)
session: _LiveSession
if prior and fp_prior in self._sessions:
session = self._sessions.pop(fp_prior)
send_text = last_text
_log.info(
"complete: POOL HIT fp=%s -> reusing session_id=%s",
fp_prior[:12],
session.session_id,
)
else:
_log.info(
"complete: POOL MISS fp=%s (prior=%d msgs) -> spawning new session",
fp_prior[:12],
len(prior),
)
session = await self._create_session(prior)
if prior and self._opts.history_injection_mode == "concat_message":
send_text = build_concat_prompt(prior, last_text)
_log.info(
"complete: concat_message mode, send_text_len=%d",
len(send_text),
)
else:
send_text = last_text
events: list[Event] = []
n_assistant = 0
n_user = 0
n_system = 0
try:
_log.info(
"complete: sending user msg to session_id=%s (text_len=%d)",
session.session_id,
len(send_text),
)
async for event in session.tm.send_user_message(send_text):
events.append(event)
if isinstance(event, AssistantMessage):
n_assistant += 1
elif isinstance(event, UserMessage):
n_user += 1
else:
n_system += 1
yield event
except BaseException:
except BaseException as exc:
_log.exception(
"complete: session_id=%s FAILED (events so far: a=%d u=%d sys=%d): %s",
session.session_id,
n_assistant,
n_user,
n_system,
exc,
)
with contextlib.suppress(Exception):
await session.aclose()
raise
synthesized_cycle = synthesize_turn_messages(events)
new_history = [*list(messages), *synthesized_cycle]
self._sessions[hash_history(new_history)] = session
new_fp = hash_history(new_history)
self._sessions[new_fp] = session
_log.info(
"complete: session_id=%s DONE a=%d u=%d sys=%d synth=%d -> repooled under fp=%s",
session.session_id,
n_assistant,
n_user,
n_system,
len(synthesized_cycle),
new_fp[:12],
)
async def aclose(self) -> None:
"""Shut down all live sessions; remove the temp mcp-config file."""
@@ -237,10 +293,24 @@ class ClaudeCodeBackend:
jsonl_path.write_text(seed, encoding="utf-8")
start_offset = jsonl_path.stat().st_size
resume = True
_log.info(
"_create_session: session_id=%s SEED jsonl=%s bytes=%d history_msgs=%d resume=True",
session_id,
jsonl_path,
start_offset,
len(history),
)
else:
jsonl_path = resolve_jsonl_path(cwd, session_id)
start_offset = 0
resume = False
_log.info(
"_create_session: session_id=%s FRESH jsonl=%s history_msgs=%d resume=False mode=%s",
session_id,
jsonl_path,
len(history),
self._opts.history_injection_mode,
)
if self._session_factory is not None:
result = self._session_factory(
@@ -260,6 +330,12 @@ class ClaudeCodeBackend:
async def _spawn_real_session(
self, *, session_id: str, resume: bool, jsonl_path: Path, start_offset: int
) -> _LiveSession:
_log.info(
"_spawn_real_session: session_id=%s resume=%s start_offset=%d",
session_id,
resume,
start_offset,
)
pty_opts = self._build_pty_options(session_id=session_id, resume=resume)
pty = PtyClaudeProcess(pty_opts)
watcher = JsonlWatcher(jsonl_path, start_offset=start_offset)
@@ -274,6 +350,11 @@ class ClaudeCodeBackend:
on_parse_error=self._on_parse_error,
)
await tm.start()
_log.info(
"_spawn_real_session: session_id=%s STARTED pid=%s",
session_id,
getattr(pty, "pid", "?"),
)
return _LiveSession(pty=pty, watcher=watcher, tm=tm)
def _build_pty_options(self, *, session_id: str, resume: bool) -> PtyProcessOptions: