mirror of
https://codeberg.org/icewind/logsmash.git
synced 2026-06-03 10:04:12 +02:00
group by user agent
This commit is contained in:
parent
181559d841
commit
cbdc59d591
3 changed files with 44 additions and 0 deletions
|
|
@ -3,12 +3,14 @@ mod remote;
|
|||
mod unique;
|
||||
mod url;
|
||||
mod user;
|
||||
mod useragent;
|
||||
|
||||
use crate::app::{Filter, LineSet};
|
||||
use crate::grouping::app::{AppGrouping, APP_GROUPING_UI};
|
||||
use crate::grouping::remote::{RemoteGrouping, REMOTE_GROUPING_UI};
|
||||
use crate::grouping::url::{UrlGrouping, URL_GROUPING_UI};
|
||||
use crate::grouping::user::{UserGrouping, USER_GROUPING_UI};
|
||||
use crate::grouping::useragent::{UserAgentGrouping, USER_AGENT_GROUPING_UI};
|
||||
use crate::logfile::LogLine;
|
||||
use crate::matcher::MatchResult;
|
||||
use crate::timegraph::{SparkLine, TimeGraph};
|
||||
|
|
@ -132,6 +134,7 @@ pub enum Groupings<'logs> {
|
|||
App(AppGrouping<'logs>),
|
||||
User(UserGrouping<'logs>),
|
||||
Remote(RemoteGrouping<'logs>),
|
||||
UserAgent(UserAgentGrouping<'logs>),
|
||||
}
|
||||
|
||||
impl<'logs> GroupingResult<'logs> for Groupings<'logs> {
|
||||
|
|
@ -142,6 +145,7 @@ impl<'logs> GroupingResult<'logs> for Groupings<'logs> {
|
|||
Groupings::App(r) => r.matches(filter),
|
||||
Groupings::User(r) => r.matches(filter),
|
||||
Groupings::Remote(r) => r.matches(filter),
|
||||
Groupings::UserAgent(r) => r.matches(filter),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,6 +158,7 @@ impl<'logs> GroupingResult<'logs> for Groupings<'logs> {
|
|||
Groupings::App(r) => Box::new(r.render()),
|
||||
Groupings::User(r) => Box::new(r.render()),
|
||||
Groupings::Remote(r) => Box::new(r.render()),
|
||||
Groupings::UserAgent(r) => Box::new(r.render()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -164,6 +169,7 @@ pub enum GroupingOptions {
|
|||
App,
|
||||
User,
|
||||
Remote,
|
||||
UserAgent,
|
||||
}
|
||||
|
||||
impl GroupingOptions {
|
||||
|
|
@ -173,6 +179,7 @@ impl GroupingOptions {
|
|||
GroupingOptions::App,
|
||||
GroupingOptions::User,
|
||||
GroupingOptions::Remote,
|
||||
GroupingOptions::UserAgent,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
|
@ -184,6 +191,7 @@ impl GroupingOptions {
|
|||
GroupingOptions::App => line.app.hash(&mut hasher),
|
||||
GroupingOptions::User => line.user.hash(&mut hasher),
|
||||
GroupingOptions::Remote => line.remote.hash(&mut hasher),
|
||||
GroupingOptions::UserAgent => line.user_agent.hash(&mut hasher),
|
||||
}
|
||||
hasher.finish()
|
||||
}
|
||||
|
|
@ -202,6 +210,9 @@ impl GroupingOptions {
|
|||
GroupingOptions::Remote => Groupings::Remote(RemoteGrouping {
|
||||
remote: line.remote.as_str(),
|
||||
}),
|
||||
GroupingOptions::UserAgent => Groupings::UserAgent(UserAgentGrouping {
|
||||
user_agent: line.user_agent.as_ref(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -211,6 +222,7 @@ impl GroupingOptions {
|
|||
GroupingOptions::App => "App",
|
||||
GroupingOptions::User => "User",
|
||||
GroupingOptions::Remote => "Remote",
|
||||
GroupingOptions::UserAgent => "User Agent",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,6 +232,7 @@ impl GroupingOptions {
|
|||
GroupingOptions::App => APP_GROUPING_UI,
|
||||
GroupingOptions::User => USER_GROUPING_UI,
|
||||
GroupingOptions::Remote => REMOTE_GROUPING_UI,
|
||||
GroupingOptions::UserAgent => USER_AGENT_GROUPING_UI,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
29
src/grouping/useragent.rs
Normal file
29
src/grouping/useragent.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use crate::app::Filter;
|
||||
use crate::grouping::{GroupingResult, GroupingUi};
|
||||
use ratatui::layout::{Alignment, Constraint};
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(PartialEq, Clone)]
|
||||
pub struct UserAgentGrouping<'a> {
|
||||
pub user_agent: &'a str,
|
||||
}
|
||||
|
||||
pub const USER_AGENT_GROUPING_UI: GroupingUi = GroupingUi {
|
||||
header: &[("User Agent", Alignment::Left)],
|
||||
widths: &[Constraint::Percentage(100)],
|
||||
};
|
||||
|
||||
impl<'a> GroupingResult<'a> for UserAgentGrouping<'a> {
|
||||
fn matches(&self, filter: &Filter) -> bool {
|
||||
if filter.is_empty() {
|
||||
return true;
|
||||
}
|
||||
filter
|
||||
.parts()
|
||||
.all(|filter_part| filter_part.is_match(self.user_agent))
|
||||
}
|
||||
|
||||
fn render(&self) -> impl Iterator<Item = Cow<'a, str>> {
|
||||
[self.user_agent.into()].into_iter()
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,8 @@ pub struct LogLine<'a> {
|
|||
pub message: Cow<'a, str>,
|
||||
pub exception: Option<Exception<'a>>,
|
||||
pub app: Cow<'a, str>,
|
||||
#[serde(rename = "userAgent")]
|
||||
pub user_agent: Cow<'a, str>,
|
||||
#[serde(with = "date")]
|
||||
pub time: OffsetDateTime,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue