From 23bc984cd93d84fde30a6fbb2db8217167d39862 Mon Sep 17 00:00:00 2001 From: John Carmack Date: Tue, 13 Jan 2026 22:03:10 -0800 Subject: [PATCH 1/2] Drastically shorten README, link to docs.rs for details --- README.md | 355 +++--------------------------------------------------- 1 file changed, 20 insertions(+), 335 deletions(-) diff --git a/README.md b/README.md index 276d3d1..fae127e 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,16 @@ # Tauri Plugin Tracing -A Tauri plugin that integrates the Rust `tracing` crate for structured logging, bridging logs between your Rust backend and JavaScript frontend. - -## Why tauri-plugin-tracing? - -This plugin provides everything `tauri-plugin-log` offers, plus advanced capabilities from the `tracing` ecosystem. - -### Feature Comparison - -| Feature | tauri-plugin-log | tauri-plugin-tracing | -|---------|------------------|----------------------| -| Log levels (trace/debug/info/warn/error) | ✓ | ✓ | -| Console output (stdout/stderr) | ✓ | ✓ | -| File logging with rotation | ✓ | ✓ | -| Forward logs to webview | ✓ | ✓ | -| Per-module filtering | ✓ | ✓ | -| Colored output | ✓ | ✓ | -| Custom log formats | ✓ | ✓ | -| Size-based rotation | ✓ | ✓ | -| **Structured span context** | | ✓ | -| **Custom tracing layers** | | ✓ | -| **OpenTelemetry integration** | | ✓ | -| **Span timing visualization** | | ✓ | -| **Early initialization** | | ✓ | - -### Additional Features - -- **Structured Spans**: Track execution context across async boundaries with `tracing` spans -- **Custom Layers**: Add OpenTelemetry, Sentry, or any `tracing-subscriber` layer -- **Span Timing Visualization**: Generate flamegraphs/flamecharts showing span durations and call hierarchy -- **Early Initialization**: Set up logging before Tauri starts for complete startup tracing -- **ANSI Stripping**: `StripAnsiWriter` removes color codes when writing to files +Integrate Rust's `tracing` crate with your Tauri app. Bridge logs between Rust and JavaScript with support for file rotation, custom layers, and span visualization. ## Installation -### Rust - ```toml [dependencies] tauri-plugin-tracing = "0.2" ``` -### JavaScript - ```bash npm install @fltsci/tauri-plugin-tracing -# or -pnpm add @fltsci/tauri-plugin-tracing ``` ## Quick Start @@ -68,318 +32,39 @@ fn main() { ``` ```typescript -import { info, debug, error, attachConsole } from '@fltsci/tauri-plugin-tracing'; - -// Forward Rust logs to browser console -await attachConsole(); +import { info, attachConsole } from '@fltsci/tauri-plugin-tracing'; -// Log from JavaScript -info('Application started'); -debug('Debug details', { user: 'alice' }); -error('Something went wrong'); +await attachConsole(); // See Rust logs in browser console +info('Hello from JS'); // Send JS logs to Rust ``` ## Features -### Cargo Features - -- **`colored`** - ANSI color output in terminal -- **`specta`** - TypeScript type generation -- **`flamegraph`** - Span timing visualization with flamegraph/flamechart SVG generation - -### Log Targets - -Configure where logs are written: - -```rust -use tauri_plugin_tracing::{Builder, Target}; - -Builder::new() - .targets([ - Target::Stdout, - Target::Webview, - Target::LogDir { file_name: None }, - ]) - .with_default_subscriber() - .build() -``` - -- **Stdout** / **Stderr** - Terminal output -- **Webview** - Forward to JavaScript via events -- **LogDir** - Platform log directory (`~/Library/Logs/` on macOS) -- **Folder** - Custom directory - -### File Logging - -```rust -Builder::new() - .with_file_logging() // Enable file logging - .with_rotation(Rotation::Daily) // Rotate daily - .with_rotation_strategy(RotationStrategy::KeepSome(7)) // Keep 7 files - .with_max_file_size(MaxFileSize::mb(10)) // Rotate at 10 MB - .with_default_subscriber() - .build() -``` - -### Per-Module Filtering - -```rust -Builder::new() - .with_max_level(LevelFilter::INFO) - .with_target("my_app::database", LevelFilter::DEBUG) - .with_target("hyper", LevelFilter::WARN) - .with_default_subscriber() - .build() -``` - -### Custom Formatting - -```rust -use tauri_plugin_tracing::{Builder, LogFormat}; - -Builder::new() - .with_format(LogFormat::Compact) // or Full, Pretty - .with_file(true) - .with_line_number(true) - .with_thread_ids(true) - .with_default_subscriber() - .build() -``` - -### Custom Tracing Layers - -```rust -use tracing_subscriber::Layer; - -let otel_layer = tracing_opentelemetry::layer().boxed(); - -Builder::new() - .with_layer(otel_layer) - .with_default_subscriber() - .build() -``` - -### Span Timing Visualization - -Requires the `flamegraph` feature. - -> **Note:** This captures span durations (wall-clock time), not CPU time. It's useful for -> understanding call hierarchy and finding latency bottlenecks, but not for CPU profiling. -> For CPU profiling, use Instruments (macOS), `perf` (Linux), or `samply`. - -**With default subscriber:** - -```rust -Builder::new() - .with_flamegraph() - .with_default_subscriber() - .build() -``` - -**With custom subscriber:** - -```rust -use tauri_plugin_tracing::{Builder, WebviewLayer, LevelFilter, create_flame_layer}; -use tracing_subscriber::{Registry, layer::SubscriberExt, util::SubscriberInitExt, fmt}; - -let builder = Builder::new().with_max_level(LevelFilter::DEBUG); -let filter = builder.build_filter(); - -tauri::Builder::default() - .plugin(builder.build()) - .setup(move |app| { - let flame_layer = create_flame_layer(app.handle())?; - - Registry::default() - .with(fmt::layer()) - .with(WebviewLayer::new(app.handle().clone())) - .with(flame_layer) - .with(filter) - .init(); - Ok(()) - }) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); -``` - -**Early initialization (before Tauri starts):** - -```rust -use tauri_plugin_tracing::{Builder, create_flame_layer_with_path, FlameExt}; -use tracing_subscriber::{registry, layer::SubscriberExt, util::SubscriberInitExt, fmt}; - -fn main() { - let log_dir = std::env::temp_dir().join("my-app"); - std::fs::create_dir_all(&log_dir).unwrap(); - - // Create flame layer before Tauri starts - let (flame_layer, flame_guard) = create_flame_layer_with_path( - &log_dir.join("profile.folded") - ).unwrap(); - - // Initialize tracing early - registry() - .with(fmt::layer()) - .with(flame_layer) - .init(); - - // Now start Tauri and register the guard - tauri::Builder::default() - .plugin(Builder::new().build()) - .setup(move |app| { - // Register the guard so JS can generate flamegraphs - app.handle().register_flamegraph(flame_guard)?; - Ok(()) - }) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); -} -``` - -**Generate visualizations from JavaScript:** - -```typescript -import { generateFlamegraph, generateFlamechart } from '@fltsci/tauri-plugin-tracing'; - -// Generate a flamegraph (collapses identical stack frames, shows cumulative time) -const flamegraphPath = await generateFlamegraph(); - -// Generate a flamechart (preserves chronological ordering) -const flamechartPath = await generateFlamechart(); -``` - -## Custom Subscriber Setup - -For advanced use cases, compose your own subscriber: - -```rust -use tauri_plugin_tracing::{Builder, WebviewLayer, LevelFilter}; -use tracing_subscriber::{Registry, layer::SubscriberExt, util::SubscriberInitExt, fmt}; - -let builder = Builder::new() - .with_max_level(LevelFilter::DEBUG) - .with_target("hyper", LevelFilter::WARN); - -let filter = builder.build_filter(); - -tauri::Builder::default() - .plugin(builder.build()) - .setup(move |app| { - Registry::default() - .with(fmt::layer()) - .with(WebviewLayer::new(app.handle().clone())) - .with(filter) - .init(); - Ok(()) - }) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); -``` - -### Custom Subscriber with File Logging - -Use `tracing_appender` (re-exported by this crate) for file logging with custom subscribers: - -```rust -use tauri::Manager; -use tauri_plugin_tracing::{Builder, WebviewLayer, LevelFilter, tracing_appender}; -use tracing_subscriber::{Registry, layer::SubscriberExt, util::SubscriberInitExt, fmt}; - -let builder = Builder::new().with_max_level(LevelFilter::DEBUG); -let filter = builder.build_filter(); - -tauri::Builder::default() - .plugin(builder.build()) - .setup(move |app| { - let log_dir = app.path().app_log_dir()?; - let file_appender = tracing_appender::rolling::daily(&log_dir, "app"); - let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); - - // Store guard in Tauri state to keep file logging active - app.manage(guard); - - Registry::default() - .with(fmt::layer()) - .with(fmt::layer().with_ansi(false).with_writer(non_blocking)) - .with(WebviewLayer::new(app.handle().clone())) - .with(filter) - .init(); - Ok(()) - }) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); -``` - -### Early Initialization - -For maximum control, initialize tracing before creating the Tauri app: - -```rust -use tauri_plugin_tracing::{Builder, StripAnsiWriter, tracing_appender}; -use tracing::Level; -use tracing_subscriber::filter::Targets; -use tracing_subscriber::layer::SubscriberExt; -use tracing_subscriber::util::SubscriberInitExt; -use tracing_subscriber::{fmt, registry}; - -fn setup_logger() -> Builder { - let log_dir = std::env::temp_dir().join("my-app"); - let _ = std::fs::create_dir_all(&log_dir); - - let file_appender = tracing_appender::rolling::daily(&log_dir, "app"); - let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); - std::mem::forget(guard); // Keep file logging active for app lifetime - - let targets = Targets::new() - .with_default(Level::DEBUG) - .with_target("hyper", Level::WARN) - .with_target("reqwest", Level::WARN); - - registry() - .with(fmt::layer().with_ansi(true)) - .with(fmt::layer().with_writer(StripAnsiWriter::new(non_blocking)).with_ansi(false)) - .with(targets) - .init(); +- **Log levels**: trace, debug, info, warn, error +- **Targets**: stdout, stderr, webview, file (with rotation) +- **Filtering**: per-module log levels +- **Custom layers**: OpenTelemetry, Sentry, or any tracing-subscriber layer +- **Span visualization**: flamegraph/flamechart SVG generation (`flamegraph` feature) - Builder::new() // Return minimal builder - logging is already configured -} - -fn main() { - let builder = setup_logger(); - tauri::Builder::default() - .plugin(builder.build()) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); -} -``` +### Cargo Features -## JavaScript API +- `colored` - ANSI color output +- `specta` - TypeScript type generation +- `flamegraph` - Span timing visualization -### Logging +## Console Integration ```typescript -import { trace, debug, info, warn, error } from '@fltsci/tauri-plugin-tracing'; +import { attachConsole, interceptConsole, takeoverConsole } from '@fltsci/tauri-plugin-tracing'; -trace('Very verbose info'); -debug('Debug details'); -info('General info'); -warn('Warning'); -error('Error'); +attachConsole(); // Rust logs → browser console +interceptConsole(); // JS console → Rust tracing +takeoverConsole(); // Both directions (full integration) ``` -### Event Listeners - -```typescript -import { attachConsole, attachLogger } from '@fltsci/tauri-plugin-tracing'; - -// Forward all Rust logs to browser console -const unlisten = await attachConsole(); +## Documentation -// Custom log handler -const unlisten = await attachLogger(({ level, message }) => { - // Send to external service, store locally, etc. -}); -``` +See [docs.rs](https://docs.rs/tauri-plugin-tracing) for the full API reference and advanced usage (custom subscribers, file logging, early initialization). ## License From 529430231e85de7bc18889d1795ac05aebb61a0f Mon Sep 17 00:00:00 2001 From: John Carmack Date: Tue, 13 Jan 2026 22:06:04 -0800 Subject: [PATCH 2/2] Add changefile --- .changes/shorten-readme.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/shorten-readme.md diff --git a/.changes/shorten-readme.md b/.changes/shorten-readme.md new file mode 100644 index 0000000..5921580 --- /dev/null +++ b/.changes/shorten-readme.md @@ -0,0 +1,6 @@ +--- +"tracing": patch +"tracing-js": patch +--- + +Shorten README, link to docs.rs for details.