mirror of
https://codeberg.org/icewind/logsmash.git
synced 2026-06-03 10:04:12 +02:00
lazy histograms
This commit is contained in:
parent
2f3e2325df
commit
8299a90578
4 changed files with 56 additions and 37 deletions
77
src/app.rs
77
src/app.rs
|
|
@ -3,6 +3,7 @@ use crate::matcher::MatchResult;
|
||||||
use crate::timegraph::TimeGraph;
|
use crate::timegraph::TimeGraph;
|
||||||
use logsmash_data::{LoggingStatementWithPathPrefix, StatementList};
|
use logsmash_data::{LoggingStatementWithPathPrefix, StatementList};
|
||||||
use regex::{escape, Regex, RegexBuilder};
|
use regex::{escape, Regex, RegexBuilder};
|
||||||
|
use std::cell::OnceCell;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
|
@ -42,39 +43,46 @@ impl<'a> App<'a> {
|
||||||
pub struct LogMatch {
|
pub struct LogMatch {
|
||||||
pub result: Option<MatchResult>,
|
pub result: Option<MatchResult>,
|
||||||
pub count: usize,
|
pub count: usize,
|
||||||
pub histogram: TimeGraph,
|
pub histogram: OnceCell<TimeGraph>,
|
||||||
pub sparkline: String,
|
pub sparkline: OnceCell<String>,
|
||||||
pub all: GroupedLines,
|
pub all: GroupedLines,
|
||||||
pub grouped: Vec<GroupedLines>,
|
pub grouped: Vec<GroupedLines>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LogMatch {
|
impl LogMatch {
|
||||||
pub fn new(result: Option<MatchResult>, lines: Vec<usize>, all_lines: &[LogLine]) -> Self {
|
pub fn new(result: Option<MatchResult>, lines: Vec<usize>, all_lines: &[LogLine]) -> Self {
|
||||||
let min_time = all_lines[0].time;
|
|
||||||
let max_time = all_lines.last().unwrap().time;
|
|
||||||
let mut histogram = TimeGraph::new(min_time, max_time);
|
|
||||||
for line in lines.iter().map(|line| &all_lines[*line]) {
|
|
||||||
histogram.add(line.time);
|
|
||||||
}
|
|
||||||
let count = lines.len();
|
let count = lines.len();
|
||||||
let grouped = group_lines(all_lines, lines.iter().copied());
|
let grouped = group_lines(all_lines, lines.iter().copied());
|
||||||
let sparkline = histogram.sparkline::<10>();
|
let all = GroupedLines::new(lines);
|
||||||
let all = GroupedLines {
|
|
||||||
sparkline: sparkline.clone(),
|
|
||||||
histogram: histogram.clone(),
|
|
||||||
lines,
|
|
||||||
};
|
|
||||||
|
|
||||||
LogMatch {
|
LogMatch {
|
||||||
result,
|
result,
|
||||||
count,
|
count,
|
||||||
histogram,
|
histogram: OnceCell::new(),
|
||||||
sparkline,
|
sparkline: OnceCell::new(),
|
||||||
grouped,
|
grouped,
|
||||||
all,
|
all,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sparkline(&self, app: &App) -> &str {
|
||||||
|
self.sparkline
|
||||||
|
.get_or_init(|| self.histogram(app).sparkline::<10>())
|
||||||
|
.as_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn histogram(&self, app: &App) -> &TimeGraph {
|
||||||
|
self.histogram.get_or_init(|| {
|
||||||
|
let min_time = app.lines[0].time;
|
||||||
|
let max_time = app.lines.last().unwrap().time;
|
||||||
|
let mut histogram = TimeGraph::new(min_time, max_time);
|
||||||
|
for line in self.all.lines.iter().map(|line| &app.lines[*line]) {
|
||||||
|
histogram.add(line.time);
|
||||||
|
}
|
||||||
|
histogram
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn row_count(&self) -> usize {
|
pub fn row_count(&self) -> usize {
|
||||||
self.result.as_ref().map(|res| res.len()).unwrap_or(1)
|
self.result.as_ref().map(|res| res.len()).unwrap_or(1)
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +134,7 @@ fn group_lines<I: Iterator<Item = usize>>(all_lines: &[LogLine], indices: I) ->
|
||||||
|
|
||||||
let mut list: Vec<_> = map
|
let mut list: Vec<_> = map
|
||||||
.into_values()
|
.into_values()
|
||||||
.map(|lines| GroupedLines::new(lines, all_lines))
|
.map(|lines| GroupedLines::new(lines))
|
||||||
.collect();
|
.collect();
|
||||||
list.sort_by_key(|list| list.len());
|
list.sort_by_key(|list| list.len());
|
||||||
list.reverse();
|
list.reverse();
|
||||||
|
|
@ -135,26 +143,37 @@ fn group_lines<I: Iterator<Item = usize>>(all_lines: &[LogLine], indices: I) ->
|
||||||
|
|
||||||
pub struct GroupedLines {
|
pub struct GroupedLines {
|
||||||
pub lines: Vec<usize>,
|
pub lines: Vec<usize>,
|
||||||
pub histogram: TimeGraph,
|
pub histogram: OnceCell<TimeGraph>,
|
||||||
pub sparkline: String,
|
pub sparkline: OnceCell<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GroupedLines {
|
impl GroupedLines {
|
||||||
pub fn new(lines: Vec<usize>, all_lines: &[LogLine]) -> Self {
|
pub fn new(lines: Vec<usize>) -> Self {
|
||||||
let min_time = all_lines[0].time;
|
|
||||||
let max_time = all_lines.last().unwrap().time;
|
|
||||||
let mut histogram = TimeGraph::new(min_time, max_time);
|
|
||||||
for line in lines.iter().map(|line| &all_lines[*line]) {
|
|
||||||
histogram.add(line.time);
|
|
||||||
}
|
|
||||||
let sparkline = histogram.sparkline::<10>();
|
|
||||||
GroupedLines {
|
GroupedLines {
|
||||||
lines,
|
lines,
|
||||||
histogram,
|
histogram: OnceCell::new(),
|
||||||
sparkline,
|
sparkline: OnceCell::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sparkline(&self, app: &App) -> &str {
|
||||||
|
self.sparkline
|
||||||
|
.get_or_init(|| self.histogram(app).sparkline::<10>())
|
||||||
|
.as_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn histogram(&self, app: &App) -> &TimeGraph {
|
||||||
|
self.histogram.get_or_init(|| {
|
||||||
|
let min_time = app.lines[0].time;
|
||||||
|
let max_time = app.lines.last().unwrap().time;
|
||||||
|
let mut histogram = TimeGraph::new(min_time, max_time);
|
||||||
|
for line in self.lines.iter().map(|line| &app.lines[*line]) {
|
||||||
|
histogram.add(line.time);
|
||||||
|
}
|
||||||
|
histogram
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.lines.len()
|
self.lines.len()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ fn log_row<'a>(result: &'a LogMatch, app: &'a App, name: &'static str) -> Row<'a
|
||||||
Text::from(message),
|
Text::from(message),
|
||||||
Text::from(paths),
|
Text::from(paths),
|
||||||
Text::from(lines).alignment(Alignment::Right),
|
Text::from(lines).alignment(Alignment::Right),
|
||||||
Text::from(result.sparkline.as_str()),
|
Text::from(result.sparkline(app)),
|
||||||
Text::from(result.count().to_string()),
|
Text::from(result.count().to_string()),
|
||||||
])
|
])
|
||||||
.height(match_result.len() as u16)
|
.height(match_result.len() as u16)
|
||||||
|
|
@ -74,7 +74,7 @@ fn log_row<'a>(result: &'a LogMatch, app: &'a App, name: &'static str) -> Row<'a
|
||||||
Text::from(name),
|
Text::from(name),
|
||||||
Text::from(""),
|
Text::from(""),
|
||||||
Text::from(""),
|
Text::from(""),
|
||||||
Text::from(result.sparkline.as_str()),
|
Text::from(result.sparkline(app)),
|
||||||
Text::from(result.count().to_string()),
|
Text::from(result.count().to_string()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,12 +112,12 @@ fn ui(frame: &mut Frame, app: &App, state: &mut UiState) {
|
||||||
}) => {
|
}) => {
|
||||||
let selected = table_state.selected();
|
let selected = table_state.selected();
|
||||||
let histogram = if selected == 0 {
|
let histogram = if selected == 0 {
|
||||||
&app.all.histogram
|
app.all.histogram(app)
|
||||||
} else if selected < app.matches.len() + 1 {
|
} else if selected < app.matches.len() + 1 {
|
||||||
let log_match = &app.matches[selected - 1];
|
let log_match = &app.matches[selected - 1];
|
||||||
&log_match.histogram
|
log_match.histogram(app)
|
||||||
} else {
|
} else {
|
||||||
&app.unmatched.histogram
|
app.unmatched.histogram(app)
|
||||||
};
|
};
|
||||||
|
|
||||||
frame.render_widget(UiHistogram::new(histogram), layout[0]);
|
frame.render_widget(UiHistogram::new(histogram), layout[0]);
|
||||||
|
|
@ -137,7 +137,7 @@ fn ui(frame: &mut Frame, app: &App, state: &mut UiState) {
|
||||||
&result.grouped[selected - 1]
|
&result.grouped[selected - 1]
|
||||||
};
|
};
|
||||||
|
|
||||||
frame.render_widget(UiHistogram::new(&selected_group.histogram), layout[0]);
|
frame.render_widget(UiHistogram::new(&selected_group.histogram(app)), layout[0]);
|
||||||
frame.render_stateful_widget(
|
frame.render_stateful_widget(
|
||||||
grouped_lines(app, result, filter),
|
grouped_lines(app, result, filter),
|
||||||
layout[1],
|
layout[1],
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ pub fn grouped_lines<'a>(
|
||||||
Text::from("All lines"),
|
Text::from("All lines"),
|
||||||
Text::from(""),
|
Text::from(""),
|
||||||
Text::from(""),
|
Text::from(""),
|
||||||
Text::from(log_match.sparkline.as_str()),
|
Text::from(log_match.sparkline(app)),
|
||||||
Text::from(log_match.count().to_string()),
|
Text::from(log_match.count().to_string()),
|
||||||
]))
|
]))
|
||||||
.chain(
|
.chain(
|
||||||
|
|
@ -58,7 +58,7 @@ fn group_row<'a>(app: &'a App, group: &'a GroupedLines) -> Row<'a> {
|
||||||
Text::from(line.level.as_str()),
|
Text::from(line.level.as_str()),
|
||||||
Text::from(line.app.as_ref()),
|
Text::from(line.app.as_ref()),
|
||||||
Text::from(line.display()),
|
Text::from(line.display()),
|
||||||
Text::from(group.sparkline.as_str()),
|
Text::from(group.sparkline(app)),
|
||||||
Text::from(group.len().to_string()),
|
Text::from(group.len().to_string()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue