Skip to content

Commit c69c297

Browse files
committed
Add DLT-Statistics host-command for native-ui
1 parent be1afd6 commit c69c297

File tree

13 files changed

+458
-383
lines changed

13 files changed

+458
-383
lines changed

application/apps/indexer/gui/application/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ chrono-tz.workspace = true
3939
dirs.workspace = true
4040
serialport.workspace = true
4141
dlt-core.workspace = true
42-
lazy_static.workspace = true
4342
rustc-hash = "2.1"
4443

4544
#TODO: Replace env logger with log4rs

application/apps/indexer/gui/application/src/host/command.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub enum HostCommand {
3232
stream: StreamNames,
3333
parser: ParserNames,
3434
},
35+
DltStatistics(Box<DltStatisticsParam>),
3536
StartSession(Box<StartSessionParam>),
3637
CloseSessionSetup(Uuid),
3738
CloseMultiSetup(Uuid),
@@ -43,6 +44,12 @@ pub enum HostCommand {
4344
},
4445
}
4546

47+
#[derive(Debug, Clone)]
48+
pub struct DltStatisticsParam {
49+
pub session_setup_id: Uuid,
50+
pub source_paths: Vec<PathBuf>,
51+
}
52+
4653
#[derive(Debug, Clone)]
4754
pub struct StartSessionParam {
4855
pub parser: ParserConfig,
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
use dlt_core::{
2+
dlt::LogLevel,
3+
parse::DltParseError,
4+
read::DltMessageReader,
5+
statistics::{Statistic, StatisticCollector, collect_statistics},
6+
};
7+
use rustc_hash::{FxHashMap, FxHashSet};
8+
use std::{fs::File, path::PathBuf};
9+
10+
/// Collects the DLT statistics from the given source files.
11+
pub fn dlt_statistics(sources: Vec<PathBuf>) -> Result<DltStatistics, String> {
12+
let mut statistics = DltStatistics::default();
13+
14+
for source in sources {
15+
if let Ok(path) = source.clone().into_os_string().into_string()
16+
&& let Ok(file) = File::open(path)
17+
{
18+
let mut reader = DltMessageReader::new(file, true);
19+
if let Err(error) = collect_statistics(&mut reader, &mut statistics) {
20+
return Err(format!("{:?}: {}", source, error));
21+
}
22+
} else {
23+
return Err(format!("invalid source: {:?}", source));
24+
}
25+
}
26+
27+
Ok(statistics)
28+
}
29+
30+
/// The statistics-info of DLT files.
31+
#[derive(Debug, Default, Clone)]
32+
pub struct DltStatistics {
33+
counter: usize,
34+
pub total: LevelDistribution,
35+
pub app_ids: FxHashMap<String, LevelDistribution>,
36+
pub ctx_ids: FxHashMap<String, LevelDistribution>,
37+
pub ecu_ids: FxHashMap<String, LevelDistribution>,
38+
}
39+
40+
impl DltStatistics {
41+
pub fn count(&self) -> usize {
42+
self.app_ids.len() + self.ctx_ids.len() + self.ecu_ids.len()
43+
}
44+
}
45+
46+
/// The Level distribution of DLT messages.
47+
#[derive(Debug, Default, Clone)]
48+
pub struct LevelDistribution {
49+
pub fatal: FxHashSet<usize>,
50+
pub error: FxHashSet<usize>,
51+
pub warn: FxHashSet<usize>,
52+
pub info: FxHashSet<usize>,
53+
pub debug: FxHashSet<usize>,
54+
pub verbose: FxHashSet<usize>,
55+
pub none: FxHashSet<usize>,
56+
pub invalid: FxHashSet<usize>,
57+
}
58+
59+
impl LevelDistribution {
60+
pub fn count(&self) -> usize {
61+
self.fatal.len()
62+
+ self.error.len()
63+
+ self.warn.len()
64+
+ self.info.len()
65+
+ self.debug.len()
66+
+ self.verbose.len()
67+
+ self.none.len()
68+
+ self.invalid.len()
69+
}
70+
71+
pub fn values(&self) -> [usize; 8] {
72+
[
73+
self.fatal.len(),
74+
self.error.len(),
75+
self.warn.len(),
76+
self.info.len(),
77+
self.debug.len(),
78+
self.verbose.len(),
79+
self.none.len(),
80+
self.invalid.len(),
81+
]
82+
}
83+
84+
pub fn merge(&mut self, other: &LevelDistribution) -> &mut Self {
85+
self.fatal.extend(other.fatal.iter().copied());
86+
self.error.extend(other.error.iter().copied());
87+
self.warn.extend(other.warn.iter().copied());
88+
self.info.extend(other.info.iter().copied());
89+
self.debug.extend(other.debug.iter().copied());
90+
self.verbose.extend(other.verbose.iter().copied());
91+
self.none.extend(other.none.iter().copied());
92+
self.invalid.extend(other.invalid.iter().copied());
93+
self
94+
}
95+
96+
pub fn intersect(&mut self, other: &LevelDistribution) -> &mut Self {
97+
self.fatal.retain(|item| other.fatal.contains(item));
98+
self.error.retain(|item| other.error.contains(item));
99+
self.warn.retain(|item| other.warn.contains(item));
100+
self.info.retain(|item| other.info.contains(item));
101+
self.debug.retain(|item| other.debug.contains(item));
102+
self.verbose.retain(|item| other.verbose.contains(item));
103+
self.none.retain(|item| other.none.contains(item));
104+
self.invalid.retain(|item| other.invalid.contains(item));
105+
self
106+
}
107+
}
108+
109+
impl StatisticCollector for DltStatistics {
110+
fn collect_statistic(&mut self, statistic: Statistic) -> Result<(), DltParseError> {
111+
self.counter += 1;
112+
let msg = self.counter;
113+
114+
let level = statistic.log_level;
115+
add_for_level(&mut self.total, level, msg);
116+
117+
let header = statistic.standard_header;
118+
add_for_id(
119+
&mut self.ecu_ids,
120+
header.ecu_id.unwrap_or("NONE".to_string()),
121+
level,
122+
msg,
123+
);
124+
125+
if let Some(header) = statistic.extended_header {
126+
add_for_id(&mut self.app_ids, header.application_id, level, msg);
127+
add_for_id(&mut self.ctx_ids, header.context_id, level, msg);
128+
}
129+
130+
Ok(())
131+
}
132+
}
133+
134+
fn add_for_id(
135+
ids: &mut FxHashMap<String, LevelDistribution>,
136+
id: String,
137+
level: Option<LogLevel>,
138+
msg: usize,
139+
) {
140+
if let Some(levels) = ids.get_mut(&id) {
141+
add_for_level(levels, level, msg);
142+
} else {
143+
let mut levels = LevelDistribution::default();
144+
add_for_level(&mut levels, level, msg);
145+
ids.insert(id, levels);
146+
}
147+
}
148+
149+
fn add_for_level(levels: &mut LevelDistribution, level: Option<LogLevel>, msg: usize) {
150+
match level {
151+
None => {
152+
levels.none.insert(msg);
153+
}
154+
Some(LogLevel::Fatal) => {
155+
levels.fatal.insert(msg);
156+
}
157+
Some(LogLevel::Error) => {
158+
levels.error.insert(msg);
159+
}
160+
Some(LogLevel::Warn) => {
161+
levels.warn.insert(msg);
162+
}
163+
Some(LogLevel::Info) => {
164+
levels.info.insert(msg);
165+
}
166+
Some(LogLevel::Debug) => {
167+
levels.debug.insert(msg);
168+
}
169+
Some(LogLevel::Verbose) => {
170+
levels.verbose.insert(msg);
171+
}
172+
Some(LogLevel::Invalid(_)) => {
173+
levels.invalid.insert(msg);
174+
}
175+
}
176+
}

application/apps/indexer/gui/application/src/host/common/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod colors;
2+
pub mod dlt_stats;
23
pub mod file_utls;
34
pub mod parsers;
45
pub mod sources;

application/apps/indexer/gui/application/src/host/communication.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub struct ServiceHandle {
3434
}
3535

3636
/// Provide functions to send host messages and waking up the UI on them.
37-
#[derive(Debug)]
37+
#[derive(Debug, Clone)]
3838
pub struct ServiceSenders {
3939
message_tx: mpsc::Sender<HostMessage>,
4040
notification_tx: mpsc::Sender<AppNotification>,

application/apps/indexer/gui/application/src/host/message.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use uuid::Uuid;
22

33
use crate::{
4-
host::ui::{multi_setup::state::MultiFileState, session_setup::state::SessionSetupState},
4+
host::{
5+
common::dlt_stats::DltStatistics,
6+
ui::{multi_setup::state::MultiFileState, session_setup::state::SessionSetupState},
7+
},
58
session::InitSessionParams,
69
};
710

@@ -14,7 +17,11 @@ pub enum HostMessage {
1417
SessionSetupClosed { id: Uuid },
1518
/// Close multiple files setup with the provided id.
1619
MultiSetupClose { id: Uuid },
17-
20+
/// The collected DLT statistics on a file for a SessionSetup
21+
DltStatistics {
22+
setup_session_id: Uuid,
23+
statistics: Option<DltStatistics>,
24+
},
1825
/// A new session has been successfully created.
1926
SessionCreated {
2027
session_params: InitSessionParams,

0 commit comments

Comments
 (0)