diff --git a/src-tauri/src/events.rs b/src-tauri/src/events.rs index 09b68fb..9073232 100644 --- a/src-tauri/src/events.rs +++ b/src-tauri/src/events.rs @@ -1,23 +1,15 @@ -use std::collections::HashMap; - use serde::{Deserialize, Serialize}; use specta::Type; use tauri_specta::Event; -use crate::{ - downloader::{download_progress::DownloadProgress, download_task_state::DownloadTaskState}, - types::log_level::LogLevel, +use crate::downloader::{ + download_progress::DownloadProgress, download_task_state::DownloadTaskState, }; #[derive(Debug, Clone, Serialize, Deserialize, Type, Event)] +#[serde(rename_all = "camelCase")] pub struct LogEvent { - pub timestamp: String, - pub level: LogLevel, - pub fields: HashMap, - pub target: String, - pub filename: String, - #[serde(rename = "line_number")] - pub line_number: i64, + pub json_raw: String, } #[derive(Debug, Clone, Serialize, Deserialize, Type, Event)] diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 3ab3e57..e80eaba 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -33,6 +33,7 @@ use crate::{ downloader::download_manager::DownloadManager, errors::install_custom_eyre_handler, events::{DownloadEvent, LogEvent}, + types::log_metadata::LogMetadata, }; fn generate_context() -> tauri::Context { @@ -72,7 +73,8 @@ pub fn run() { get_skip_segments, get_available_media_formats, ]) - .events(tauri_specta::collect_events![LogEvent, DownloadEvent]); + .events(tauri_specta::collect_events![LogEvent, DownloadEvent]) + .typ::(); #[cfg(debug_assertions)] builder diff --git a/src-tauri/src/logger.rs b/src-tauri/src/logger.rs index 88e658a..73039df 100644 --- a/src-tauri/src/logger.rs +++ b/src-tauri/src/logger.rs @@ -13,7 +13,7 @@ use tracing_error::ErrorLayer; use tracing_subscriber::{ Layer, Registry, filter::{FilterExt, Targets, filter_fn}, - fmt::{layer, time::LocalTime}, + fmt::{MakeWriter, layer, time::LocalTime}, layer::SubscriberExt, registry::LookupSpan, util::SubscriberInitExt, @@ -30,17 +30,8 @@ struct LogEventWriter { impl Write for LogEventWriter { fn write(&mut self, buf: &[u8]) -> std::io::Result { - let log_string = String::from_utf8_lossy(buf); - match serde_json::from_str::(&log_string) { - Ok(log_event) => { - let _ = log_event.emit(&self.app); - } - Err(err) => { - let log_string = log_string.to_string(); - let message = err.to_string(); - tracing::error!(log_string, message, "将日志字符串解析为LogEvent失败"); - } - } + let json_raw = String::from_utf8_lossy(buf).to_string(); + let _ = LogEvent { json_raw }.emit(&self.app); Ok(buf.len()) } @@ -49,6 +40,20 @@ impl Write for LogEventWriter { } } +struct LogEventWriterFactory { + app: AppHandle, +} + +impl MakeWriter<'_> for LogEventWriterFactory { + type Writer = LogEventWriter; + + fn make_writer(&self) -> Self::Writer { + LogEventWriter { + app: self.app.clone(), + } + } +} + static RELOAD_FN: OnceLock eyre::Result<()> + Send + Sync>> = OnceLock::new(); static GUARD: OnceLock>> = OnceLock::new(); @@ -70,9 +75,9 @@ pub fn init(app: &AppHandle) -> eyre::Result<()> { .with_file(true) .with_line_number(true); // 发送到前端 - let log_event_writer = std::sync::Mutex::new(LogEventWriter { app: app.clone() }); + let log_event_factory = LogEventWriterFactory { app: app.clone() }; let log_event_layer = layer() - .with_writer(log_event_writer) + .with_writer(log_event_factory) .with_timer(LocalTime::rfc_3339()) .with_file(true) .with_line_number(true) diff --git a/src-tauri/src/types/log_level.rs b/src-tauri/src/types/log_level.rs deleted file mode 100644 index c8bc880..0000000 --- a/src-tauri/src/types/log_level.rs +++ /dev/null @@ -1,16 +0,0 @@ -use serde::{Deserialize, Serialize}; -use specta::Type; - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Type)] -pub enum LogLevel { - #[serde(rename = "TRACE")] - Trace, - #[serde(rename = "DEBUG")] - Debug, - #[serde(rename = "INFO")] - Info, - #[serde(rename = "WARN")] - Warn, - #[serde(rename = "ERROR")] - Error, -} diff --git a/src-tauri/src/types/log_metadata.rs b/src-tauri/src/types/log_metadata.rs new file mode 100644 index 0000000..2187f48 --- /dev/null +++ b/src-tauri/src/types/log_metadata.rs @@ -0,0 +1,39 @@ +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; +use specta::Type; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Type)] +pub struct LogMetadata { + pub timestamp: String, + pub level: LogLevel, + pub fields: HashMap, + pub target: String, + pub filename: String, + pub line_number: i64, + #[serde(default)] + pub span: serde_json::Value, + #[serde(default)] + pub spans: Vec, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Type)] +pub struct LogSpan { + pub name: String, + #[serde(flatten)] + pub other_fields: HashMap, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Type)] +pub enum LogLevel { + #[serde(rename = "TRACE")] + Trace, + #[serde(rename = "DEBUG")] + Debug, + #[serde(rename = "INFO")] + Info, + #[serde(rename = "WARN")] + Warn, + #[serde(rename = "ERROR")] + Error, +} diff --git a/src-tauri/src/types/mod.rs b/src-tauri/src/types/mod.rs index 68e0bb7..fd290e1 100644 --- a/src-tauri/src/types/mod.rs +++ b/src-tauri/src/types/mod.rs @@ -19,7 +19,7 @@ pub mod get_history_info_params; pub mod get_normal_info_params; pub mod get_user_video_info_params; pub mod history_info; -pub mod log_level; +pub mod log_metadata; pub mod normal_info; pub mod normal_media_url; pub mod player_info; diff --git a/src/bindings.ts b/src/bindings.ts index 73a4113..b5b219a 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -331,8 +331,10 @@ export type JsonTask = { selected: boolean; completed: boolean } export type JsonValue = null | boolean | number | string | JsonValue[] | { [key in string]: JsonValue } export type LabelInUserInfo = { path: string; text: string; label_theme: string; text_color: string; bg_style: number; bg_color: string; border_color: string; use_img_label: boolean; img_label_uri_hans: string; img_label_uri_hant: string; img_label_uri_hans_static: string; img_label_uri_hant_static: string } export type LevelInfoInUserInfo = { current_level: number; current_min: number; current_exp: number } -export type LogEvent = { timestamp: string; level: LogLevel; fields: { [key in string]: JsonValue }; target: string; filename: string; line_number: number } +export type LogEvent = { jsonRaw: string } export type LogLevel = "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" +export type LogMetadata = { timestamp: string; level: LogLevel; fields: { [key in string]: JsonValue }; target: string; filename: string; line_number: number; span?: JsonValue; spans?: LogSpan[] } +export type LogSpan = ({ [key in string]: null | boolean | number | string | JsonValue[] | { [key in string]: JsonValue } }) & { name: string } export type MediaChunk = { start: number; end: number; completed: boolean } export type MediaInFav = { id: number; type: number; title: string; cover: string; intro: string; page: number; duration: number; upper: UpperInMedia; attr: number; cnt_info: CntInfoInMedia; link: string; ctime: number; pubtime: number; fav_time: number; bv_id: string; bvid: string; ugc: Ugc | null; media_list_link: string } export type MediaInWatchLater = { aid: number; videos: number; tid: number; tname: string; copyright: number; pic: string; title: string; pubdate: number; ctime: number; desc: string; state: number; duration: number; redirect_url: string | null; mission_id: number | null; rights: RightsInWatchLater; owner: OwnerInWatchLater; stat: StatInWatchLater; dynamic: string; dimension: DimensionInWatchLater; short_link_v2: string; up_from_v2: number | null; first_frame: string | null; pub_location: string | null; cover43: string; tidv2: number; tnamev2: string; pid_v2: number; pid_name_v2: string; page: PageInWatchLater; count: number; cid: number; progress: number; add_at: number; bvid: string; uri: string; enable_vt: number; view_text_1: string; card_type: number; left_icon_type: number; left_text: string; right_icon_type: number; right_text: string; arc_state: number; pgc_label: string; show_up: boolean; forbid_fav: boolean; forbid_sort: boolean; season_title: string; long_title: string; index_title: string; c_source: string; season_id: number | null } diff --git a/src/dialogs/LogDialog.vue b/src/dialogs/LogDialog.vue index 25c45e6..b8f8761 100644 --- a/src/dialogs/LogDialog.vue +++ b/src/dialogs/LogDialog.vue @@ -1,5 +1,5 @@