mirror of
https://codeberg.org/icewind/logsmash.git
synced 2026-06-03 18:14:11 +02:00
grouped lines
This commit is contained in:
parent
13f1f31dd8
commit
483bb5691d
12 changed files with 158 additions and 92 deletions
|
|
@ -19,7 +19,7 @@ pub fn footer(app: &App, page: UiPage) -> Table {
|
|||
Table::new(
|
||||
[Row::new([
|
||||
help(page).to_string(),
|
||||
format!("{} unmatched items", app.unmatched.len()),
|
||||
format!("{} unmatched items", app.unmatched.lines.len()),
|
||||
format!("{} parse errors", app.error_count),
|
||||
])],
|
||||
widths,
|
||||
|
|
|
|||
|
|
@ -29,28 +29,16 @@ pub fn match_list(app: &App) -> Table {
|
|||
Constraint::Min(10),
|
||||
];
|
||||
|
||||
let all = Row::new([
|
||||
Text::from("All lines"),
|
||||
Text::from(String::new()),
|
||||
Text::from(String::new()).alignment(Alignment::Right),
|
||||
Text::from(sparkline(&app.histogram.counts(10))),
|
||||
Text::from(app.lines.len().to_string()),
|
||||
]);
|
||||
let unmatched = if app.unmatched.is_empty() {
|
||||
let all = log_row(&app.all, &app, "All lines");
|
||||
let unmatched = if app.unmatched.lines.is_empty() {
|
||||
Either::Right(empty())
|
||||
} else {
|
||||
Either::Left(once(Row::new([
|
||||
Text::from("Unmatched lines"),
|
||||
Text::from(String::new()),
|
||||
Text::from(String::new()).alignment(Alignment::Right),
|
||||
Text::from(sparkline(&app.unmatched_histogram.counts(10))),
|
||||
Text::from(app.unmatched.len().to_string()),
|
||||
])))
|
||||
Either::Left(once(log_row(&app.unmatched, &app, "Unmatched lines")))
|
||||
};
|
||||
|
||||
Table::new(
|
||||
once(all)
|
||||
.chain(app.matches.iter().map(|result| log_row(result, app)))
|
||||
.chain(app.matches.iter().map(|result| log_row(result, app, "")))
|
||||
.chain(unmatched),
|
||||
widths,
|
||||
)
|
||||
|
|
@ -59,22 +47,32 @@ pub fn match_list(app: &App) -> Table {
|
|||
.highlight_spacing(HighlightSpacing::Always)
|
||||
}
|
||||
|
||||
fn log_row<'a>(result: &LogMatch, app: &'a App) -> Row<'a> {
|
||||
let mut message = String::new();
|
||||
let mut paths = String::new();
|
||||
let mut lines = String::new();
|
||||
for index in result.result.iter() {
|
||||
let statement = app.log_statements.get(index).expect("invalid match index");
|
||||
writeln!(&mut message, "{}", statement.message()).unwrap();
|
||||
writeln!(&mut paths, "{}", statement.path()).unwrap();
|
||||
writeln!(&mut lines, "{}", statement.line).unwrap();
|
||||
fn log_row<'a>(result: &LogMatch, app: &'a App, name: &'static str) -> Row<'a> {
|
||||
if let Some(match_result) = &result.result {
|
||||
let mut message = String::new();
|
||||
let mut paths = String::new();
|
||||
let mut lines = String::new();
|
||||
for index in match_result.iter() {
|
||||
let statement = app.log_statements.get(index).expect("invalid match index");
|
||||
writeln!(&mut message, "{}", statement.message()).unwrap();
|
||||
writeln!(&mut paths, "{}", statement.path()).unwrap();
|
||||
writeln!(&mut lines, "{}", statement.line).unwrap();
|
||||
}
|
||||
Row::new([
|
||||
Text::from(message),
|
||||
Text::from(paths),
|
||||
Text::from(lines).alignment(Alignment::Right),
|
||||
Text::from(sparkline(&result.histogram.counts(10))),
|
||||
Text::from(result.count().to_string()),
|
||||
])
|
||||
.height(match_result.len() as u16)
|
||||
} else {
|
||||
Row::new([
|
||||
Text::from(name),
|
||||
Text::from(""),
|
||||
Text::from(""),
|
||||
Text::from(sparkline(&result.histogram.counts(10))),
|
||||
Text::from(result.count().to_string()),
|
||||
])
|
||||
}
|
||||
Row::new([
|
||||
Text::from(message),
|
||||
Text::from(paths),
|
||||
Text::from(lines).alignment(Alignment::Right),
|
||||
Text::from(sparkline(&result.histogram.counts(10))),
|
||||
Text::from(result.count().to_string()),
|
||||
])
|
||||
.height(result.result.len() as u16)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,12 +80,12 @@ fn ui(frame: &mut Frame, app: &App, state: &mut UiState) {
|
|||
UiState::MatchList { table_state } => {
|
||||
let selected = table_state.selected().unwrap_or(0);
|
||||
let histogram = if selected == 0 {
|
||||
&app.histogram
|
||||
&app.all.histogram
|
||||
} else if selected < app.matches.len() + 1 {
|
||||
let log_match = &app.matches[selected - 1];
|
||||
&log_match.histogram
|
||||
} else {
|
||||
&app.unmatched_histogram
|
||||
&app.unmatched.histogram
|
||||
};
|
||||
frame.render_widget(UiHistogram::new(histogram), layout[0]);
|
||||
frame.render_stateful_widget(match_list(app), layout[1], table_state);
|
||||
|
|
@ -96,19 +96,25 @@ fn ui(frame: &mut Frame, app: &App, state: &mut UiState) {
|
|||
table_state,
|
||||
} => {
|
||||
let log_match = &app.matches[*index];
|
||||
let lines = log_match.lines.iter().map(|i| &app.lines[*i]);
|
||||
|
||||
frame.render_widget(UiHistogram::new(&log_match.histogram), layout[0]);
|
||||
frame.render_stateful_widget(grouped_lines(lines), layout[1], table_state);
|
||||
let selected_group = &log_match.grouped[table_state.selected().unwrap_or_default()];
|
||||
frame.render_widget(UiHistogram::new(&selected_group.histogram), layout[0]);
|
||||
frame.render_stateful_widget(grouped_lines(app, log_match), layout[1], table_state);
|
||||
frame.render_widget(footer(app, page), layout[2]);
|
||||
}
|
||||
UiState::All { table_state } => {
|
||||
frame.render_stateful_widget(grouped_lines(app.lines.iter()), layout[1], table_state);
|
||||
let selected_group = &app.all.grouped[table_state.selected().unwrap_or_default()];
|
||||
frame.render_widget(UiHistogram::new(&selected_group.histogram), layout[0]);
|
||||
frame.render_stateful_widget(grouped_lines(app, &app.all), layout[1], table_state);
|
||||
frame.render_widget(footer(app, page), layout[2]);
|
||||
}
|
||||
UiState::Unmatched { table_state } => {
|
||||
let lines = app.unmatched.iter().map(|i| &app.lines[*i]);
|
||||
frame.render_stateful_widget(grouped_lines(lines), layout[1], table_state);
|
||||
let selected_group = &app.unmatched.grouped[table_state.selected().unwrap_or_default()];
|
||||
frame.render_widget(UiHistogram::new(&selected_group.histogram), layout[0]);
|
||||
frame.render_stateful_widget(
|
||||
grouped_lines(app, &app.unmatched),
|
||||
layout[1],
|
||||
table_state,
|
||||
);
|
||||
frame.render_widget(footer(app, page), layout[2]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,47 @@
|
|||
use crate::logline::LogLine;
|
||||
use crate::ui::style::{TABLE_HEADER_STYLE, TABLE_SELECTED_STYLE, TIME_FORMAT};
|
||||
use crate::app::{App, GroupedLines, LogMatch};
|
||||
use crate::ui::histogram::sparkline;
|
||||
use crate::ui::style::{TABLE_HEADER_STYLE, TABLE_SELECTED_STYLE};
|
||||
use ratatui::layout::Constraint;
|
||||
use ratatui::text::Text;
|
||||
use ratatui::widgets::{Cell, HighlightSpacing, Row, Table};
|
||||
use time::format_description::well_known::Iso8601;
|
||||
|
||||
pub fn grouped_lines<'a, I: Iterator<Item = &'a LogLine> + 'a>(lines: I) -> Table<'a> {
|
||||
let header = ["Level", "App", "Message", "Date"]
|
||||
.into_iter()
|
||||
.map(Cell::from)
|
||||
.collect::<Row>()
|
||||
.style(TABLE_HEADER_STYLE)
|
||||
.height(1);
|
||||
pub fn grouped_lines(app: &App, log_match: &LogMatch) -> Table<'static> {
|
||||
let grouped = &log_match.grouped;
|
||||
let header = [
|
||||
Text::from("Level"),
|
||||
Text::from("App"),
|
||||
Text::from("Message"),
|
||||
Text::from("Time"),
|
||||
Text::from("Count"),
|
||||
]
|
||||
.into_iter()
|
||||
.map(Cell::from)
|
||||
.collect::<Row>()
|
||||
.style(TABLE_HEADER_STYLE)
|
||||
.height(1);
|
||||
|
||||
let widths = [
|
||||
Constraint::Min(10),
|
||||
Constraint::Min(20),
|
||||
Constraint::Percentage(100),
|
||||
Constraint::Min(30),
|
||||
Constraint::Length(10),
|
||||
Constraint::Min(10),
|
||||
];
|
||||
let table = Table::new(lines.map(|line| log_row(line)), widths)
|
||||
let table = Table::new(grouped.iter().map(|group| group_row(app, group)), widths)
|
||||
.header(header)
|
||||
.highlight_style(TABLE_SELECTED_STYLE)
|
||||
.highlight_spacing(HighlightSpacing::Always);
|
||||
table
|
||||
}
|
||||
|
||||
fn log_row(line: &LogLine) -> Row {
|
||||
fn group_row(app: &App, group: &GroupedLines) -> Row<'static> {
|
||||
let line = &app.lines[group.lines[0]];
|
||||
|
||||
Row::new([
|
||||
line.level.as_str().to_string(),
|
||||
line.app.to_string(),
|
||||
line.message.clone(),
|
||||
line.time.format(&Iso8601::<TIME_FORMAT>).unwrap(),
|
||||
sparkline(&group.histogram.counts(10)),
|
||||
group.len().to_string(),
|
||||
])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ impl UiState {
|
|||
fn table_count(&self, app: &App) -> usize {
|
||||
match self {
|
||||
UiState::MatchList { .. } => app.match_lines(),
|
||||
UiState::Match { selected, .. } => app.matches[*selected].count(),
|
||||
UiState::All { .. } => app.lines.len(),
|
||||
UiState::Unmatched { .. } => app.unmatched.len(),
|
||||
UiState::Match { selected, .. } => app.matches[*selected].grouped.len(),
|
||||
UiState::All { .. } => app.all.grouped.len(),
|
||||
UiState::Unmatched { .. } => app.unmatched.grouped.len(),
|
||||
UiState::Quit => 0,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue