diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ec520a4..8439499 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,4 +19,6 @@ jobs: - run: nix build -L .#entrace_core - run: nix build -L .#entrace_core_lite - run: nix build -L .#entrace_script + - run: nix develop --command bash -c "cargo semver-checks -p entrace_core" + name: semver-checks - run: nix build -L .#entrace diff --git a/Cargo.lock b/Cargo.lock index a13f052..b197bb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1405,7 +1405,7 @@ checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" [[package]] name = "entrace_core" -version = "0.1.3" +version = "0.2.0" dependencies = [ "bincode", "crossbeam-channel", diff --git a/Cargo.toml b/Cargo.toml index a63dd91..d22a50c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,8 @@ members = ["example", "gui", "entrace_core", "bench", "entrace_query", "entrace_ [profile.profiling] inherits = 'release' -debug = "line-tables-only" +debug = true + # Optimize all dependencies even in debug builds: [profile.dev.package."*"] opt-level = 2 diff --git a/entrace_core/Cargo.toml b/entrace_core/Cargo.toml index 539c39c..02eeb77 100644 --- a/entrace_core/Cargo.toml +++ b/entrace_core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "entrace_core" description = "client library for ENTRACE, a modern log viewer and observability toolkit for Rust" -version = "0.1.3" +version = "0.2.0" edition = "2024" license = "MIT OR Apache-2.0" repository = "https://github.com/algorithmiker/entrace" diff --git a/entrace_core/src/lib.rs b/entrace_core/src/lib.rs index 262a9d4..60dd97e 100644 --- a/entrace_core/src/lib.rs +++ b/entrace_core/src/lib.rs @@ -260,9 +260,9 @@ impl IETPresentationConfig { /// See also [FileIETLogProvider::new] and [remote::load_iht_trace] for functions that read an IET trace, /// in a safe way. pub unsafe fn load_trace( - file_path: impl AsRef + Send + 'static, config: LoadConfig, -) -> Result, LoadTraceError> { - let mut file = File::open(&file_path)?; + file_path: &Path, config: LoadConfig, +) -> Result { + let mut file = File::open(file_path)?; let mut buf = [0; 10]; file.read_exact(&mut buf).map_err(|x| LoadTraceError::BadMagic(MagicParseError::IoError(x)))?; let (version, ty) = parse_entrace_magic(&buf)?; @@ -272,11 +272,11 @@ pub unsafe fn load_trace( match ty { StorageFormat::IET => { let provider = FileIETLogProvider::new(file, config.iht, false)?; - Ok(Box::new(provider)) + Ok(LogProviderImpl::FileIET(provider)) } StorageFormat::IETPrefix => { let provider = FileIETLogProvider::new(file, config.iht, true)?; - Ok(Box::new(provider)) + Ok(LogProviderImpl::FileIET(provider)) } StorageFormat::ET => { #[cfg(feature = "mmap")] @@ -285,7 +285,7 @@ pub unsafe fn load_trace( // SAFETY: Mmap is inherently unsafe. let provider = unsafe { MmapLogProvider::from_file(&file) } .map_err(LoadTraceError::MmapError)?; - return Ok(Box::new(provider)); + return Ok(LogProviderImpl::Mmap(provider)); } #[allow(unreachable_code)] Err(LoadTraceError::MmapNeeded) diff --git a/entrace_core/src/log_provider.rs b/entrace_core/src/log_provider.rs index e09b954..f168fd0 100644 --- a/entrace_core/src/log_provider.rs +++ b/entrace_core/src/log_provider.rs @@ -1,6 +1,9 @@ use crate::{ Header, MetadataRefContainer, - remote::{FileIETError, RemoteLogProviderError}, + remote::{ + BaseIETLogProvider, FileIETError, FileIETLogProvider, RemoteLogProvider, + RemoteLogProviderError, + }, tree_layer::EnValueRef, }; @@ -45,3 +48,83 @@ pub trait LogProvider { /// as it directly affects FPS. fn frame_callback(&mut self) {} } + +pub enum LogProviderImpl { + BaseIET(BaseIETLogProvider), + FileIET(FileIETLogProvider), + Remote(RemoteLogProvider), + #[cfg(feature = "mmap")] + Mmap(crate::mmap::MmapLogProvider), +} + +impl LogProvider for LogProviderImpl { + fn children(&self, x: u32) -> Result<&[u32], LogProviderError> { + match self { + #[cfg(feature = "mmap")] + Self::Mmap(inner) => inner.children(x), + Self::BaseIET(inner) => inner.children(x), + Self::FileIET(inner) => inner.children(x), + Self::Remote(inner) => inner.children(x), + } + } + + fn parent(&self, x: u32) -> Result { + match self { + #[cfg(feature = "mmap")] + Self::Mmap(inner) => inner.parent(x), + Self::BaseIET(inner) => inner.parent(x), + Self::FileIET(inner) => inner.parent(x), + Self::Remote(inner) => inner.parent(x), + } + } + + fn attrs(&'_ self, x: u32) -> Result)>, LogProviderError> { + match self { + #[cfg(feature = "mmap")] + Self::Mmap(inner) => inner.attrs(x), + Self::BaseIET(inner) => inner.attrs(x), + Self::FileIET(inner) => inner.attrs(x), + Self::Remote(inner) => inner.attrs(x), + } + } + + fn header(&'_ self, x: u32) -> Result, LogProviderError> { + match self { + #[cfg(feature = "mmap")] + Self::Mmap(inner) => inner.header(x), + Self::BaseIET(inner) => inner.header(x), + Self::FileIET(inner) => inner.header(x), + Self::Remote(inner) => inner.header(x), + } + } + + fn meta(&'_ self, x: u32) -> Result, LogProviderError> { + match self { + #[cfg(feature = "mmap")] + Self::Mmap(inner) => inner.meta(x), + Self::BaseIET(inner) => inner.meta(x), + Self::FileIET(inner) => inner.meta(x), + Self::Remote(inner) => inner.meta(x), + } + } + + fn len(&self) -> usize { + match self { + #[cfg(feature = "mmap")] + Self::Mmap(inner) => inner.len(), + Self::BaseIET(inner) => inner.len(), + Self::FileIET(inner) => inner.len(), + Self::Remote(inner) => inner.len(), + } + } + + fn frame_callback(&mut self) { + match self { + #[cfg(feature = "mmap")] + Self::Mmap(inner) => inner.frame_callback(), + Self::BaseIET(inner) => inner.frame_callback(), + Self::FileIET(inner) => inner.frame_callback(), + Self::Remote(inner) => inner.frame_callback(), + } + } +} diff --git a/entrace_query/Cargo.toml b/entrace_query/Cargo.toml index bc3fa2c..70e43a5 100644 --- a/entrace_query/Cargo.toml +++ b/entrace_query/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] mlua = { version = "0.11.0", features = ["error-send", "luajit"] } -entrace_core = { version = "0.1.1", path = "../entrace_core/" } +entrace_core = { version = "0.2.0", path = "../entrace_core/" } anyhow = "1.0.100" memchr = "2.7.6" thiserror = "2.0.17" diff --git a/entrace_query/src/lib.rs b/entrace_query/src/lib.rs index 30ff322..9e5c335 100644 --- a/entrace_query/src/lib.rs +++ b/entrace_query/src/lib.rs @@ -1,10 +1,7 @@ -use entrace_core::LogProvider; - pub mod filtersets; pub mod lua_api; pub mod lua_value; -pub(crate) type TraceProvider = Box; #[derive(thiserror::Error, Debug, Clone)] pub enum QueryError { #[error("Index out of bounds. Tried to access element {index} of a container of size {actual}")] diff --git a/entrace_query/src/lua_api.rs b/entrace_query/src/lua_api.rs index b9162c4..5490e3f 100644 --- a/entrace_query/src/lua_api.rs +++ b/entrace_query/src/lua_api.rs @@ -15,15 +15,15 @@ use std::{ use anyhow::bail; use entrace_core::{ - EnValue, EnValueRef, LevelContainer, LogProvider, LogProviderError, LogProviderResult, - MetadataRefContainer, + EnValue, EnValueRef, LevelContainer, LogProvider, LogProviderError, LogProviderImpl, + LogProviderResult, MetadataRefContainer, }; use memchr::memmem::Finder; use mlua::{ExternalError, ExternalResult, IntoLua, Lua, Table, Value}; use roaring::RoaringBitmap; use crate::{ - QueryError, TraceProvider, + QueryError, filtersets::{Filterset, Matcher, Predicate, PredicateId}, lua_value::{LuaValueRef, LuaValueRefRef}, }; @@ -873,33 +873,6 @@ pub fn en_filterset_materialize( } } -struct DynAdapter<'a>(&'a dyn LogProvider); -impl<'a> LogProvider for DynAdapter<'a> { - fn children(&self, x: u32) -> Result<&[u32], LogProviderError> { - self.0.children(x) - } - - fn parent(&self, x: u32) -> Result { - self.0.parent(x) - } - - fn attrs(&'_ self, x: u32) -> Result)>, LogProviderError> { - self.0.attrs(x) - } - - fn header(&'_ self, x: u32) -> Result, LogProviderError> { - self.0.header(x) - } - - fn meta(&'_ self, x: u32) -> Result, LogProviderError> { - self.0.meta(x) - } - - fn len(&self) -> usize { - self.0.len() - } -} - pub struct JoinCtx { is_joining: AtomicBool, threads_joined: AtomicUsize, @@ -942,7 +915,6 @@ pub fn en_join(joinable: Arc) -> impl Fn(Table) -> LogProviderResult { let globals = $lua.globals(); @@ -1066,7 +1038,7 @@ impl LuaEvalState { } } pub fn setup_lua_on_arc_rwlock( - lua: &mut Lua, trace: Arc>, state: LuaEvalState, + lua: &mut Lua, trace: Arc>, state: LuaEvalState, ) -> Result<(), mlua::Error> { /// INPUT a Fn(impl LogProvider) -> Fn($arg) -> Result /// OUTPUT a Fn(Arc>> -> Fn(Lua, $arg) -> mlua::Result @@ -1075,8 +1047,7 @@ pub fn setup_lua_on_arc_rwlock( let tp = $trace_provider.clone(); move |_lua: &Lua, a: $arg| { let log = tp.read().unwrap(); - let adapter = DynAdapter(&**log); - $fn(&adapter)(a).map_err(|x| x.into_lua_err()) + $fn(&*log)(a).map_err(|x| x.into_lua_err()) } }}; } @@ -1088,8 +1059,7 @@ pub fn setup_lua_on_arc_rwlock( let tp = $trace_provider.clone(); move |lua: &Lua, a: $arg| { let log = tp.read().unwrap(); - let adapter = DynAdapter(&**log); - $fn(&adapter, lua)(a) + $fn(&*log, lua)(a) } }}; } @@ -1099,8 +1069,7 @@ pub fn setup_lua_on_arc_rwlock( "en_contains_anywhere", lua.create_function(move |_lua: &Lua, (id, needle): (u32, String)| { let log = t.read().unwrap(); - let adapter = DynAdapter(&**log); - en_contains_anywhere(&adapter, finder_cache.clone(), reusable_buf.clone())((id, needle)) + en_contains_anywhere(&*log, finder_cache.clone(), reusable_buf.clone())((id, needle)) .map_err(to_lua_err) })?, )?; @@ -1110,17 +1079,14 @@ pub fn setup_lua_on_arc_rwlock( } pub fn setup_lua_no_lock( - lua: &mut Lua, trace: Arc, state: LuaEvalState, + lua: &mut Lua, trace: Arc, state: LuaEvalState, ) -> Result<(), mlua::Error> { /// INPUT a Fn(impl LogProvider) -> Fn($arg) -> Result /// OUTPUT a Fn(Arc>> -> Fn(Lua, $arg) -> mlua::Result macro_rules! lua_wrap { ($trace_provider: expr, $arg: ty, $fn: expr) => {{ let tp = $trace_provider.clone(); - move |_lua: &Lua, a: $arg| { - let adapter = DynAdapter(&**tp); - $fn(&adapter)(a).map_err(|x| x.into_lua_err()) - } + move |_lua: &Lua, a: $arg| $fn(&*tp)(a).map_err(|x| x.into_lua_err()) }}; } @@ -1129,10 +1095,7 @@ pub fn setup_lua_no_lock( macro_rules! lua_wrap2 { ($trace_provider: expr, $arg: ty, $fn: expr) => {{ let tp = $trace_provider.clone(); - move |lua: &Lua, a: $arg| { - let adapter = DynAdapter(&**tp); - $fn(&adapter, lua)(a) - } + move |lua: &Lua, a: $arg| $fn(&*tp, lua)(a) }}; } let LuaEvalState { join_ctx, range, finder_cache, reusable_buf } = state; @@ -1140,8 +1103,7 @@ pub fn setup_lua_no_lock( lua.globals().set( "en_contains_anywhere", lua.create_function(move |_lua: &Lua, (id, needle): (u32, String)| { - let adapter = DynAdapter(&**t); - en_contains_anywhere(&adapter, finder_cache.clone(), reusable_buf.clone())((id, needle)) + en_contains_anywhere(&*t, finder_cache.clone(), reusable_buf.clone())((id, needle)) .map_err(to_lua_err) })?, )?; diff --git a/entrace_script/Cargo.toml b/entrace_script/Cargo.toml index 0e27148..4b19d74 100644 --- a/entrace_script/Cargo.toml +++ b/entrace_script/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" clap = { version = "4.5.50", features = ["derive"] } mlua = { version = "0.11.0", features = ["error-send", "luajit"] } entrace_query = { version = "0.1.1", path = "../entrace_query/" } -entrace_core = { version = "0.1.1", path = "../entrace_core/" } +entrace_core = { version = "0.2.0", path = "../entrace_core/" } anyhow = "1.0.100" [[bin]] diff --git a/entrace_script/src/main.rs b/entrace_script/src/main.rs index 30c795b..1574ad2 100644 --- a/entrace_script/src/main.rs +++ b/entrace_script/src/main.rs @@ -1,3 +1,4 @@ +use entrace_core::LogProvider; use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc, sync::Arc}; use clap::Parser; @@ -17,7 +18,7 @@ fn main() -> anyhow::Result<()> { let Args { lua_file, trace_file } = Args::parse(); let trace = unsafe { entrace_core::load_trace( - trace_file, + &trace_file, entrace_core::LoadConfig { iht: IETLoadConfig { watch: FileWatchConfig::DontWatch, diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 1285cac..3b170ba 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -15,7 +15,7 @@ directories = "6.0.0" eframe = "0.33.0" egui = "0.33.0" egui_extras = { version = "0.33.0", features = ["svg"] } -entrace_core = { version = "0.1.1", path = "../entrace_core/" } +entrace_core = { version = "0.2.0", path = "../entrace_core/" } entrace_query = { version = "0.1.1", path = "../entrace_query/" } memchr = "2.7.5" mimalloc = "0.1.47" diff --git a/gui/src/app.rs b/gui/src/app.rs index 54f6a39..6dbc766 100644 --- a/gui/src/app.rs +++ b/gui/src/app.rs @@ -13,7 +13,7 @@ use egui::{ epaint::text::{FontInsert, InsertFontFamily}, }; use entrace_core::{ - IETLoadConfig, IETPresentationConfig, LoadConfig, + IETLoadConfig, IETPresentationConfig, LoadConfig, LogProvider, remote::{FileWatchConfig, NotifyExt}, }; use nucleo_matcher::{ @@ -155,7 +155,7 @@ impl App { }, }; let trace = time_print("loading trace", || unsafe { - entrace_core::load_trace(path, load_config) + entrace_core::load_trace(path.as_ref(), load_config) }); match trace { Ok(x) => { diff --git a/gui/src/connection_dialog.rs b/gui/src/connection_dialog.rs index 342391c..bbbc33d 100644 --- a/gui/src/connection_dialog.rs +++ b/gui/src/connection_dialog.rs @@ -7,7 +7,7 @@ use std::{ use egui::Context; use entrace_core::{ - IETPresentationConfig, + IETPresentationConfig, LogProviderImpl, remote::{IETEvent, RemoteLogProvider}, }; use tracing::info; @@ -80,7 +80,9 @@ pub fn connect_dialog(ctx: &Context, app: &mut App) { let meta_open = EnBitVec::repeat(false, 1); app.log_status = LogStatus::Ready(LogState { file_path: PathBuf::from(&dialog.connect_url), - trace_provider: Arc::new(RwLock::new(Box::new(provider))), + trace_provider: Arc::new(RwLock::new(LogProviderImpl::Remote( + provider, + ))), is_open, meta_open, locating_state: RefCell::new(LocatingState::None), diff --git a/gui/src/homepage.rs b/gui/src/homepage.rs index 98b6178..73ba076 100644 --- a/gui/src/homepage.rs +++ b/gui/src/homepage.rs @@ -1,10 +1,10 @@ use crate::{ - App, LevelRepr, LogStatus, TraceProvider, TraceReader, row_height, + App, LevelRepr, LogStatus, TraceReader, row_height, search::LocatingState, tree::{TreeContextMut, tree_view}, }; use egui::{CollapsingHeader, Color32, Response, RichText, ScrollArea, Ui, vec2}; -use entrace_core::display_error_context; +use entrace_core::{LogProvider, LogProviderImpl, display_error_context}; use std::{ cell::RefCell, sync::{Arc, RwLock}, @@ -24,7 +24,7 @@ impl SpanResponse { pub enum SpanContext<'a> { QueryResults { locating_state: &'a RefCell, - trace_provider: Arc>, + trace_provider: Arc>, }, } diff --git a/gui/src/log.rs b/gui/src/log.rs index 8f64c24..ff05c22 100644 --- a/gui/src/log.rs +++ b/gui/src/log.rs @@ -6,7 +6,7 @@ use std::{ }; use entrace_core::{ - LogProvider, display_error_context, + LogProvider, LogProviderImpl, display_error_context, remote::{IETEvent, Notify, NotifyExt}, }; use tracing::{info, trace}; @@ -36,11 +36,9 @@ impl Display for LogStatus { } } } -/// TODO: try to remove this box by making LogProvider Sized -pub type TraceProvider = Box; pub struct LogState { pub file_path: PathBuf, - pub trace_provider: Arc>, + pub trace_provider: Arc>, /// Used for culling. pub is_open: EnBitVec, pub meta_open: EnBitVec, diff --git a/gui/src/main.rs b/gui/src/main.rs index 9bc4cd6..c09a12f 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -1,5 +1,5 @@ use egui::{Color32, FontId, TextStyle, Theme, Ui}; -use entrace_core::LevelContainer; +use entrace_core::{LevelContainer, LogProviderImpl}; use mimalloc::MiMalloc; use std::{ sync::RwLockReadGuard, @@ -52,7 +52,7 @@ fn main() -> eframe::Result { ) } -type TraceReader<'a> = RwLockReadGuard<'a, TraceProvider>; +type TraceReader<'a> = RwLockReadGuard<'a, LogProviderImpl>; pub fn time(f: impl FnOnce() -> T) -> (Duration, T) { let start = Instant::now(); diff --git a/gui/src/search/mod.rs b/gui/src/search/mod.rs index 6b182cc..de8f886 100644 --- a/gui/src/search/mod.rs +++ b/gui/src/search/mod.rs @@ -13,11 +13,11 @@ use std::{ time::{Duration, Instant}, }; -use crate::{TraceProvider, search::query_window::PaginatedResults, spawn_task}; +use crate::{search::query_window::PaginatedResults, spawn_task}; use crossbeam::channel::Receiver; use egui::{Pos2, Rect}; -use entrace_core::LogProviderError; +use entrace_core::{LogProvider, LogProviderError, LogProviderImpl}; use entrace_query::{ QueryError, lua_api::{JoinCtx, LuaEvalState, setup_lua_on_arc_rwlock}, @@ -101,7 +101,7 @@ pub struct SearchState { pub query_timing: Vec, } impl SearchState { - pub fn new_query(&mut self, trace_provider: Arc>) { + pub fn new_query(&mut self, trace_provider: Arc>) { let (tx, rx) = crossbeam::channel::bounded(1); let new_id = self.last_id + 1; self.last_id += 1; @@ -254,7 +254,7 @@ impl LocatingState { } } impl LocatingState { - pub fn start_locating(target: u32, trace_provider: &Arc>) -> Self { + pub fn start_locating(target: u32, trace_provider: &Arc>) -> Self { let tc = trace_provider.clone(); let (tx, path_rx) = crossbeam::channel::bounded(1); spawn_task(move || { diff --git a/gui/src/tree.rs b/gui/src/tree.rs index 6111013..e33516c 100644 --- a/gui/src/tree.rs +++ b/gui/src/tree.rs @@ -7,7 +7,7 @@ use std::{ use egui::{ Color32, Rect, RichText, Sense, Shape, Stroke, Ui, UiBuilder, epaint::RectShape, pos2, vec2, }; -use entrace_core::{MetadataRefContainer, display_error_context}; +use entrace_core::{LogProvider, MetadataRefContainer, display_error_context}; use tracing::{debug, info, warn}; use crate::{ diff --git a/shell.nix b/shell.nix index 9b08fd2..a9f05ff 100644 --- a/shell.nix +++ b/shell.nix @@ -32,6 +32,7 @@ pkgs.mkShell { rustfmt-nightly pkgs.cargo-about pkgs.dioxus-cli + pkgs.cargo-semver-checks ]; preferLocalBuild = true; env.RUSTFLAGS = "-C link-arg=-fuse-ld=mold";