---
name: logging
description: How to log in the y5 compositor. Use whenever you add, change, or migrate logging — any time you'd reach for a log/print statement, "add a log", debug output, `tracing::*!`, `println!`, or a fatal `panic!` with a message. y5 has its own tracing-free structured logging; this skill is the source of truth for using it.
---

# y5 logging

y5 has its **own** structured logging system. **Never use `tracing`, `log`, or `println!`/
`eprintln!` for diagnostics in compositor code.** Use the macros from
`compositor_model_debug_instance_record`. Full reference: that crate's module docs
(`compositor.model/model.debug/debug.instance/instance.record`).

## The rule

- Levels: `error!`, `warn!`, `info!`, `trace!` — same `format!` args as `tracing`.
- Fatal: `abort!("msg {x}")` — logs at Error **and** panics (synchronously flushed first).
- No `tracing` / `log` / `tracing-subscriber` deps in new/changed crates. If a crate you touch
  still imports them only for logging, migrate the call sites and drop the deps.

## Wiring a crate to log (one-time per crate)

The `add-crate` template already inserts this. If a crate lacks it, add to its **`lib.rs`**
(after any leading `#![...]` inner attributes):

```rust
#[macro_use]
extern crate compositor_model_debug_instance_record;
```

and ensure its `Cargo.toml` has (it resolves via the workspace links — run `compositor.workspace/link.all.sh` if
you just added the dep to a workspace that didn't have it):

```toml
compositor_model_debug_instance_record = { workspace = true }
```

Then call the macros from any module in the crate — no per-module `use` needed. The crate name
and function path are attached automatically as filter tags.

## Migrating `tracing`

`tracing::info!(...)` → `info!(...)` (likewise `error!`/`warn!`/`trace!`). Confirm the two
`lib.rs` lines above exist, then remove `tracing` + `tracing-subscriber` from the crate's
`Cargo.toml`. Grep the crate for `tracing::` to be sure none remain.

## Levels: two independent controls

- **Compile-time**: cargo features `error/warn/info/trace` on the record crate (set by the
  top-level `execute` dep). A disabled level compiles to nothing. `abort!` is never stripped.
- **Runtime**: `COMPOSITOR_LOG_LEVEL` (e.g. `info,warn,error,trace`) selects what is emitted
  among compiled-in levels.

## Viewing logs

Records stream over gRPC (`/tmp/y5-compositor-logs.sock`) to the **`compositor.developer/developer.tool`**
Tauri viewer (filter by crate/function/level, timeline, presets, dumps). Run the compositor with
`COMPOSITOR_LOG_LEVEL` set, then `cd compositor.developer/developer.tool/developer.tool.window/logs && npm run tauri dev`. They also
print dmesg-style to the compositor's stderr.

## Do NOT

- Do not add `tracing`/`log` to `Cargo.toml`.
- Do not `println!`/`eprintln!` for diagnostics (use `info!`/`trace!`).
- Do not `panic!("msg")` for a logged fatal — use `abort!("msg")`.
- Do not hand-write a per-crate logger — `instance!()` is the only mechanism.
