Snodo.Logging (snodo v0.4.3)

Copy Markdown View Source

Log messages from a request handler to the client, as notifications/message.

:ok = Snodo.Logging.log(context, :info, "Import started", logger: "importer")
:ok = Snodo.Logging.log(context, :debug, %{"rows" => 120})

The server opts in by advertising the "logging" capability. Which messages reach the client then depends on the protocol revision:

  • 2026-07-28: the client sets io.modelcontextprotocol/logLevel in a request's _meta. Messages below that level are dropped, and a request without a level gets no messages at all.
  • 2025-11-25 and 2025-06-18: the client sets a level with logging/setLevel. Over stdio that level holds for the connection. Over HTTP these dialects keep no session, so a request uses the runtime's :log_level (default :info), which the older specifications allow when the client has not set one.

log/4 returns :ok both when the message was written and when it was dropped on purpose (no "logging" capability, below the level, no level, or no channel for notifications), so a handler can match :ok. It returns {:error, reason} for invalid input (:invalid_level, :invalid_data, :invalid_logger, :too_large) or when the request can no longer take messages (:closed, :cancelled, :limit_reached, :timeout, :wrong_process).

Messages share the request's notification channel with progress notifications: they are written before the request's result, one at a time, each acknowledged after the transport writes it. A request may send at most 1,000 messages, each with at most 16 KiB of encoded data. Only the process that runs the request may log; Snodo.Component.Wrap.Timeout hands that right to its task.

Summary

Functions

The levels, from least to most severe (RFC 5424 severities).

Sends data at level for the request in context.

Types

level()

@type level() ::
  :debug | :info | :notice | :warning | :error | :critical | :alert | :emergency

t()

@opaque t()

Functions

levels()

@spec levels() :: [level()]

The levels, from least to most severe (RFC 5424 severities).

log(context, level, data, opts \\ [])

@spec log(Snodo.Context.t(), level(), term(), keyword()) :: :ok | {:error, atom()}

Sends data at level for the request in context.

data is any JSON value. opts takes :logger, a string naming the source of the message.