.. _stdlib_logger: ============================ Structured JSON Lines logger ============================ .. das:module:: logger The logger module provides a structured, file-backed logging facility for daslang tools (MCP server, daslang-live, dastest, etc). Records are written as one JSON object per line ("JSON Lines" / ``ndjson``) to ``{get_das_root()}/logs/.log``, with an ISO 8601 UTC timestamp (millisecond precision), level name, dotted category, message, and optional ``fields`` object. The default level is ``LOG_INFO``; per-category overrides apply by dotted prefix (an override on ``"mcp.live"`` covers ``"mcp.live"``, ``"mcp.live.foo"``, and so on). :func:`logger_install_hook` registers a process-wide debug agent that diverts ``print`` and ``to_log`` into the log file — essential for stdio-transport processes (MCP server, language servers) where any stdout write corrupts the wire format. All functions and symbols are in "logger" module, use require to get access to it. .. code-block:: das require daslib/logger +++++ Setup +++++ * :ref:`logger_get_name () : string ` * :ref:`logger_get_path () : string ` * :ref:`logger_init (name: string) ` * :ref:`logger_set_name (name: string) ` * :ref:`logger_set_path (path: string) ` .. _function-logger_logger_get_name: .. das:function:: logger_get_name() : string Returns the logical name passed to :func:`logger_set_name` (empty if the path was set directly via :func:`logger_set_path`). .. _function-logger_logger_get_path: .. das:function:: logger_get_path() : string Returns the currently configured log file path (empty if unset). .. _function-logger_logger_init_string: .. das:function:: logger_init(name: string) Convenience: ``logger_set_name(name)`` + ``logger_install_hook()``. The common-case one-liner for tools that want both behaviors. :Arguments: * **name** : string .. _function-logger_logger_set_name_string: .. das:function:: logger_set_name(name: string) Configure the log file as ``{get_das_root()}/logs/.log``. Re-opens if the path changes; closes the previous handle. Each Context tracks its own state — call once per context. :Arguments: * **name** : string .. _function-logger_logger_set_path_string: .. das:function:: logger_set_path(path: string) Override the log file path explicitly. Pass an absolute path or a path relative to the current working directory. :Arguments: * **path** : string +++++++++++++ Level filters +++++++++++++ * :ref:`logger_clear_category_levels () ` * :ref:`logger_get_min_level () : int ` * :ref:`logger_set_category_level (category: string; level: int) ` * :ref:`logger_set_min_level (level: int) ` .. _function-logger_logger_clear_category_levels: .. das:function:: logger_clear_category_levels() Remove all per-category overrides. .. _function-logger_logger_get_min_level: .. das:function:: logger_get_min_level() : int Returns the currently configured global minimum level. .. _function-logger_logger_set_category_level_string_int: .. das:function:: logger_set_category_level(category: string; level: int) Override the level filter for one category. Dotted prefix matching: an override on ``"mcp.live"`` applies to ``"mcp.live"``, ``"mcp.live.foo"``, ``"mcp.live.bar"`` (unless they have their own more specific override). :Arguments: * **category** : string * **level** : int .. _function-logger_logger_set_min_level_int: .. das:function:: logger_set_min_level(level: int) Global minimum level. Records below this are dropped before formatting. Default ``LOG_INFO``. :Arguments: * **level** : int ++++++++++++++ Output control ++++++++++++++ * :ref:`logger_close () ` * :ref:`logger_flush () ` * :ref:`logger_set_stderr_fallback (enabled: bool) ` .. _function-logger_logger_close: .. das:function:: logger_close() Close the log file. Subsequent writes will lazy-reopen. .. _function-logger_logger_flush: .. das:function:: logger_flush() Explicit flush. Each write already flushes; only useful if you disable auto-flush in a fork. .. _function-logger_logger_set_stderr_fallback_bool: .. das:function:: logger_set_stderr_fallback(enabled: bool) Enable / disable writing to stderr when the log file can't be opened. Defaults to true; set to false for strict stdio-transport servers that must NEVER write to either stream on file failure. :Arguments: * **enabled** : bool +++++++++ Log calls +++++++++ * :ref:`logger_critical (category: string; message: string; fields: JsonValue? = null) ` * :ref:`logger_debug (category: string; message: string; fields: JsonValue? = null) ` * :ref:`logger_error (category: string; message: string; fields: JsonValue? = null) ` * :ref:`logger_info (category: string; message: string; fields: JsonValue? = null) ` * :ref:`logger_log (level: int; category: string; message: string; fields: JsonValue? = null) ` * :ref:`logger_trace (category: string; message: string; fields: JsonValue? = null) ` * :ref:`logger_warning (category: string; message: string; fields: JsonValue? = null) ` .. _function-logger_logger_critical_string_string_JsonValue_q_: .. das:function:: logger_critical(category: string; message: string; fields: JsonValue? = null) Critical / fatal record. ``LOG_CRITICAL``. :Arguments: * **category** : string * **message** : string * **fields** : :ref:`JsonValue `? .. _function-logger_logger_debug_string_string_JsonValue_q_: .. das:function:: logger_debug(category: string; message: string; fields: JsonValue? = null) Debug-level record. ``LOG_DEBUG``. :Arguments: * **category** : string * **message** : string * **fields** : :ref:`JsonValue `? .. _function-logger_logger_error_string_string_JsonValue_q_: .. das:function:: logger_error(category: string; message: string; fields: JsonValue? = null) Error record. ``LOG_ERROR``. :Arguments: * **category** : string * **message** : string * **fields** : :ref:`JsonValue `? .. _function-logger_logger_info_string_string_JsonValue_q_: .. das:function:: logger_info(category: string; message: string; fields: JsonValue? = null) Informational record. ``LOG_INFO`` — the default level. :Arguments: * **category** : string * **message** : string * **fields** : :ref:`JsonValue `? .. _function-logger_logger_log_int_string_string_JsonValue_q_: .. das:function:: logger_log(level: int; category: string; message: string; fields: JsonValue? = null) Generic log entry. Prefer the named-level helpers below. :Arguments: * **level** : int * **category** : string * **message** : string * **fields** : :ref:`JsonValue `? .. _function-logger_logger_trace_string_string_JsonValue_q_: .. das:function:: logger_trace(category: string; message: string; fields: JsonValue? = null) Verbose trace-level record. ``LOG_TRACE``. :Arguments: * **category** : string * **message** : string * **fields** : :ref:`JsonValue `? .. _function-logger_logger_warning_string_string_JsonValue_q_: .. das:function:: logger_warning(category: string; message: string; fields: JsonValue? = null) Warning record. ``LOG_WARNING``. :Arguments: * **category** : string * **message** : string * **fields** : :ref:`JsonValue `? +++++++++++ Stdout hook +++++++++++ * :ref:`logger_install_hook () ` .. _function-logger_logger_install_hook: .. das:function:: logger_install_hook() Install a global debug agent that diverts ``print`` and ``to_log`` (from any Context, current or future) into the configured log file. Idempotent — safe to call from every module's [init], from MCP main, etc. Worker threads spawned via ``new_thread`` inherit the hook automatically; no per-context re-install needed.