mirror of
https://codeberg.org/icewind/logsmash.git
synced 2026-06-03 10:04:12 +02:00
remove logging statement indirection
This commit is contained in:
parent
7dfbbddde6
commit
ea695e8460
8 changed files with 120 additions and 126 deletions
|
|
@ -24,15 +24,11 @@ impl StatementList {
|
||||||
StatementList { statements }
|
StatementList { statements }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(
|
pub fn iter(&self) -> impl Iterator<Item = LoggingStatementWithPathPrefix> + Send + '_ {
|
||||||
&self,
|
self.statements.iter().copied().flat_map(|(prefix, list)| {
|
||||||
) -> impl Iterator<Item = (LogStatementIndex, &'static LoggingStatement)> + Send + '_ {
|
list.iter()
|
||||||
self.statements
|
.map(|statement| statement.with_path_prefix(prefix))
|
||||||
.iter()
|
})
|
||||||
.copied()
|
|
||||||
.flat_map(|(_, list)| list.iter())
|
|
||||||
.enumerate()
|
|
||||||
.map(|(index, statement)| (LogStatementIndex(index), statement))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, mut index: LogStatementIndex) -> Option<LoggingStatementWithPathPrefix> {
|
pub fn get(&self, mut index: LogStatementIndex) -> Option<LoggingStatementWithPathPrefix> {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Clone, Copy, Deserialize, Hash, PartialOrd, Ord, Eq)]
|
#[derive(Debug, Default, PartialEq, Clone, Copy, Deserialize, Hash, PartialOrd, Ord, Eq)]
|
||||||
#[serde(from = "i64")]
|
#[serde(from = "i64")]
|
||||||
|
|
@ -57,7 +59,7 @@ impl LogLevel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone, Eq, Ord)]
|
||||||
pub struct LoggingStatement {
|
pub struct LoggingStatement {
|
||||||
pub level: LogLevel,
|
pub level: LogLevel,
|
||||||
pub path: &'static str,
|
pub path: &'static str,
|
||||||
|
|
@ -68,24 +70,31 @@ pub struct LoggingStatement {
|
||||||
pub has_meaningful_message: bool,
|
pub has_meaningful_message: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for LoggingStatement {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
(self.path, self.line).partial_cmp(&(other.path, other.line))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for LoggingStatement {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
(self.path, self.line).hash(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LoggingStatement {
|
impl LoggingStatement {
|
||||||
pub fn with_path_prefix(&self, path_prefix: &'static str) -> LoggingStatementWithPathPrefix {
|
pub fn with_path_prefix(
|
||||||
|
&'static self,
|
||||||
|
path_prefix: &'static str,
|
||||||
|
) -> LoggingStatementWithPathPrefix {
|
||||||
LoggingStatementWithPathPrefix {
|
LoggingStatementWithPathPrefix {
|
||||||
level: self.level,
|
|
||||||
path_prefix,
|
path_prefix,
|
||||||
path: self.path,
|
statement: self,
|
||||||
line: self.line,
|
|
||||||
placeholders: self.placeholders,
|
|
||||||
exception: self.exception,
|
|
||||||
pattern: self.pattern,
|
|
||||||
has_meaningful_message: self.has_meaningful_message,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message(&self) -> impl Display + '_ {
|
pub fn message(&self) -> impl Display + '_ {
|
||||||
LoggingMessage {
|
LoggingMessage { message: &self }
|
||||||
message: self.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pattern_len(&self) -> usize {
|
pub fn pattern_len(&self) -> usize {
|
||||||
|
|
@ -93,50 +102,34 @@ impl LoggingStatement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone, Eq, Ord, PartialOrd, Hash)]
|
||||||
pub struct LoggingStatementWithPathPrefix {
|
pub struct LoggingStatementWithPathPrefix {
|
||||||
pub level: LogLevel,
|
pub statement: &'static LoggingStatement,
|
||||||
pub path_prefix: &'static str,
|
pub path_prefix: &'static str,
|
||||||
pub path: &'static str,
|
|
||||||
pub line: usize,
|
|
||||||
pub placeholders: &'static [&'static str],
|
|
||||||
pub exception: Option<&'static str>,
|
|
||||||
pub pattern: &'static str,
|
|
||||||
pub has_meaningful_message: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&LoggingStatementWithPathPrefix> for LoggingStatement {
|
|
||||||
fn from(value: &LoggingStatementWithPathPrefix) -> Self {
|
|
||||||
LoggingStatement {
|
|
||||||
level: value.level,
|
|
||||||
path: value.path,
|
|
||||||
line: value.line,
|
|
||||||
placeholders: value.placeholders,
|
|
||||||
exception: value.exception,
|
|
||||||
pattern: value.pattern,
|
|
||||||
has_meaningful_message: value.has_meaningful_message,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LoggingStatementWithPathPrefix {
|
impl LoggingStatementWithPathPrefix {
|
||||||
fn raw_message(&self) -> LoggingMessage {
|
fn raw_message(&self) -> LoggingMessage<'static> {
|
||||||
LoggingMessage {
|
LoggingMessage {
|
||||||
message: self.into(),
|
message: self.statement,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path(&self) -> impl Display {
|
pub fn path(&self) -> impl Display {
|
||||||
LoggingStatementPath {
|
LoggingStatementPath {
|
||||||
path_prefix: self.path_prefix,
|
path_prefix: self.path_prefix,
|
||||||
path: self.path,
|
path: self.statement.path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn line(&self) -> usize {
|
||||||
|
self.statement.line
|
||||||
|
}
|
||||||
|
|
||||||
pub fn message(&self) -> impl Display {
|
pub fn message(&self) -> impl Display {
|
||||||
LoggingStatementMessage {
|
LoggingStatementMessage {
|
||||||
message: self.raw_message(),
|
message: self.raw_message(),
|
||||||
exception: self.exception,
|
exception: self.statement.exception,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +146,7 @@ impl Display for LoggingStatementPath {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LoggingStatementMessage {
|
struct LoggingStatementMessage {
|
||||||
pub message: LoggingMessage,
|
pub message: LoggingMessage<'static>,
|
||||||
pub exception: Option<&'static str>,
|
pub exception: Option<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,16 +167,16 @@ impl Display for LoggingStatementWithPathPrefix {
|
||||||
"«{}» {} line {}",
|
"«{}» {} line {}",
|
||||||
self.raw_message(),
|
self.raw_message(),
|
||||||
self.path(),
|
self.path(),
|
||||||
self.line
|
self.statement.line
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LoggingMessage {
|
struct LoggingMessage<'a> {
|
||||||
message: LoggingStatement,
|
message: &'a LoggingStatement,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for LoggingMessage {
|
impl Display for LoggingMessage<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
if self.message.pattern.is_empty() {
|
if self.message.pattern.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
||||||
39
src/app.rs
39
src/app.rs
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::grouping::group_lines_by;
|
||||||
use crate::logfile::{LogFile, LogLine, LogLineNumber};
|
use crate::logfile::{LogFile, LogLine, LogLineNumber};
|
||||||
use crate::logs::ParsedLogs;
|
use crate::logs::ParsedLogs;
|
||||||
use crate::matcher::MatchResult;
|
use crate::matcher::MatchResult;
|
||||||
|
|
@ -6,7 +7,6 @@ use logsmash_data::{LoggingStatementWithPathPrefix, StatementList};
|
||||||
use regex::{escape, Regex, RegexBuilder};
|
use regex::{escape, Regex, RegexBuilder};
|
||||||
use serde_json::Error as JsonError;
|
use serde_json::Error as JsonError;
|
||||||
use std::cell::OnceCell;
|
use std::cell::OnceCell;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
|
|
@ -64,7 +64,7 @@ pub struct LogMatch<'logs> {
|
||||||
impl<'logs> LogMatch<'logs> {
|
impl<'logs> LogMatch<'logs> {
|
||||||
pub fn new(result: Option<MatchResult>, lines: Vec<&'logs LogLine<'logs>>) -> Self {
|
pub fn new(result: Option<MatchResult>, lines: Vec<&'logs LogLine<'logs>>) -> Self {
|
||||||
let count = lines.len();
|
let count = lines.len();
|
||||||
let grouped = group_lines(lines.iter().copied());
|
let grouped = group_lines_by(lines.iter().copied(), LogLine::identity);
|
||||||
let all = LineSet::new(lines);
|
let all = LineSet::new(lines);
|
||||||
|
|
||||||
LogMatch {
|
LogMatch {
|
||||||
|
|
@ -96,33 +96,31 @@ impl<'logs> LogMatch<'logs> {
|
||||||
}
|
}
|
||||||
|
|
||||||
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.count()).unwrap_or(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn statements<'a>(
|
pub fn statements<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
app: &'a App,
|
) -> impl Iterator<Item = &'a LoggingStatementWithPathPrefix> + use<'a> {
|
||||||
) -> impl Iterator<Item = LoggingStatementWithPathPrefix> + 'a {
|
self.result.iter().flat_map(|res| res.iter())
|
||||||
self.result
|
|
||||||
.iter()
|
|
||||||
.flat_map(|res| res.iter())
|
|
||||||
.filter_map(|index| app.log_statements.get(index))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn matches(&self, app: &App, filter: &Filter) -> bool {
|
pub fn matches(&self, filter: &Filter) -> bool {
|
||||||
if filter.is_empty() {
|
if filter.is_empty() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
self.statements(app).any(|statement| {
|
self.statements().any(|statement| {
|
||||||
filter.parts().all(|filter_part| {
|
filter.parts().all(|filter_part| {
|
||||||
filter_part.is_match(statement.pattern)
|
filter_part.is_match(statement.statement.pattern)
|
||||||
|| filter_part.is_match(statement.path)
|
|| filter_part.is_match(statement.statement.path)
|
||||||
|| filter_part.is_match(statement.path_prefix)
|
|| filter_part.is_match(statement.path_prefix)
|
||||||
|| statement
|
|| statement
|
||||||
|
.statement
|
||||||
.placeholders
|
.placeholders
|
||||||
.iter()
|
.iter()
|
||||||
.any(|placeholder| filter_part.is_match(placeholder))
|
.any(|placeholder| filter_part.is_match(placeholder))
|
||||||
|| statement
|
|| statement
|
||||||
|
.statement
|
||||||
.exception
|
.exception
|
||||||
.filter(|exception| filter_part.is_match(exception))
|
.filter(|exception| filter_part.is_match(exception))
|
||||||
.is_some()
|
.is_some()
|
||||||
|
|
@ -135,21 +133,6 @@ impl<'logs> LogMatch<'logs> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn group_lines<'logs, I: Iterator<Item = &'logs LogLine<'logs>>>(
|
|
||||||
indices: I,
|
|
||||||
) -> Vec<LineSet<'logs>> {
|
|
||||||
let mut map: BTreeMap<u64, Vec<&'logs LogLine<'logs>>> = BTreeMap::new();
|
|
||||||
|
|
||||||
for line in indices {
|
|
||||||
map.entry(line.identity()).or_default().push(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut list: Vec<_> = map.into_values().map(LineSet::new).collect();
|
|
||||||
list.sort_by_key(|list| list.len());
|
|
||||||
list.reverse();
|
|
||||||
list
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LineSet<'logs> {
|
pub struct LineSet<'logs> {
|
||||||
pub lines: Vec<&'logs LogLine<'logs>>,
|
pub lines: Vec<&'logs LogLine<'logs>>,
|
||||||
pub histogram: OnceCell<TimeGraph>,
|
pub histogram: OnceCell<TimeGraph>,
|
||||||
|
|
|
||||||
21
src/grouping.rs
Normal file
21
src/grouping.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
use crate::app::LineSet;
|
||||||
|
use crate::logfile::LogLine;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
pub fn group_lines_by<'logs, I, F, K>(indices: I, f: F) -> Vec<LineSet<'logs>>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = &'logs LogLine<'logs>>,
|
||||||
|
K: Ord,
|
||||||
|
F: Fn(&'logs LogLine<'logs>) -> K,
|
||||||
|
{
|
||||||
|
let mut map: BTreeMap<K, Vec<&'logs LogLine<'logs>>> = BTreeMap::new();
|
||||||
|
|
||||||
|
for line in indices {
|
||||||
|
map.entry(f(line)).or_default().push(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut list: Vec<_> = map.into_values().map(LineSet::new).collect();
|
||||||
|
list.sort_by_key(|list| list.len());
|
||||||
|
list.reverse();
|
||||||
|
list
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,7 @@ use std::sync::RwLock;
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod error;
|
mod error;
|
||||||
|
pub mod grouping;
|
||||||
mod logfile;
|
mod logfile;
|
||||||
mod logs;
|
mod logs;
|
||||||
mod matcher;
|
mod matcher;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::logfile::logline::{Exception, LogLine};
|
use crate::logfile::logline::{Exception, LogLine};
|
||||||
use crate::logfile::LineNumber;
|
use crate::logfile::LineNumber;
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
use logsmash_data::{LogLevel, LogStatementIndex, LoggingStatement, StatementList};
|
use logsmash_data::{LogLevel, LoggingStatementWithPathPrefix, StatementList};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
@ -13,22 +13,22 @@ pub struct LogMatch {
|
||||||
exception: Option<&'static str>,
|
exception: Option<&'static str>,
|
||||||
path: &'static str,
|
path: &'static str,
|
||||||
line: LineNumber,
|
line: LineNumber,
|
||||||
index: LogStatementIndex,
|
statement: LoggingStatementWithPathPrefix,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LogMatch {
|
impl LogMatch {
|
||||||
pub fn new(index: LogStatementIndex, statement: &LoggingStatement) -> LogMatch {
|
pub fn new(statement: LoggingStatementWithPathPrefix) -> LogMatch {
|
||||||
LogMatch {
|
LogMatch {
|
||||||
level: statement.level,
|
level: statement.statement.level,
|
||||||
pattern: if statement.has_meaningful_message {
|
pattern: if statement.statement.has_meaningful_message {
|
||||||
statement.pattern
|
statement.statement.pattern
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
},
|
},
|
||||||
exception: statement.exception,
|
exception: statement.statement.exception,
|
||||||
path: statement.path,
|
path: statement.statement.path,
|
||||||
line: statement.line.into(),
|
line: statement.statement.line.into(),
|
||||||
index,
|
statement,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,10 +44,7 @@ pub struct Matcher {
|
||||||
|
|
||||||
impl Matcher {
|
impl Matcher {
|
||||||
pub fn new(statements: &StatementList) -> Matcher {
|
pub fn new(statements: &StatementList) -> Matcher {
|
||||||
let mut matches: Vec<_> = statements
|
let mut matches: Vec<_> = statements.iter().map(LogMatch::new).collect();
|
||||||
.iter()
|
|
||||||
.map(|(index, statement)| LogMatch::new(index, statement))
|
|
||||||
.collect();
|
|
||||||
matches.sort_by(|a, b| {
|
matches.sort_by(|a, b| {
|
||||||
// sort first by level, then by longest pattern
|
// sort first by level, then by longest pattern
|
||||||
a.level
|
a.level
|
||||||
|
|
@ -106,13 +103,13 @@ impl Matcher {
|
||||||
best_length = log_match.pattern_len();
|
best_length = log_match.pattern_len();
|
||||||
best_match = Some(match best_match {
|
best_match = Some(match best_match {
|
||||||
Some(MatchResult::Single(res)) => {
|
Some(MatchResult::Single(res)) => {
|
||||||
MatchResult::List(vec![res, log_match.index])
|
MatchResult::List(vec![res, log_match.statement.clone()])
|
||||||
}
|
}
|
||||||
Some(MatchResult::List(mut list)) => {
|
Some(MatchResult::List(mut list)) => {
|
||||||
list.push(log_match.index);
|
list.push(log_match.statement.clone());
|
||||||
MatchResult::List(list)
|
MatchResult::List(list)
|
||||||
}
|
}
|
||||||
None => MatchResult::Single(log_match.index),
|
None => MatchResult::Single(log_match.statement.clone()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -123,13 +120,13 @@ impl Matcher {
|
||||||
best_match
|
best_match
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_exception(&self, exception: &Exception) -> Option<LogStatementIndex> {
|
fn match_exception(&self, exception: &Exception) -> Option<LoggingStatementWithPathPrefix> {
|
||||||
for log_match in self.matches.iter() {
|
for log_match in self.matches.iter() {
|
||||||
if log_match.line == exception.line
|
if log_match.line == exception.line
|
||||||
&& log_match.exception == Some(exception.exception.as_ref())
|
&& log_match.exception == Some(exception.exception.as_ref())
|
||||||
&& exception.file.ends_with(log_match.path)
|
&& exception.file.ends_with(log_match.path)
|
||||||
{
|
{
|
||||||
return Some(log_match.index);
|
return Some(log_match.statement.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
@ -148,8 +145,8 @@ pub fn match_single(pattern: &str, text: &str) -> bool {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq)]
|
#[derive(Debug, Clone, Eq)]
|
||||||
pub enum MatchResult {
|
pub enum MatchResult {
|
||||||
Single(LogStatementIndex),
|
Single(LoggingStatementWithPathPrefix),
|
||||||
List(Vec<LogStatementIndex>),
|
List(Vec<LoggingStatementWithPathPrefix>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for MatchResult {
|
impl PartialEq for MatchResult {
|
||||||
|
|
@ -182,30 +179,30 @@ impl Hash for MatchResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MatchResult {
|
impl MatchResult {
|
||||||
pub fn len(&self) -> usize {
|
pub fn iter(&self) -> impl Iterator<Item = &LoggingStatementWithPathPrefix> + '_ {
|
||||||
|
match self {
|
||||||
|
MatchResult::Single(statement) => Either::Left(once(statement)),
|
||||||
|
MatchResult::List(list) => Either::Right(list.iter()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn count(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
MatchResult::Single(_) => 1,
|
MatchResult::Single(_) => 1,
|
||||||
MatchResult::List(list) => list.len(),
|
MatchResult::List(list) => list.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = LogStatementIndex> + '_ {
|
impl From<LoggingStatementWithPathPrefix> for MatchResult {
|
||||||
match self {
|
fn from(value: LoggingStatementWithPathPrefix) -> Self {
|
||||||
MatchResult::Single(index) => Either::Left(once(*index)),
|
MatchResult::Single(value)
|
||||||
MatchResult::List(list) => Either::Right(list.iter().copied()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<usize> for MatchResult {
|
impl From<Vec<LoggingStatementWithPathPrefix>> for MatchResult {
|
||||||
fn from(value: usize) -> Self {
|
fn from(value: Vec<LoggingStatementWithPathPrefix>) -> Self {
|
||||||
MatchResult::Single(LogStatementIndex::from(value))
|
MatchResult::List(value)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Vec<usize>> for MatchResult {
|
|
||||||
fn from(value: Vec<usize>) -> Self {
|
|
||||||
MatchResult::List(value.into_iter().map(LogStatementIndex::from).collect())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -278,6 +275,7 @@ fn test_matcher() {
|
||||||
use crate::logfile::logline::Exception;
|
use crate::logfile::logline::Exception;
|
||||||
use crate::logfile::LogLineNumber;
|
use crate::logfile::LogLineNumber;
|
||||||
use crate::logs::LogIndex;
|
use crate::logs::LogIndex;
|
||||||
|
use logsmash_data::LoggingStatement;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tinystr::TinyAsciiStr;
|
use tinystr::TinyAsciiStr;
|
||||||
|
|
@ -357,7 +355,7 @@ fn test_matcher() {
|
||||||
|
|
||||||
let matcher = Matcher::new(&StatementList::new(vec![("", STATEMENTS)]));
|
let matcher = Matcher::new(&StatementList::new(vec![("", STATEMENTS)]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(MatchResult::from(0)),
|
Some(MatchResult::from(STATEMENTS[0].with_path_prefix(""))),
|
||||||
matcher.match_log(&LogLine {
|
matcher.match_log(&LogLine {
|
||||||
version: "29",
|
version: "29",
|
||||||
app: "core".into(),
|
app: "core".into(),
|
||||||
|
|
@ -367,7 +365,10 @@ fn test_matcher() {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(MatchResult::from(vec![3, 4])),
|
Some(MatchResult::from(vec![
|
||||||
|
STATEMENTS[3].with_path_prefix(""),
|
||||||
|
STATEMENTS[4].with_path_prefix("")
|
||||||
|
])),
|
||||||
matcher.match_log(&LogLine {
|
matcher.match_log(&LogLine {
|
||||||
version: "29",
|
version: "29",
|
||||||
app: "core".into(),
|
app: "core".into(),
|
||||||
|
|
@ -377,7 +378,7 @@ fn test_matcher() {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(MatchResult::from(1)),
|
Some(MatchResult::from(STATEMENTS[1].with_path_prefix(""))),
|
||||||
matcher.match_log(&LogLine {
|
matcher.match_log(&LogLine {
|
||||||
version: "29",
|
version: "29",
|
||||||
app: "core".into(),
|
app: "core".into(),
|
||||||
|
|
@ -397,7 +398,7 @@ fn test_matcher() {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(MatchResult::from(2)),
|
Some(MatchResult::from(STATEMENTS[2].with_path_prefix(""))),
|
||||||
matcher.match_log(
|
matcher.match_log(
|
||||||
&LogLine {
|
&LogLine {
|
||||||
version: "29",
|
version: "29",
|
||||||
|
|
@ -409,7 +410,7 @@ fn test_matcher() {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(MatchResult::from(4)),
|
Some(MatchResult::from(STATEMENTS[4].with_path_prefix(""))),
|
||||||
matcher.match_log(
|
matcher.match_log(
|
||||||
&LogLine {
|
&LogLine {
|
||||||
version: "29",
|
version: "29",
|
||||||
|
|
@ -427,7 +428,7 @@ fn test_matcher() {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(MatchResult::from(5)),
|
Some(MatchResult::from(STATEMENTS[5].with_path_prefix(""))),
|
||||||
matcher.match_log(&LogLine {
|
matcher.match_log(&LogLine {
|
||||||
version: "29",
|
version: "29",
|
||||||
app: "core".into(),
|
app: "core".into(),
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ pub fn match_list<'a>(app: &'a App<'a>, filter: &Filter) -> ScrollbarTable<'a> {
|
||||||
.chain(
|
.chain(
|
||||||
app.matches
|
app.matches
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|result| result.matches(app, filter))
|
.filter(|result| result.matches(filter))
|
||||||
.map(|result| log_row(result, app, "")),
|
.map(|result| log_row(result, app, "")),
|
||||||
)
|
)
|
||||||
.chain(unmatched),
|
.chain(unmatched),
|
||||||
|
|
@ -55,11 +55,10 @@ fn log_row<'a>(result: &'a LogMatch, app: &'a App, name: &'static str) -> Row<'a
|
||||||
let mut message = String::new();
|
let mut message = String::new();
|
||||||
let mut paths = String::new();
|
let mut paths = String::new();
|
||||||
let mut lines = String::new();
|
let mut lines = String::new();
|
||||||
for index in match_result.iter() {
|
for statement in match_result.iter() {
|
||||||
let statement = app.log_statements.get(index).expect("invalid match index");
|
|
||||||
writeln!(&mut message, "{}", statement.message()).ok();
|
writeln!(&mut message, "{}", statement.message()).ok();
|
||||||
writeln!(&mut paths, "{}", statement.path()).ok();
|
writeln!(&mut paths, "{}", statement.path()).ok();
|
||||||
writeln!(&mut lines, "{}", statement.line).ok();
|
writeln!(&mut lines, "{}", statement.line()).ok();
|
||||||
}
|
}
|
||||||
Row::new([
|
Row::new([
|
||||||
Text::from(message),
|
Text::from(message),
|
||||||
|
|
@ -68,7 +67,7 @@ fn log_row<'a>(result: &'a LogMatch, app: &'a App, name: &'static str) -> Row<'a
|
||||||
Text::from(result.sparkline(app)),
|
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.count() as u16)
|
||||||
} else {
|
} else {
|
||||||
Row::new([
|
Row::new([
|
||||||
Text::from(name),
|
Text::from(name),
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ impl<'a> MatchListState<'a> {
|
||||||
} else {
|
} else {
|
||||||
app.matches
|
app.matches
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|log_match| log_match.matches(app, &self.filter))
|
.filter(|log_match| log_match.matches(&self.filter))
|
||||||
.nth(selected - 1)
|
.nth(selected - 1)
|
||||||
.unwrap_or(&app.unmatched)
|
.unwrap_or(&app.unmatched)
|
||||||
}
|
}
|
||||||
|
|
@ -356,7 +356,7 @@ impl<'a> UiState<'a> {
|
||||||
let match_row_counts = app
|
let match_row_counts = app
|
||||||
.matches
|
.matches
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|m| m.matches(app, filter))
|
.filter(|m| m.matches(filter))
|
||||||
.map(|m| m.row_count());
|
.map(|m| m.row_count());
|
||||||
for (index, row_count) in once(1)
|
for (index, row_count) in once(1)
|
||||||
.chain(match_row_counts)
|
.chain(match_row_counts)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue