mirror of
https://github.com/usestrix/strix.git
synced 2026-08-23 11:22:37 +02:00
feat(logging): per-scan `{run_dir}/strix.log` with scan/agent context tagging
Every scan now writes a complete log file at ``{run_dir}/strix.log``
captured from the moment ``run_dir`` is resolved through teardown.
Stdlib ``logging`` only — no parallel framework.
New ``strix/telemetry/logging.py``:
* ``setup_scan_logging(run_dir, debug=)`` attaches a ``FileHandler``
(DEBUG, all ``strix.*``) plus a ``StreamHandler`` (ERROR by
default; DEBUG via ``STRIX_DEBUG=1``).
* ``ContextVar``-backed ``scan_id`` and ``agent_id`` injected by a
``Filter`` so every line is auto-tagged across asyncio tasks
without callers passing them explicitly.
* Third-party noise (``httpx``, ``litellm``, ``openai``,
``anthropic``, ``urllib3``, ``httpcore``) capped at WARNING.
* Returns a teardown handle for ``finally`` cleanup.
Wiring:
* ``orchestration/scan.py`` calls ``setup_scan_logging`` once per
scan after ``run_dir`` resolves; sets scan_id; tears down in
``finally``. Adds INFO logs for sandbox bring-up + scan
start/end.
* ``orchestration/hooks.py`` sets/clears ``agent_id`` ContextVar in
``on_agent_start`` / ``on_agent_end`` and emits INFO for agent
lifecycle, DEBUG for every tool start/end and LLM call.
* ``interface/main.py`` drops the ``setLevel(ERROR)`` silencer.
Coverage expanded across ~20 files (orchestration, agents, runtime,
llm, tools, interface, config, skills) with INFO for lifecycle and
DEBUG for verbose detail. Per the system instructions in
``logger.warning(f"…{e}")`` were converted to module logger calls.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
9d7f754b59
commit
46ff025209
@@ -35,6 +35,7 @@ from strix.orchestration.filter import inject_messages_filter
|
||||
from strix.orchestration.hooks import StrixOrchestrationHooks
|
||||
from strix.orchestration.run_loop import run_with_continuation
|
||||
from strix.runtime import session_manager
|
||||
from strix.telemetry.logging import set_scan_id, setup_scan_logging
|
||||
|
||||
|
||||
#: Default ``max_turns`` budget passed to ``Runner.run``.
|
||||
@@ -199,13 +200,32 @@ async def run_strix_scan(
|
||||
"""
|
||||
if scan_id is None:
|
||||
scan_id = f"scan-{uuid.uuid4().hex[:8]}"
|
||||
logger.info("Starting Strix scan %s", scan_id)
|
||||
|
||||
# Resolve run_dir before any heavy bring-up so the log file captures
|
||||
# everything from sandbox start onwards. Tracer (if present) owns the
|
||||
# canonical path; otherwise fall back to ``./strix_runs/<scan_id>``.
|
||||
run_dir = (
|
||||
tracer.get_run_dir()
|
||||
if tracer is not None and hasattr(tracer, "get_run_dir")
|
||||
else Path.cwd() / "strix_runs" / scan_id
|
||||
)
|
||||
teardown_logging = setup_scan_logging(run_dir)
|
||||
set_scan_id(scan_id)
|
||||
logger.info(
|
||||
"Starting Strix scan %s (image=%s, max_turns=%d, interactive=%s, run_dir=%s)",
|
||||
scan_id,
|
||||
image,
|
||||
max_turns,
|
||||
interactive,
|
||||
run_dir,
|
||||
)
|
||||
|
||||
resolved_model = model or load_settings().llm.model
|
||||
if not resolved_model:
|
||||
raise RuntimeError(
|
||||
"No LLM model configured. Set STRIX_LLM env or pass model= to run_strix_scan().",
|
||||
)
|
||||
logger.info("LLM model resolved: %s", resolved_model)
|
||||
|
||||
# Caller may pre-create the bus so it can hold a handle (e.g., the
|
||||
# TUI uses it to route stop / chat-input commands). Otherwise we
|
||||
@@ -213,12 +233,14 @@ async def run_strix_scan(
|
||||
if bus is None:
|
||||
bus = AgentMessageBus()
|
||||
root_id = uuid.uuid4().hex[:8]
|
||||
logger.info("Bringing up sandbox session for scan %s", scan_id)
|
||||
|
||||
bundle = await session_manager.create_or_reuse(
|
||||
scan_id,
|
||||
image=image,
|
||||
sources_path=sources_path,
|
||||
)
|
||||
logger.info("Sandbox ready for scan %s", scan_id)
|
||||
|
||||
try:
|
||||
# Lazy: ``strix.interface`` pulls cli→tui→scan which would cycle.
|
||||
@@ -316,10 +338,14 @@ async def run_strix_scan(
|
||||
session=session,
|
||||
)
|
||||
except BaseException:
|
||||
logger.exception("Strix scan %s failed", scan_id)
|
||||
# Cancel any descendant tasks the root spawned before unwinding.
|
||||
# cancel_descendants is idempotent and handles the empty-tree case.
|
||||
await bus.cancel_descendants(root_id)
|
||||
raise
|
||||
finally:
|
||||
if cleanup_on_exit:
|
||||
logger.info("Tearing down sandbox session for scan %s", scan_id)
|
||||
await session_manager.cleanup(scan_id)
|
||||
logger.info("Strix scan %s done", scan_id)
|
||||
teardown_logging()
|
||||
|
||||
Reference in New Issue
Block a user