mirror of
https://codeberg.org/icewind/logsmash.git
synced 2026-06-03 10:04:12 +02:00
lazy histograms for groups list
This commit is contained in:
parent
2631696ddd
commit
06704ebc6a
4 changed files with 91 additions and 51 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -3,5 +3,5 @@ target
|
||||||
.env
|
.env
|
||||||
result
|
result
|
||||||
*.log
|
*.log
|
||||||
profile.json
|
profile.*
|
||||||
*.out.*
|
*.out.*
|
||||||
|
|
@ -10,25 +10,25 @@ use ratatui::prelude::{StatefulWidget, Widget};
|
||||||
use ratatui::text::Text;
|
use ratatui::text::Text;
|
||||||
use ratatui::widgets::{Cell, Paragraph, Row, Wrap};
|
use ratatui::widgets::{Cell, Paragraph, Row, Wrap};
|
||||||
|
|
||||||
pub struct LogsByIdentifier<'a> {
|
pub struct DistinctLogs<'a> {
|
||||||
lines: &'a [&'a LogLine<'a>],
|
lines: &'a [&'a LogLine<'a>],
|
||||||
filter: &'a Filter,
|
filter: &'a Filter,
|
||||||
grouping: DistinctLogGrouping,
|
grouping: DistinctLogGrouping,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logs_by_identifier<'a>(
|
pub fn distinct_logs<'a>(
|
||||||
lines: &'a [&'a LogLine<'a>],
|
lines: &'a [&'a LogLine<'a>],
|
||||||
filter: &'a Filter,
|
filter: &'a Filter,
|
||||||
grouping: DistinctLogGrouping,
|
grouping: DistinctLogGrouping,
|
||||||
) -> LogsByIdentifier<'a> {
|
) -> DistinctLogs<'a> {
|
||||||
LogsByIdentifier {
|
DistinctLogs {
|
||||||
lines,
|
lines,
|
||||||
filter,
|
filter,
|
||||||
grouping,
|
grouping,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatefulWidget for LogsByIdentifier<'_> {
|
impl StatefulWidget for DistinctLogs<'_> {
|
||||||
type State = ScrollbarTableState;
|
type State = ScrollbarTableState;
|
||||||
|
|
||||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State)
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State)
|
||||||
|
|
@ -1,20 +1,43 @@
|
||||||
use crate::app::Filter;
|
use crate::app::Filter;
|
||||||
use crate::grouping::{GroupingResult, GroupingUi, LogGrouping};
|
use crate::grouping::{GroupingResult, GroupingUi, LogGrouping};
|
||||||
use crate::ui::style::TABLE_HEADER_STYLE;
|
use crate::ui::style::TABLE_HEADER_STYLE;
|
||||||
use crate::ui::table::ScrollbarTable;
|
use crate::ui::table::{ScrollbarTable, ScrollbarTableState};
|
||||||
use ratatui::prelude::*;
|
use ratatui::prelude::*;
|
||||||
use ratatui::widgets::{Cell, Row};
|
use ratatui::widgets::{Cell, Row};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
pub fn grouping_list<'a>(
|
pub struct GroupingList<'a, 'b> {
|
||||||
items: &[LogGrouping<'a>],
|
items: &'b [LogGrouping<'a>],
|
||||||
ui: &GroupingUi,
|
ui: &'b GroupingUi,
|
||||||
time_range: RangeInclusive<OffsetDateTime>,
|
time_range: RangeInclusive<OffsetDateTime>,
|
||||||
filter: &Filter,
|
filter: &'b Filter,
|
||||||
) -> ScrollbarTable<'a> {
|
}
|
||||||
let header = ui
|
|
||||||
|
pub fn grouping_list<'a, 'b>(
|
||||||
|
items: &'b [LogGrouping<'a>],
|
||||||
|
ui: &'b GroupingUi,
|
||||||
|
time_range: RangeInclusive<OffsetDateTime>,
|
||||||
|
filter: &'b Filter,
|
||||||
|
) -> GroupingList<'a, 'b> {
|
||||||
|
GroupingList {
|
||||||
|
items,
|
||||||
|
ui,
|
||||||
|
time_range,
|
||||||
|
filter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StatefulWidget for GroupingList<'_, '_> {
|
||||||
|
type State = ScrollbarTableState;
|
||||||
|
|
||||||
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State)
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
let header = self
|
||||||
|
.ui
|
||||||
.header
|
.header
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
|
|
@ -27,26 +50,40 @@ pub fn grouping_list<'a>(
|
||||||
.style(TABLE_HEADER_STYLE)
|
.style(TABLE_HEADER_STYLE)
|
||||||
.height(1);
|
.height(1);
|
||||||
|
|
||||||
let items: Vec<Row<'a>> = items
|
let items: Vec<_> = self
|
||||||
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|result| result.matches(filter))
|
.filter(|result| result.matches(self.filter))
|
||||||
.map(|result| grouped_row(result, time_range.clone()))
|
.enumerate()
|
||||||
|
.map(|(i, result)| {
|
||||||
|
grouped_row(
|
||||||
|
result,
|
||||||
|
self.time_range.clone(),
|
||||||
|
i.abs_diff(state.selected()) < 100,
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
ScrollbarTable::new(
|
let table = ScrollbarTable::new(
|
||||||
items,
|
items,
|
||||||
ui.widths
|
self.ui
|
||||||
|
.widths
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.chain([Constraint::Length(10), Constraint::Min(10)]),
|
.chain([Constraint::Length(10), Constraint::Min(10)]),
|
||||||
)
|
)
|
||||||
.header(header)
|
.header(header);
|
||||||
|
|
||||||
|
table.render(area, buf, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn grouped_row<'a>(
|
fn grouped_row<'a>(
|
||||||
grouping: &LogGrouping<'a>,
|
grouping: &LogGrouping<'a>,
|
||||||
time_range: RangeInclusive<OffsetDateTime>,
|
time_range: RangeInclusive<OffsetDateTime>,
|
||||||
|
is_in_view: bool,
|
||||||
) -> Row<'a> {
|
) -> Row<'a> {
|
||||||
|
if is_in_view {
|
||||||
if let Some(match_result) = &grouping.result {
|
if let Some(match_result) = &grouping.result {
|
||||||
let grouping_columns = match_result.render();
|
let grouping_columns = match_result.render();
|
||||||
let columns = grouping_columns.chain([
|
let columns = grouping_columns.chain([
|
||||||
|
|
@ -63,4 +100,7 @@ fn grouped_row<'a>(
|
||||||
Text::from(grouping.count().to_string()),
|
Text::from(grouping.count().to_string()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Row::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::error::UiError;
|
use crate::error::UiError;
|
||||||
use crate::grouping::LogGrouping;
|
use crate::grouping::LogGrouping;
|
||||||
use crate::ui::by_identifier::logs_by_identifier;
|
use crate::ui::distinct_logs::distinct_logs;
|
||||||
use crate::ui::error_list::error_list;
|
use crate::ui::error_list::error_list;
|
||||||
use crate::ui::footer::footer;
|
use crate::ui::footer::footer;
|
||||||
use crate::ui::grouping_list::grouping_list;
|
use crate::ui::grouping_list::grouping_list;
|
||||||
|
|
@ -28,7 +28,7 @@ use std::io;
|
||||||
use std::io::stdout;
|
use std::io::stdout;
|
||||||
use std::panic::{set_hook, take_hook};
|
use std::panic::{set_hook, take_hook};
|
||||||
|
|
||||||
mod by_identifier;
|
mod distinct_logs;
|
||||||
mod error_list;
|
mod error_list;
|
||||||
mod footer;
|
mod footer;
|
||||||
mod grouping_list;
|
mod grouping_list;
|
||||||
|
|
@ -186,7 +186,7 @@ fn ui(frame: &mut Frame, app: &App, state: &mut UiState) {
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
frame.render_stateful_widget(
|
frame.render_stateful_widget(
|
||||||
logs_by_identifier(lines, filter, *grouping),
|
distinct_logs(lines, filter, *grouping),
|
||||||
layout[0].union(layout[1]),
|
layout[0].union(layout[1]),
|
||||||
table_state,
|
table_state,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue