Console Debugging in Tauri: DevTools & Terminal Logging
Video: Console Debugging in Tauri: DevTools & Terminal Logging by Taught by Celeste AI - AI Coding Coach
Two consoles. Browser DevTools for the frontend. The terminal you launched
tauri devin for Rust. Knowing which gets which output is half the debugging skill.
A Tauri app has two runtimes. The frontend runs in a webview — debug it like any web app, with browser DevTools. The Rust backend runs as a native process — debug it like any Rust app, with println!, eprintln!, and the tracing ecosystem. This lesson is the map of where each kind of output goes and how to read it.
DevTools for the frontend
In development, right-click anywhere in the Tauri window and pick Inspect Element. The familiar Chrome DevTools panel appears.
Useful tabs:
- Console —
console.logoutput, errors, warnings. - Network — every HTTP request the frontend makes (via the
httpplugin or fetch). - Elements — the live HTML/CSS, identical to a browser.
- Sources — set breakpoints in your TypeScript/JavaScript.
- Application — local storage, cookies, IndexedDB.
DevTools are auto-enabled in tauri dev builds. For production builds, they're disabled by default. To enable in production:
"app": {
"windows": [{
"devTools": true
}]
}
Or build with cargo run --features devtools.
Logging from JavaScript
console.log("info");
console.warn("watch out");
console.error("something went wrong");
console.table([{ a: 1 }, { a: 2 }]);
console.time("op"); /* ... */ console.timeEnd("op");
Output goes to the DevTools Console. Standard browser API; nothing Tauri-specific.
For a console.log that also fires from production, route through Rust:
import { invoke } from "@tauri-apps/api/core";
async function logToBackend(msg: string) {
await invoke("log", { message: msg });
}
#[tauri::command]
fn log(message: String) {
println!("[FRONTEND] {}", message);
}
Now production users' issues can be traced via the Rust log if you've set up file-based logging.
Logging from Rust
Simplest: println! and eprintln!. Both write to the terminal where you ran npm run tauri dev.
#[tauri::command]
fn save(text: String) -> Result<(), String> {
println!("save called with text length: {}", text.len());
// ...
Ok(())
}
Run npm run tauri dev. Hit the button that triggers save. The terminal shows the println output.
For long-running apps, use the log crate plus an env logger:
log = "0.4"
env_logger = "0.11"
use log::{info, warn, error, debug};
env_logger::init();
info!("app starting");
debug!("db pool: {:?}", pool);
warn!("non-fatal issue");
error!("boom: {}", err);
Set RUST_LOG=debug (or info, warn, error) to control verbosity:
RUST_LOG=debug npm run tauri dev
env_logger formats logs with timestamps, levels, and module paths. Much nicer than raw println! for serious apps.
tracing for structured logging
For production-grade logging, the tracing crate is the standard:
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
use tracing::{info, warn, error, instrument};
tracing_subscriber::fmt()
.with_env_filter("info,my_app=debug")
.init();
#[instrument]
async fn fetch_user(id: u64) -> Result<User, Error> {
info!("fetching user");
// ...
}
#[instrument] automatically logs entry/exit and arguments. with_env_filter lets you control verbosity per module. The output is structured (key=value pairs) and parseable for log-aggregation tools.
File-based logging
For production users who hit bugs, you want logs they can send you. Use the tauri-plugin-log plugin:
cargo add tauri-plugin-log
npm install @tauri-apps/plugin-log
.plugin(tauri_plugin_log::Builder::new()
.target(tauri_plugin_log::Target::new(
tauri_plugin_log::TargetKind::LogDir { file_name: None }
))
.build())
Logs go to a file in the app's log directory. From the frontend:
import { info, error } from "@tauri-apps/plugin-log";
info("user clicked save");
error(`save failed: ${err}`);
The plugin captures both Rust and JS logs into a unified file. Add a "Show logs" button to your UI that opens the file in the OS's default viewer.
Tauri-specific debug helpers
println! in Tauri commands works the same as anywhere — output to stdout. For eprintln!, output to stderr. Both visible in tauri dev's terminal.
For panics, the runtime catches them and shows the error in the terminal. A panic will crash the app, so design for graceful errors instead of relying on panics.
Source maps
In tauri dev, Vite produces source maps. When a JS error fires, the DevTools "Sources" tab shows your TypeScript with original line numbers. Set breakpoints there.
In production builds, source maps are usually omitted. To enable for debugging a release build:
// vite.config.ts
export default defineConfig({
build: { sourcemap: true },
});
Performance debugging
DevTools has a Performance tab for the frontend — record a session, see what's slow.
For Rust performance, use cargo flamegraph:
cargo install flamegraph
cargo flamegraph --bin my-app
Generates an SVG showing where CPU time is spent. Open in a browser to drill into hot functions.
Network debugging
DevTools' Network tab shows every HTTP request if it goes through the browser fetch API. Requests made via tauri-plugin-http's fetch may or may not appear depending on how they're routed.
For Rust-side requests via reqwest, log them yourself:
let resp = reqwest::get(&url).await?;
info!(status = resp.status().as_u16(), url = %url, "http response");
Or wire reqwest to a tracing-aware HTTP client wrapper.
Common mistakes
Looking in the wrong console. println! from Rust is in the terminal. console.log is in DevTools. Confusion about which is which wastes hours.
No logging in production. When the user reports a bug, you have nothing to look at. Set up file-based logging from day one.
Logging too much. Verbose logs in a hot loop fill up the disk and slow the app. Use levels (debug, info, warn, error) and filter by env var.
Logging sensitive data. API keys, passwords, PII shouldn't appear in logs that users might send back.
Debug builds in production. Tauri's release build is npm run tauri build. Don't ship tauri dev's output to users — it's unoptimized and noisy.
What's next
Next lesson: shell commands. Run external processes (git, ffmpeg, your own CLI tools) from a Tauri app and capture their output.
Recap
DevTools for the frontend, terminal/log file for Rust. println! for quick debugging; log + env_logger for medium-grade; tracing for structured production logging. tauri-plugin-log to write logs to a file users can send. Source maps for breaking on TypeScript code. Recordings for performance.
Next: shell commands.