inefficient date range

This commit is contained in:
2025-12-09 19:20:58 +01:00
parent 97caee37cc
commit b7f7aeeb9a
3 changed files with 106 additions and 11 deletions

View File

@@ -67,6 +67,9 @@ impl LogViewerApp {
case_sensitive: config.case_sensitive, case_sensitive: config.case_sensitive,
use_regex: config.use_regex, use_regex: config.use_regex,
history: config.search_history, history: config.search_history,
date_range_enabled: false,
date_from: String::new(),
date_to: String::new(),
}, },
indexing_state: IndexingState::new(), indexing_state: IndexingState::new(),
search_state: SearchState::new(), search_state: SearchState::new(),
@@ -111,6 +114,9 @@ impl LogViewerApp {
query: self.search_panel_state.query.clone(), query: self.search_panel_state.query.clone(),
case_sensitive: self.search_panel_state.case_sensitive, case_sensitive: self.search_panel_state.case_sensitive,
use_regex: self.search_panel_state.use_regex, use_regex: self.search_panel_state.use_regex,
date_range_enabled: self.search_panel_state.date_range_enabled,
date_from: self.search_panel_state.date_from.clone(),
date_to: self.search_panel_state.date_to.clone(),
}; };
let line_index = Arc::clone(&tab.line_index); let line_index = Arc::clone(&tab.line_index);
@@ -306,7 +312,8 @@ impl eframe::App for LogViewerApp {
} }
// Render filtered view with improved styling // Render filtered view with improved styling
let show_filtered = !self.search_panel_state.query.is_empty(); // Show filtered view if there's a query OR if date range is enabled
let show_filtered = !self.search_panel_state.query.is_empty() || self.search_panel_state.date_range_enabled;
let highlight_rules = self.highlight_manager.rules.clone(); let highlight_rules = self.highlight_manager.rules.clone();
let mut export_clicked = false; let mut export_clicked = false;

View File

@@ -43,6 +43,9 @@ pub struct SearchParams {
pub query: String, pub query: String,
pub case_sensitive: bool, pub case_sensitive: bool,
pub use_regex: bool, pub use_regex: bool,
pub date_range_enabled: bool,
pub date_from: String,
pub date_to: String,
} }
impl SearchParams { impl SearchParams {
@@ -99,6 +102,47 @@ pub fn start_search(
}); });
} }
fn find_date_range(
params: &SearchParams,
line_index: &LineIndex,
file_path: &Path,
) -> Option<(usize, usize)> {
if !params.date_range_enabled || params.date_from.is_empty() || params.date_to.is_empty() {
return None;
}
let file = File::open(file_path).ok()?;
let mut file_handle = BufReader::new(file);
let mut start_line = None;
let mut end_line = None;
// Find first line containing date_from text
for line_num in 0..line_index.total_lines {
if let Some(content) = line_index.read_line(&mut file_handle, line_num) {
if content.contains(&params.date_from) {
start_line = Some(line_num);
break;
}
}
}
// Find last line containing date_to text
for line_num in (0..line_index.total_lines).rev() {
if let Some(content) = line_index.read_line(&mut file_handle, line_num) {
if content.contains(&params.date_to) {
end_line = Some(line_num + 1); // +1 to include this line
break;
}
}
}
match (start_line, end_line) {
(Some(start), Some(end)) if start < end => Some((start, end)),
_ => None,
}
}
fn search_lines( fn search_lines(
params: &SearchParams, params: &SearchParams,
line_index: &LineIndex, line_index: &LineIndex,
@@ -110,17 +154,28 @@ fn search_lines(
return Vec::new(); return Vec::new();
} }
// Determine optimal chunk size based on total lines // Determine the line range to search (all lines or date range)
// Aim for enough chunks to utilize all cores, but not too many to avoid overhead let (search_start, search_end) = if let Some((start, end)) = find_date_range(params, line_index, file_path) {
let num_threads = rayon::current_num_threads(); (start, end)
let min_chunk_size = 1000; // Process at least 1000 lines per chunk } else {
let chunk_size = (total_lines / (num_threads * 4)).max(min_chunk_size); (0, total_lines)
};
// Split line numbers into chunks let lines_to_search = search_end - search_start;
let chunks: Vec<(usize, usize)> = (0..total_lines) if lines_to_search == 0 {
return Vec::new();
}
// Determine optimal chunk size based on lines to search
let num_threads = rayon::current_num_threads();
let min_chunk_size = 1000;
let chunk_size = (lines_to_search / (num_threads * 4)).max(min_chunk_size);
// Split line numbers into chunks within the search range
let chunks: Vec<(usize, usize)> = (search_start..search_end)
.step_by(chunk_size) .step_by(chunk_size)
.map(|start| { .map(|start| {
let end = (start + chunk_size).min(total_lines); let end = (start + chunk_size).min(search_end);
(start, end) (start, end)
}) })
.collect(); .collect();
@@ -143,7 +198,14 @@ fn search_lines(
// Process each line - only store line numbers, not content // Process each line - only store line numbers, not content
for (line_number, content) in lines { for (line_number, content) in lines {
if params.matches_line(&content, &regex_matcher) { // If date range is enabled and query is empty, include all lines in range
let should_include = if params.date_range_enabled && params.query.is_empty() {
true
} else {
params.matches_line(&content, &regex_matcher)
};
if should_include {
chunk_results.push(FilteredLine { line_number }); chunk_results.push(FilteredLine { line_number });
} }
} }

View File

@@ -8,6 +8,9 @@ pub struct SearchPanelState {
pub case_sensitive: bool, pub case_sensitive: bool,
pub use_regex: bool, pub use_regex: bool,
pub history: Vec<String>, pub history: Vec<String>,
pub date_range_enabled: bool,
pub date_from: String,
pub date_to: String,
} }
pub struct SearchPanelActions { pub struct SearchPanelActions {
@@ -75,8 +78,9 @@ pub fn render_search_panel(
.checkbox(&mut state.case_sensitive, "Case sensitive") .checkbox(&mut state.case_sensitive, "Case sensitive")
.changed(); .changed();
let regex_changed = ui.checkbox(&mut state.use_regex, "Regex").changed(); let regex_changed = ui.checkbox(&mut state.use_regex, "Regex").changed();
let date_range_changed = ui.checkbox(&mut state.date_range_enabled, "Date range").changed();
if case_changed || regex_changed { if case_changed || regex_changed || date_range_changed {
actions.config_changed = true; actions.config_changed = true;
} }
@@ -103,6 +107,28 @@ pub fn render_search_panel(
} }
}); });
// Date range fields (show when date_range_enabled is true)
if state.date_range_enabled {
ui.add_space(6.0);
ui.horizontal(|ui| {
ui.label("From:");
ui.add(
egui::TextEdit::singleline(&mut state.date_from)
.desired_width(180.0)
.hint_text("2025-01-01 00:00:00")
);
ui.add_space(8.0);
ui.label("To:");
ui.add(
egui::TextEdit::singleline(&mut state.date_to)
.desired_width(180.0)
.hint_text("2025-01-01 01:00:00")
);
});
}
// Progress bar // Progress bar
if search_state.is_searching() { if search_state.is_searching() {
ui.add_space(6.0); ui.add_space(6.0);