generated from nhcarrigan/template
feat: add debug console for frontend and backend logs
Added a comprehensive debug console feature that captures and displays logs from both the frontend and backend in a unified interface. Frontend changes: - Created DebugConsole component with real-time log display - Added debugConsoleStore for state management and console capture - Integrated console into main layout - Added toggle button in StatusBar with console icon - Implemented Ctrl+` keyboard shortcut to open/close console - Features: log filtering by level, auto-scroll, timestamps, colour-coding Backend changes: - Added tracing and tracing-subscriber dependencies - Created custom TauriLogLayer to emit Rust logs to frontend - Integrated tracing subscriber in lib.rs setup - Logs are forwarded via Tauri events (debug:log) Key features: - Circular buffer (max 1000 logs) prevents memory issues - Frontend logs captured via console method overrides - Backend logs forwarded from Rust tracing layer - Log level filtering (debug, info, warn, error, all) - Source badges distinguish frontend vs backend logs - Colour-coded log levels for easy identification - Auto-scroll toggle for inspecting older logs - Clear logs button for resetting the console - Beautiful dark-themed UI matching app aesthetic Closes #126
This commit is contained in:
Generated
+74
@@ -1658,6 +1658,8 @@ dependencies = [
|
||||
"tauri-plugin-store",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"uuid 1.19.0",
|
||||
"windows 0.62.2",
|
||||
]
|
||||
@@ -2245,6 +2247,15 @@ dependencies = [
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
|
||||
dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.10"
|
||||
@@ -2401,6 +2412,15 @@ dependencies = [
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
@@ -3879,6 +3899,15 @@ dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shared_child"
|
||||
version = "1.1.1"
|
||||
@@ -4695,6 +4724,15 @@ dependencies = [
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.10.3"
|
||||
@@ -4986,6 +5024,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
|
||||
dependencies = [
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex-automata",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5167,6 +5235,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.2.1"
|
||||
|
||||
@@ -33,6 +33,8 @@ semver = "1"
|
||||
chrono = { version = "0.4.43", features = ["serde"] }
|
||||
discord-rich-presence = "0.2"
|
||||
dirs = "5"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows = { version = "0.62", features = [
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tauri::{AppHandle, Emitter};
|
||||
use tracing::{Level, Subscriber};
|
||||
use tracing_subscriber::layer::{Context, Layer};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DebugLogEvent {
|
||||
pub level: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TauriLogLayer {
|
||||
app: Arc<AppHandle>,
|
||||
}
|
||||
|
||||
impl TauriLogLayer {
|
||||
pub fn new(app: AppHandle) -> Self {
|
||||
Self {
|
||||
app: Arc::new(app),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Layer<S> for TauriLogLayer
|
||||
where
|
||||
S: Subscriber,
|
||||
{
|
||||
fn on_event(
|
||||
&self,
|
||||
event: &tracing::Event<'_>,
|
||||
_ctx: Context<'_, S>,
|
||||
) {
|
||||
let metadata = event.metadata();
|
||||
let level = match *metadata.level() {
|
||||
Level::ERROR => "error",
|
||||
Level::WARN => "warn",
|
||||
Level::INFO => "info",
|
||||
Level::DEBUG => "debug",
|
||||
Level::TRACE => "debug",
|
||||
};
|
||||
|
||||
// Extract message from the event
|
||||
struct MessageVisitor {
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl tracing::field::Visit for MessageVisitor {
|
||||
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
|
||||
if field.name() == "message" {
|
||||
self.message = format!("{:?}", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = MessageVisitor {
|
||||
message: String::new(),
|
||||
};
|
||||
event.record(&mut visitor);
|
||||
|
||||
// If we couldn't extract a message, try to format the whole event
|
||||
if visitor.message.is_empty() {
|
||||
visitor.message = metadata.name().to_string();
|
||||
}
|
||||
|
||||
// Strip quotes from the message
|
||||
let message = visitor.message.trim_matches('"').to_string();
|
||||
|
||||
let log_event = DebugLogEvent {
|
||||
level: level.to_string(),
|
||||
message,
|
||||
};
|
||||
|
||||
// Emit to frontend
|
||||
let _ = self.app.emit("debug:log", log_event);
|
||||
}
|
||||
}
|
||||
+14
-1
@@ -4,6 +4,7 @@ mod clipboard;
|
||||
mod commands;
|
||||
mod config;
|
||||
mod cost_tracking;
|
||||
mod debug_logger;
|
||||
mod discord_rpc;
|
||||
mod git;
|
||||
mod notifications;
|
||||
@@ -24,6 +25,7 @@ use bridge_manager::create_shared_bridge_manager;
|
||||
use clipboard::*;
|
||||
use commands::load_saved_achievements;
|
||||
use commands::*;
|
||||
use debug_logger::TauriLogLayer;
|
||||
use discord_rpc::DiscordRpcManager;
|
||||
use git::*;
|
||||
use notifications::*;
|
||||
@@ -33,6 +35,8 @@ use snippets::*;
|
||||
use std::sync::Arc;
|
||||
use tauri::Manager;
|
||||
use temp_manager::create_shared_temp_manager;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tray::{setup_tray, should_minimize_to_tray};
|
||||
use vbs_notification::*;
|
||||
use windows_toast::*;
|
||||
@@ -58,6 +62,13 @@ pub fn run() {
|
||||
.manage(temp_manager.clone())
|
||||
.manage(discord_rpc.clone())
|
||||
.setup(move |app| {
|
||||
// Initialize tracing with custom layer that emits to frontend
|
||||
let tauri_layer = TauriLogLayer::new(app.handle().clone());
|
||||
tracing_subscriber::registry()
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.with(tauri_layer)
|
||||
.init();
|
||||
|
||||
// Initialize the app handle in the bridge manager
|
||||
bridge_manager.lock().set_app_handle(app.handle().clone());
|
||||
|
||||
@@ -67,10 +78,12 @@ pub fn run() {
|
||||
// Clean up any orphaned temp files from previous sessions
|
||||
if let Ok(count) = temp_manager.lock().cleanup_orphaned_files() {
|
||||
if count > 0 {
|
||||
println!("Cleaned up {} orphaned temp files", count);
|
||||
tracing::info!("Cleaned up {} orphaned temp files", count);
|
||||
}
|
||||
}
|
||||
|
||||
tracing::info!("Hikari Desktop started successfully");
|
||||
|
||||
// Set up system tray
|
||||
if let Err(e) = setup_tray(app.handle()) {
|
||||
eprintln!("Failed to set up system tray: {}", e);
|
||||
|
||||
Reference in New Issue
Block a user