# Logging

Lumi stores core, plugin, integration, command, and administrator activity in the shared SQLite `logs` table. Administrators review it at **Admin → Logs**. The page supports severity, component, activity type, range, full server-side search, and entry-count filters. New matching entries arrive through Lumi's authenticated event stream without a page refresh.

Each entry may include:

- `level`: `debug`, `info`, `warn`, or `error`.
- `source`: the component that produced the entry, such as `core:web`, `core:commands`, `platform:twitch`, or `plugin:lumi_ai`.
- `category`: a broad activity type such as `lifecycle`, `audit`, `http`, `command`, `integration`, `security`, or `plugin`.
- `event`: a stable machine-readable event name.
- `request_id`: the matching HTTP or diagnostic request identifier when available.
- A short message and optional structured details.

## Writing logs

Existing `log(level, message, details)` calls remain supported. New core services should use a scoped logger:

```js
const { createLogger } = require("./logger");
const logger = createLogger("core:example", { category: "integration" });

logger.info("Example connected", { endpoint: "primary" }, { event: "example_ready" });
logger.error("Example request failed", error, { event: "example_failed" });
```

Every loaded plugin receives a logger scoped to `plugin:<plugin-id>` in its `init` context:

```js
init({ logger }) {
  logger.info("Plugin feature ready", { mode: "automatic" }, { event: "feature_ready" });
}
```

Use `debug` for high-volume successful activity, `info` for meaningful state changes, `warn` for degraded or rejected work, and `error` for failed work that needs attention. Do not log full chat messages, request bodies, credentials, session data, third-party response bodies, or user access tokens.

The shared logger recursively redacts credential-shaped object keys, authorization headers, and common secret query parameters before storage. Redaction is a final safety boundary, not permission to pass known secrets to the logger. Messages and details are length-bounded so a malformed response cannot grow the database without limit.

## Administrator actions and requests

Mutating WebUI requests produce an `audit` entry with method, matched route, result status, duration, role, user ID, and a request ID. Failed and unusually slow requests are recorded as `http` warnings or errors. Query strings and submitted bodies are not included. Webhook, platform, diagnostics, plugin lifecycle, command failure, startup, and shutdown paths use dedicated sources and events.

## Retention and downloads

By default Lumi retains logs for 30 days and keeps at most 100,000 entries. Administrators can change both limits under **Log storage** on the logs page. Cleanup runs at startup and immediately after retention settings are saved. It only removes rows from the shared logs table.

Filtered downloads are available as readable text or JSON Lines. JSON Lines preserves all structured fields for external diagnostics without changing Lumi's database.
