1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
use crate::{
dlt::{LogLevel, MessageType},
parse::{
dlt_extended_header, dlt_standard_header, skip_till_after_next_storage_header,
validated_payload_length, DltParseError,
},
};
use nom::bytes::streaming::take;
use rustc_hash::FxHashMap;
use serde::Serialize;
pub fn dlt_statistic_row_info(
input: &[u8],
with_storage_header: bool,
) -> Result<(&[u8], StatisticRowInfo), DltParseError> {
let (after_storage_header, _) = if with_storage_header {
skip_till_after_next_storage_header(input)?
} else {
(input, 0)
};
let (after_storage_and_normal_header, header) = dlt_standard_header(after_storage_header)?;
let payload_length = match validated_payload_length(&header, input.len()) {
Ok(length) => length,
Err(_e) => {
return Ok((
after_storage_and_normal_header,
StatisticRowInfo {
app_id_context_id: None,
ecu_id: header.ecu_id,
level: None,
verbose: false,
},
));
}
};
if !header.has_extended_header {
let (after_message, _) =
take::<u16, &[u8], DltParseError>(payload_length)(after_storage_and_normal_header)?;
return Ok((
after_message,
StatisticRowInfo {
app_id_context_id: None,
ecu_id: header.ecu_id,
level: None,
verbose: false,
},
));
}
let (after_headers, extended_header) = dlt_extended_header(after_storage_and_normal_header)?;
let (after_message, _) = take::<u16, &[u8], DltParseError>(payload_length)(after_headers)?;
let level = match extended_header.message_type {
MessageType::Log(level) => Some(level),
_ => None,
};
Ok((
after_message,
StatisticRowInfo {
app_id_context_id: Some((extended_header.application_id, extended_header.context_id)),
ecu_id: header.ecu_id,
level,
verbose: extended_header.verbose,
},
))
}
#[derive(Serialize, Debug, Default)]
pub struct LevelDistribution {
pub non_log: usize,
pub log_fatal: usize,
pub log_error: usize,
pub log_warning: usize,
pub log_info: usize,
pub log_debug: usize,
pub log_verbose: usize,
pub log_invalid: usize,
}
impl LevelDistribution {
pub fn new(level: Option<LogLevel>) -> LevelDistribution {
let all_zero = Default::default();
match level {
None => LevelDistribution {
non_log: 1,
..all_zero
},
Some(LogLevel::Fatal) => LevelDistribution {
log_fatal: 1,
..all_zero
},
Some(LogLevel::Error) => LevelDistribution {
log_error: 1,
..all_zero
},
Some(LogLevel::Warn) => LevelDistribution {
log_warning: 1,
..all_zero
},
Some(LogLevel::Info) => LevelDistribution {
log_info: 1,
..all_zero
},
Some(LogLevel::Debug) => LevelDistribution {
log_debug: 1,
..all_zero
},
Some(LogLevel::Verbose) => LevelDistribution {
log_verbose: 1,
..all_zero
},
_ => LevelDistribution {
log_invalid: 1,
..all_zero
},
}
}
}
pub type IdMap = FxHashMap<String, LevelDistribution>;
#[derive(Serialize, Debug)]
pub struct StatisticInfo {
pub app_ids: Vec<(String, LevelDistribution)>,
pub context_ids: Vec<(String, LevelDistribution)>,
pub ecu_ids: Vec<(String, LevelDistribution)>,
pub contained_non_verbose: bool,
}
#[derive(Serialize, Debug)]
pub struct StatisticRowInfo {
pub app_id_context_id: Option<(String, String)>,
pub ecu_id: Option<String>,
pub level: Option<LogLevel>,
pub verbose: bool,
}