Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

289 lines
8.7 KiB
Markdown

# Logging
This document defines the current logging conventions for `tutti`.
The repository-owned default values for log file names and rotation budgets now live in:
- `config/tutti.defaults.json`
Go and desktop code should consume generated defaults from that source instead of carrying duplicate literal values.
## Purpose
`tuttid` is a long-running local daemon.
Its normal operational logs should be durable and reviewable even when the desktop shell is the process supervisor.
`apps/desktop` main process should also keep a durable local log for Electron-shell concerns.
## `tuttid` Default Behavior
`tuttid` defaults to file-based logging.
Current default:
- log output mode: `file`
- log path: `<state-dir>/logs/tuttid.log`
- log format: structured `slog` text output
- default level: `info`
- active file name stays stable for tailing
- rotated history uses date-indexed names such as `tuttid.2026-05-21.log`
This means normal development and product runs should treat the daemon log file as the primary source for runtime analysis.
## Desktop Main Logging
Desktop main-process logging also defaults to file output.
Current default:
- log output mode: `file`
- log path: `<state-dir>/logs/tutti-desktop.log`
- default level: `info`
- active file name stays stable for tailing
- rotated history uses date-indexed names such as `tutti-desktop.2026-05-21.log`
Desktop logging is intended for:
- app bootstrap failures
- daemon supervision events
- shell-level errors
- Electron lifecycle issues
It is not a replacement for `tuttid` business and runtime logs.
## Correlation Fields
Desktop and daemon logs should be easy to align during one local run.
Current shared correlation behavior:
- desktop generates or adopts `TUTTI_SESSION_ID` at startup
- when desktop manages `tuttid`, it passes the same `TUTTI_SESSION_ID` into the daemon process
- both `tutti-desktop.log` and `tuttid.log` now include `session_id` in each structured line when available
This is intentionally lightweight:
- it is not a distributed tracing system
- it is a stable per-launch correlation key for local debugging and log analysis
## Desktop Diagnostic Exports
Desktop diagnostic exports use an explicit time range and an explicit Session
record choice. The supported combinations are:
- the last 10 minutes of logs
- the last 10 minutes of logs plus Agent Session records
- the last 3 days of logs
- the last 3 days of logs plus Agent Session records
The selected time range applies to structured log timestamps, file modification
time when a source has no parseable timestamps, and Agent Session update time.
Choosing logs only must not query or write Agent Session records. Runtime context,
the export summary, and other non-Session diagnostic snapshots remain part of the
log bundle so exported evidence stays interpretable.
Runtime-context transport diagnostics are allowlisted. Exports may include the
bound/requested address and listener/PID paths, but must never serialize the
transport access token or newly added transport snapshot fields by default.
## Error Codes
Startup, transport, and supervision failures should carry a stable `error_code` in addition to the human-readable message.
Current desktop-focused codes include:
- `logger_file_unavailable`
- `daemon_unavailable`
- `transport_timeout`
- `transport_connect_failed`
- `transport_request_failed`
- `managed_process_stderr`
- `managed_process_exited`
- `workspace_not_found`
Current daemon runtime codes include:
- `server_serve_failed`
- `server_shutdown_failed`
Protocol-layer codes belong to daemon API contracts rather than desktop-local runtime diagnostics.
Examples:
- `workspace_not_found`
- `workspace_path_exists`
- `workspace_operation_failed`
- `invalid_request`
- `service_unavailable`
- `method_not_allowed`
Rules:
- prefer a stable machine-readable code over parsing log messages later
- keep the code small and responsibility-oriented
- let the message continue to carry specific context for humans
- keep protocol-facing codes separate from desktop-local supervision codes such as `managed_process_exited`
## Output Modes
`tuttid` currently supports:
- `TUTTID_LOG_OUTPUT=file`
- `TUTTID_LOG_OUTPUT=stdout`
- `TUTTID_LOG_OUTPUT=tee`
Desktop main currently supports:
- `TUTTI_DESKTOP_LOG_OUTPUT=file`
- `TUTTI_DESKTOP_LOG_OUTPUT=stdout`
- `TUTTI_DESKTOP_LOG_OUTPUT=tee`
Rules:
- `file` writes only to the daemon log file
- `stdout` writes only to standard output
- `tee` writes to both the daemon log file and standard output
Default:
- `TUTTID_LOG_OUTPUT` unset behaves as `file`
## Log Levels
`tuttid` supports:
- `TUTTID_LOG_LEVEL=debug`
- `TUTTID_LOG_LEVEL=info`
- `TUTTID_LOG_LEVEL=warn`
- `TUTTID_LOG_LEVEL=error`
Default:
- `TUTTID_LOG_LEVEL` unset behaves as `info`
Desktop main supports:
- `TUTTI_DESKTOP_LOG_LEVEL=debug`
- `TUTTI_DESKTOP_LOG_LEVEL=info`
- `TUTTI_DESKTOP_LOG_LEVEL=warn`
- `TUTTI_DESKTOP_LOG_LEVEL=error`
Default:
- `TUTTI_DESKTOP_LOG_LEVEL` unset behaves as `info`
### Hot-Path Diagnostics
Streaming events, polling loops, renderer snapshots, and transport frames are
hot paths. Their successful per-event diagnostics belong at `debug`; the
default `info` level should contain a bounded summary per turn, short time
window, or semantic state transition.
Rules:
- aggregate repeated success events and retain counts plus stable correlation
fields in the summary
- keep failures, dropped data, and rare lifecycle transitions visible at
`warn` or `error`
- exclude cursors, timestamps, token/message versions, and elapsed time from
change-detection signatures unless that value is the state being diagnosed
- log a periodic poll at `info` or `warn` only when its semantic result changes;
unchanged results belong at `debug`
- desktop file writes must stay ordered without performing one synchronous
filesystem write on the Electron main thread per line
## Rotation
Both daemon and desktop main now follow the same rotation convention:
- active file keeps a stable name
- rotation happens on calendar day change or when size budget is exceeded
- rotated files are date-indexed and optionally numbered for same-day rollover
Shared rotation controls:
- `TUTTI_LOG_DIR`
- `TUTTI_LOG_MAX_SIZE_MB`
- `TUTTI_LOG_MAX_BACKUPS`
- `TUTTI_LOG_MAX_AGE_DAYS`
- `TUTTI_LOG_MAX_TOTAL_MB`
Default budgets:
- max size: `50MB`
- max backups: `10`
- max age: `14 days`
- max total managed log directory size: `300MB`
## Desktop Supervision Rules
When desktop manages `tuttid`:
- daemon logs still default to file output
- desktop does not forward daemon stdout by default
- desktop still surfaces daemon stderr for startup and failure visibility
This keeps normal daemon logs in the file while still allowing focused debugging when stdout is explicitly requested.
Desktop-side debug options:
- set `TUTTID_LOG_OUTPUT=stdout` or `tee`
- or set `TUTTID_FORWARD_STDIO=1` when you want desktop to forward daemon stdout explicitly
- set `TUTTI_DESKTOP_LOG_OUTPUT=stdout` or `tee` when you want desktop shell logs on standard output
These environment variables are override and diagnostics controls, not the primary source of default logging policy.
## Allowed Override Surface
Current supported logging override surface:
- `TUTTI_LOG_DIR`
- `TUTTI_LOG_MAX_SIZE_MB`
- `TUTTI_LOG_MAX_BACKUPS`
- `TUTTI_LOG_MAX_AGE_DAYS`
- `TUTTI_LOG_MAX_TOTAL_MB`
- `TUTTID_LOG_PATH`
- `TUTTID_LOG_OUTPUT`
- `TUTTID_LOG_LEVEL`
- `TUTTI_DESKTOP_LOG_PATH`
- `TUTTI_DESKTOP_LOG_OUTPUT`
- `TUTTI_DESKTOP_LOG_LEVEL`
- `TUTTID_FORWARD_STDIO`
- `TUTTI_SESSION_ID`
Rules:
- these variables exist for local debugging, tests, packaging, and diagnostics
- do not introduce a new logging environment variable unless existing shared defaults or existing override hooks are insufficient
- prefer shared controls such as `TUTTI_LOG_DIR` and the rotation budget variables over component-specific one-off flags
- if a new logging override is added, update this document and `config/tutti.defaults.json` if the change also affects the repository-owned defaults
## Failure Visibility
Fatal startup failures should still be visible through `stderr`.
Examples:
- invalid log configuration
- logger file open failure
- listener startup failure
- fatal daemon exit
This avoids a failure mode where the daemon dies before usable file logging is available.
## Current Recommendation
Use:
- `file` for normal product runs and joint development analysis
- `tee` when debugging startup, transport, or daemon behavior while still preserving a durable file log
- `stdout` only for narrow, deliberate debugging flows
Use the same rule for desktop shell logs unless a local debugging task specifically benefits from terminal output.
## Related Docs
- [Local State Storage](./local-state-storage.md)
- [Desktop Layering](./desktop-layering.md)