micromegas_tracing/
parsing.rs

1//! Manual parsing of dynamically sized events
2use anyhow::{Context, Result};
3use micromegas_transit::{
4    CustomReaderMap, InProcSerialize, LegacyDynString, UserDefinedType, advance_window,
5    parse_pod_instance, read_advance_string, read_consume_pod,
6    value::{Object, Value},
7};
8use std::{collections::HashMap, sync::Arc};
9
10use crate::property_set::PROPERTY_SET_DEP_TYPE_NAME;
11
12lazy_static::lazy_static! {
13    static ref TIME: Arc<String> = Arc::new("time".into());
14    static ref LEVEL: Arc<String> = Arc::new("level".into());
15    static ref TARGET: Arc<String> = Arc::new("target".into());
16    static ref MSG: Arc<String> = Arc::new("msg".into());
17    static ref DESC: Arc<String> = Arc::new("desc".into());
18    static ref PROPERTIES: Arc<String> = Arc::new("properties".into());
19}
20
21fn parse_log_string_event(
22    udt: &UserDefinedType,
23    _udts: &[UserDefinedType],
24    dependencies: &HashMap<u64, Value>,
25    mut object_window: &[u8],
26) -> Result<Value> {
27    let desc_id: u64 = read_consume_pod(&mut object_window);
28    let time: i64 = read_consume_pod(&mut object_window);
29    let msg = String::from_utf8(object_window.to_vec()).with_context(|| "parsing legacy string")?;
30    let desc = dependencies
31        .get(&desc_id)
32        .with_context(|| format!("desc member {desc_id} of LogStringEvent not found"))?;
33    let members = vec![
34        (TIME.clone(), Value::I64(time)),
35        (MSG.clone(), Value::String(Arc::new(msg))),
36        (DESC.clone(), desc.clone()),
37    ];
38    Ok(Value::Object(Arc::new(Object {
39        type_name: udt.name.clone(),
40        members,
41    })))
42}
43
44fn parse_log_string_event_v2(
45    udt: &UserDefinedType,
46    _udts: &[UserDefinedType],
47    dependencies: &HashMap<u64, Value>,
48    mut object_window: &[u8],
49) -> Result<Value> {
50    let desc_id: u64 = read_consume_pod(&mut object_window);
51    let time: i64 = read_consume_pod(&mut object_window);
52    let msg = read_advance_string(&mut object_window).with_context(|| "parsing string")?;
53    let desc: Value = dependencies
54        .get(&desc_id)
55        .with_context(|| format!("desc member {desc_id} of LogStringEvent not found"))?
56        .clone();
57    let members = vec![
58        (TIME.clone(), Value::I64(time)),
59        (MSG.clone(), Value::String(Arc::new(msg))),
60        (DESC.clone(), desc),
61    ];
62    Ok(Value::Object(Arc::new(Object {
63        type_name: udt.name.clone(),
64        members,
65    })))
66}
67
68fn parse_log_string_interop_event_v3(
69    udt: &UserDefinedType,
70    udts: &[UserDefinedType],
71    dependencies: &HashMap<u64, Value>,
72    mut object_window: &[u8],
73) -> Result<Value> {
74    let string_ref_metadata = udts
75        .iter()
76        .find(|t| *t.name == "StaticStringRef")
77        .with_context(
78            || "Can't parse log string interop event with no metadata for StaticStringRef",
79        )?;
80    let time: i64 = read_consume_pod(&mut object_window);
81    let level: u8 = read_consume_pod(&mut object_window);
82    let target = parse_pod_instance(
83        string_ref_metadata,
84        udts,
85        dependencies,
86        &object_window[0..string_ref_metadata.size],
87    )
88    .with_context(|| "parse_pod_instance")?;
89    object_window = advance_window(object_window, string_ref_metadata.size);
90    let msg = read_advance_string(&mut object_window)?;
91    let members = vec![
92        (TIME.clone(), Value::I64(time)),
93        (LEVEL.clone(), Value::U8(level)),
94        (TARGET.clone(), target),
95        (MSG.clone(), Value::String(Arc::new(msg))),
96    ];
97    Ok(Value::Object(Arc::new(Object {
98        type_name: udt.name.clone(),
99        members,
100    })))
101}
102
103fn parse_tagged_log_interop_event(
104    udt: &UserDefinedType,
105    udts: &[UserDefinedType],
106    dependencies: &HashMap<u64, Value>,
107    mut object_window: &[u8],
108) -> Result<Value> {
109    let string_ref_metadata = udts
110        .iter()
111        .find(|t| *t.name == "StaticStringRef")
112        .with_context(
113            || "Can't parse log string interop event with no metadata for StaticStringRef",
114        )?;
115    let time: i64 = read_consume_pod(&mut object_window);
116    let level: u8 = read_consume_pod(&mut object_window);
117    let target = parse_pod_instance(
118        string_ref_metadata,
119        udts,
120        dependencies,
121        &object_window[0..string_ref_metadata.size],
122    )
123    .with_context(|| "parse_pod_instance")?;
124    object_window = advance_window(object_window, string_ref_metadata.size);
125    let properties_id: u64 = read_consume_pod(&mut object_window);
126    let properties = dependencies
127        .get(&properties_id)
128        .with_context(|| "fetching properties in parse_tagged_log_interop_event")?
129        .clone();
130    let msg = read_advance_string(&mut object_window)?;
131    let members = vec![
132        (TIME.clone(), Value::I64(time)),
133        (LEVEL.clone(), Value::U8(level)),
134        (TARGET.clone(), target),
135        (PROPERTIES.clone(), properties),
136        (MSG.clone(), Value::String(Arc::new(msg))),
137    ];
138    Ok(Value::Object(Arc::new(Object {
139        type_name: udt.name.clone(),
140        members,
141    })))
142}
143
144fn parse_tagged_log_string(
145    udt: &UserDefinedType,
146    _udts: &[UserDefinedType],
147    dependencies: &HashMap<u64, Value>,
148    mut object_window: &[u8],
149) -> Result<Value> {
150    let desc_id: u64 = read_consume_pod(&mut object_window);
151    let desc = dependencies
152        .get(&desc_id)
153        .with_context(|| "fetching desc in parse_tagged_log_string")?
154        .clone();
155    let properties_id: u64 = read_consume_pod(&mut object_window);
156    let properties = dependencies
157        .get(&properties_id)
158        .with_context(|| "fetching property set in parse_tagged_log_string")?
159        .clone();
160    let time: i64 = read_consume_pod(&mut object_window);
161    let msg = read_advance_string(&mut object_window)?;
162
163    let members = vec![
164        (TIME.clone(), Value::I64(time)),
165        (DESC.clone(), desc),
166        (PROPERTIES.clone(), properties),
167        (MSG.clone(), Value::String(Arc::new(msg))),
168    ];
169    Ok(Value::Object(Arc::new(Object {
170        type_name: udt.name.clone(),
171        members,
172    })))
173}
174
175fn parse_log_string_interop_event(
176    udt: &UserDefinedType,
177    udts: &[UserDefinedType],
178    dependencies: &HashMap<u64, Value>,
179    mut object_window: &[u8],
180) -> Result<Value> {
181    let stringid_metadata = udts
182        .iter()
183        .find(|t| *t.name == "StringId")
184        .with_context(|| "Can't parse log string interop event with no metadata for StringId")?;
185    unsafe {
186        let time: i64 = read_consume_pod(&mut object_window);
187        let level: u32 = read_consume_pod(&mut object_window);
188        let target = parse_pod_instance(
189            stringid_metadata,
190            udts,
191            dependencies,
192            &object_window[0..stringid_metadata.size],
193        )
194        .with_context(|| "parse_pod_instance")?;
195        object_window = advance_window(object_window, stringid_metadata.size);
196        let msg = <LegacyDynString as InProcSerialize>::read_value(object_window);
197        let members = vec![
198            (TIME.clone(), Value::I64(time)),
199            (LEVEL.clone(), Value::U32(level)),
200            (TARGET.clone(), target),
201            (MSG.clone(), Value::String(Arc::new(msg.0))),
202        ];
203        Ok(Value::Object(Arc::new(Object {
204            type_name: udt.name.clone(),
205            members,
206        })))
207    }
208}
209
210fn parse_property_set(
211    _udt: &UserDefinedType,
212    udts: &[UserDefinedType],
213    dependencies: &HashMap<u64, Value>,
214    mut window: &[u8],
215) -> Result<Value> {
216    let property_layout = udts
217        .iter()
218        .find(|t| *t.name == "Property")
219        .with_context(|| "could not find Property layout")?;
220
221    let object_id: u64 = read_consume_pod(&mut window);
222    let nb_properties: u32 = read_consume_pod(&mut window);
223    let mut members = vec![];
224    for i in 0..nb_properties {
225        let property_size = property_layout.size;
226        let begin = i as usize * property_size;
227        let property_window = &window[begin..begin + property_size];
228        if let Value::Object(obj) =
229            parse_pod_instance(property_layout, udts, dependencies, property_window)?
230        {
231            members.push((
232                obj.get::<Arc<String>>("name")?,
233                Value::String(obj.get::<Arc<String>>("value")?),
234            ));
235        } else {
236            anyhow::bail!("invalid property in propertyset");
237        }
238    }
239
240    lazy_static! {
241        static ref PROPERTY_SET_TYPE_NAME: Arc<String> = Arc::new("property_set".into());
242        static ref ID: Arc<String> = Arc::new("id".into());
243        static ref VALUE: Arc<String> = Arc::new("value".into());
244    }
245
246    let set = Arc::new(Object {
247        type_name: PROPERTY_SET_TYPE_NAME.clone(),
248        members,
249    });
250    Ok(Value::Object(Arc::new(Object {
251        type_name: PROPERTY_SET_DEP_TYPE_NAME.clone(),
252        members: vec![
253            (ID.clone(), Value::U64(object_id)),
254            (VALUE.clone(), Value::Object(set)),
255        ],
256    })))
257}
258
259/// Dictionnary of custom readers for dynamically sized events
260pub fn make_custom_readers() -> CustomReaderMap {
261    let mut custom_readers: CustomReaderMap = HashMap::new();
262    custom_readers.insert("LogStringEvent".into(), Arc::new(parse_log_string_event));
263    custom_readers.insert(
264        "LogStringEventV2".into(),
265        Arc::new(parse_log_string_event_v2),
266    );
267    custom_readers.insert(
268        "LogStringInteropEventV2".into(),
269        Arc::new(parse_log_string_interop_event),
270    );
271    custom_readers.insert(
272        "LogStringInteropEventV3".into(),
273        Arc::new(parse_log_string_interop_event_v3),
274    );
275    custom_readers.insert("TaggedLogString".into(), Arc::new(parse_tagged_log_string));
276    custom_readers.insert(
277        PROPERTY_SET_DEP_TYPE_NAME.to_string(),
278        Arc::new(parse_property_set),
279    );
280    custom_readers.insert(
281        "TaggedLogInteropEvent".into(),
282        Arc::new(parse_tagged_log_interop_event),
283    );
284    custom_readers
285}