The session_logging.py module#

Summary#

register_log_root

Register an extra logger root for the session file handler.

init_session_logging

Set up a session log folder and attach a file handler.

get_session_log_dir

Return the active session log directory, if any.

get_latest_log_path

Return the path to /latest.log if it exists.

get_latest_session_dir

Return the path from /latest_session.txt, if present.

shutdown_session_logging

Detach and close the session file handler.

Description#

Per-session debug logging for CFX-MCP.

When the gateway (or any long-running entry point) starts, this module creates a per-session folder and attaches a DEBUG-level file handler to this package’s root logger (ansys.cfx.mcp). An optional higher-level layer that shares the process can add its own root via register_log_root() so a single session.log captures the whole stack — this package never names or imports that layer. All child loggers propagate up to the handler, so tool calls, plan executions, run_code snippets, LLM round-trips, and validator decisions are all captured in one place without touching individual call sites.

Goals#

  • Self-service diagnostics — when a user reports a problem we can ask them to attach the session folder and have the full picture (logs, recorded tool args, last run_code snippets via the existing RunLogger, environment snapshot).

  • Off by default for embedded use — the library import path stays silent. The handler is only attached when an entry point explicitly calls init_session_logging() (the gateway and the CLI both do).

  • Easy to disable — setting FLUIDS_MCP_DISABLE_SESSION_LOGS=1 short-circuits the call. Safe in regulated environments where local log files must not be created.

Layout#

Default base directory:

  • Windows: %APPDATA%\\Ansys\\v271\\cfx\\aisol

  • macOS / Linux: ~/.ansys/v271/cfx/aisol

Override with FLUIDS_MCP_SESSION_LOG_DIR= (the path is used verbatim — sessions still get their own subfolders inside it).

Each session creates // containing:

  • session.log — DEBUG-level text log of every

    ansys.cfx.mcp.* module (plus any extra roots registered via register_log_root()) through Python’s logging.

  • env.txt — snapshot of process env vars relevant to the server

    (FLUIDS_*, ANSYS_*, AWP_ROOT*, AALI_*, LLM_*) plus Python/OS versions.

  • meta.json — small JSON file with session id, start time, log

    base, gateway host/port (if known).

The agent.loop.run_log.RunLogger continues to write per-conversation JSONL files under /runs/ exactly as before — the new session folder is for cross-cutting diagnostics, not per-conversation event streams.

Module detail#

session_logging.register_log_root(name: str) None#

Register an extra logger root for the session file handler.

Inversion-of-control hook: a higher-level layer running in the same process (e.g. an agent product with its own top-level package logger) calls this at import time to have its records captured in the same session.log — without this package ever importing or naming that layer. Idempotent. If a session handler is already attached, the new root is wired up immediately so registration order does not matter.

Parameters:
namestr

Name of the object, module, or setting being processed.

Returns:
None

The function completes through its side effects.

session_logging.init_session_logging(*, session_id: str | None = None, extra_meta: dict[str, object] | None = None) pathlib.Path | None#

Set up a session log folder and attach a file handler.

Returns the resolved session directory, or None when disabled via ENV_DISABLE. Safe to call multiple times — subsequent calls return the existing directory without re-attaching handlers.

Parameters:
session_idOptional[str]

Session id supplied to the function.

extra_metaOptional[dict[str, object]]

Extra meta supplied to the function.

Returns:
Optional[Path]

Result produced by the function.

session_logging.get_session_log_dir() pathlib.Path | None#

Return the active session log directory, if any.

Returns:
Optional[Path]

Result produced by the function.

session_logging.get_latest_log_path() pathlib.Path | None#

Return the path to /latest.log if it exists.

This is the stable pointer the user can Get-Content / tail without needing to know the session id. Returns None if session logging has never run on this machine.

Returns:
Optional[Path]

Result produced by the function.

session_logging.get_latest_session_dir() pathlib.Path | None#

Return the path from /latest_session.txt, if present.

Use this from a separate process (e.g. a CLI command) to find the most recent serve session directory without scanning timestamps.

Returns:
Optional[Path]

Result produced by the function.

session_logging.shutdown_session_logging() None#

Detach and close the session file handler.

Used by tests; in production the handler outlives the process by design.

Returns:
None

The function completes through its side effects.

session_logging.ENV_ENABLE = 'FLUIDS_MCP_SESSION_LOGS'#
session_logging.ENV_DISABLE = 'FLUIDS_MCP_DISABLE_SESSION_LOGS'#
session_logging.ENV_BASE_DIR = 'FLUIDS_MCP_SESSION_LOG_DIR'#
session_logging.ENV_LEVEL = 'FLUIDS_MCP_SESSION_LOG_LEVEL'#