Ashiedu's picture
Sync unified workbench
0490201 verified
# T-011: `tracing` Log Infrastructure β€” Subscriber Init, RUST_LOG Filter, Rerun Sink Feature Flag
**Type:** Task
**Phase:** 0 β€” Foundation
**Autonomy:** `agent:autonomous` β€” Mechanical wiring, no decisions required.
**Stack:** `stack:rust`
**Version:** v0.1
**Iteration:** iter-1
**Effort:** XS (1 hour)
---
> ⚠️ **Agent Scope:** T-004 already calls `tracing::info!`, `tracing::warn!`, `tracing::error!` throughout `audio/engine.rs`. Right now those calls are silent β€” no subscriber is registered. T-011 initialises the subscriber so those calls produce output. Add the `rerun-telemetry` Cargo feature as a stub (prints "Rerun sink active" but does no real Rerun work β€” T-121 owns the real implementation). Nothing else.
---
## Context
`tracing` is already a workspace dependency (AMENDMENT-001) and is called throughout `kansas/`. Without a subscriber, every `tracing::info!` call is a no-op and developers get no log output at all β€” including audio device errors, transport state transitions, and model inference latencies. This task is the one-line initialisation that activates all of it.
The `rerun-telemetry` feature flag gates the Rerun SDK dependency. Production builds ship without it (`cargo tauri build` β€” no Rerun). Development builds opt in with `cargo tauri dev --features rerun-telemetry`. T-121 fills the stub with real Rerun log calls.
---
## Prerequisites
- [ ] T-001 merged β€” workspace `Cargo.toml` with `tracing` and `tracing-subscriber` already listed
Verify both are present in `[workspace.dependencies]`. If missing, add:
```toml
tracing = { version = "*" }
tracing-subscriber = { version = "*", features = ["env-filter", "fmt"] }
```
---
## Acceptance Criteria
- [ ] `cargo tauri dev` prints structured log lines to stdout β€” at minimum the `[audio]` lines from T-004
- [ ] `RUST_LOG=debug cargo tauri dev` prints debug-level output
- [ ] `RUST_LOG=warn cargo tauri dev` shows only warnings and errors
- [ ] Without `RUST_LOG` set, default filter is `kansas=info,warn` (kansas at info, everything else at warn)
- [ ] `cargo tauri dev --features rerun-telemetry` prints `[logging] Rerun telemetry sink active (stub β€” see T-121)` and does not crash
- [ ] `cargo tauri build` (without `rerun-telemetry`) compiles without error β€” Rerun SDK is not linked
- [ ] `cargo check --workspace` β€” zero errors
- [ ] `cargo clippy --workspace -- -D warnings` β€” zero warnings
---
## New Cargo Feature
Add to `kansas/Cargo.toml`:
```toml
[features]
default = []
rerun-telemetry = [] # T-121 adds: dep:rerun when this is filled in
[dependencies]
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
# rerun dep added by T-121 under rerun-telemetry feature
```
---
## New File: `kansas/src/logging.rs`
```rust
//! Logging infrastructure for the Synesthesia Tauri backend.
//!
//! Initialise once at startup via [`setup`].
//! Log level controlled by the `RUST_LOG` environment variable.
//!
//! # Feature: `rerun-telemetry`
//! When compiled with `--features rerun-telemetry`, a stub Rerun sink is
//! registered alongside the stdout subscriber. T-121 replaces the stub with
//! real Rerun log calls.
use tracing_subscriber::{
fmt,
layer::SubscriberExt,
util::SubscriberInitExt,
EnvFilter,
};
/// Default log filter when `RUST_LOG` is not set.
/// - `kansas` crate: INFO and above (our own logs)
/// - Everything else: WARN and above (suppress noisy deps)
const DEFAULT_FILTER: &str = "kansas=info,warn";
/// Initialise the global tracing subscriber.
/// Must be called exactly once, before any `tracing::` calls.
/// Panics if called a second time (tracing subscriber is a global singleton).
pub fn setup() {
let filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new(DEFAULT_FILTER));
let fmt_layer = fmt::layer()
.with_target(true) // show module path
.with_thread_names(false) // too noisy for audio threads
.with_file(false) // file:line in DEBUG only
.compact();
let registry = tracing_subscriber::registry()
.with(filter)
.with(fmt_layer);
#[cfg(feature = "rerun-telemetry")]
let registry = registry.with(RerunStubLayer);
registry.init();
#[cfg(feature = "rerun-telemetry")]
tracing::info!("[logging] Rerun telemetry sink active (stub β€” see T-121)");
tracing::info!("[logging] Tracing initialised β€” RUST_LOG={}",
std::env::var("RUST_LOG").unwrap_or_else(|_| DEFAULT_FILTER.into()));
}
// ─── Rerun stub layer ─────────────────────────────────────────────────────────
#[cfg(feature = "rerun-telemetry")]
struct RerunStubLayer;
#[cfg(feature = "rerun-telemetry")]
impl<S: tracing::Subscriber> tracing_subscriber::Layer<S> for RerunStubLayer {
// T-121 overrides on_event() to forward structured log data to the Rerun SDK.
// Stub: no-op layer that satisfies the trait bound.
}
```
---
## Update `kansas/src/main.rs`
Add one line at the top of `main()`, before anything else:
```rust
mod logging;
// ... other mods
fn main() {
// MUST be first β€” initialises global tracing subscriber before any
// tracing::* calls in AudioEngine::new(), TransportHandle::new(), etc.
logging::setup();
let audio_engine = AudioEngine::new()
.expect("Failed to initialise audio engine");
tauri::Builder::default()
// ...
```
---
## Add `logging` Module to `kansas/src/lib.rs`
```rust
pub mod logging;
```
---
## Implementation Notes
### Why `compact()` not `pretty()`
`pretty()` emits multi-line ANSI output. In a terminal it looks great; in a Windows file redirect or CI log it produces garbled escape codes and hard-to-grep output. `compact()` gives single-line structured output readable in both.
### `tracing::instrument` for hot paths
Do **not** add `#[tracing::instrument]` to the audio callback or the tick loop β€” these fire 200+ times per second and the span overhead accumulates. Reserve `#[instrument]` for IPC command handlers and one-shot initialisation paths. T-011 does not add any `#[instrument]` attributes; that is left to individual task authors.
### The `RerunStubLayer` no-op trait impl
`tracing_subscriber::Layer<S>` has default implementations for all methods. The empty `impl` is valid Rust β€” it compiles to a zero-cost abstraction that adds no overhead when `rerun-telemetry` is disabled (the feature gates the entire struct out of the binary). When T-121 arrives it fills in `fn on_event(...)` to forward log fields to the Rerun SDK.
### Log output format
After T-011, `cargo tauri dev` produces lines like:
```
2026-03-19T18:45:01.234Z INFO kansas::logging: [logging] Tracing initialised β€” RUST_LOG=kansas=info,warn
2026-03-19T18:45:01.235Z INFO kansas::audio::engine: [audio] Output: Speakers (Realtek) | 48000Hz | 2ch
2026-03-19T18:45:01.236Z INFO kansas::audio::engine: [audio] Input: Microphone (USB) | 48000Hz | 2ch
```
---
## Testing
```bash
# Default filter β€” should see INFO from kansas, WARN from deps
cargo tauri dev
# Debug filter β€” verbose output
RUST_LOG=debug cargo tauri dev
# Warn only β€” mostly silent
RUST_LOG=warn cargo tauri dev
# Rerun stub
cargo tauri dev --features rerun-telemetry
# Expected line: [logging] Rerun telemetry sink active (stub β€” see T-121)
# Release build must NOT include rerun
cargo tauri build
# Verify: ldd/dumpbin on the .exe shows no rerun .dll
```
---
## GitHub CLI
```bash
gh issue create \
--title "T-011: tracing log infrastructure β€” subscriber init, RUST_LOG filter, Rerun sink stub" \
--label "type:task,stack:rust,agent:autonomous,priority:high,status:ready,day:1" \
--body-file T-011.md
```
---
**Parent:** GENESIS
**Blocks:** T-121 (fills `RerunStubLayer::on_event` with real Rerun calls)
**Blocked By:** T-001
**Version:** v0.1 Β· **Iteration:** iter-1 Β· **Effort:** XS (1 hour)