Skip to main content

micromegas_tracing/logs/
log_events.rs

1use crate::{
2    property_set::PropertySetId,
3    static_string_ref::{BlockStringRef, StaticStringRef},
4    string_id::{DynStringId, StringId},
5};
6use micromegas_transit::{
7    DynString, UserDefinedType, prelude::*, read_advance_string, read_consume_pod,
8};
9use std::sync::Arc;
10
11use super::LogMetadata;
12
13// Ensure we're on a 64-bit platform since we store pointers as u64
14const _: () = assert!(std::mem::size_of::<usize>() == 8);
15
16#[derive(Debug, TransitReflect)]
17pub struct LogStaticStrEvent {
18    pub desc: &'static LogMetadata<'static>,
19    pub time: i64,
20}
21
22impl InProcSerialize for LogStaticStrEvent {}
23
24/// A log with a property set attached, either interned or built from dynamic values.
25/// Its message is `desc.fmt_str`.
26#[derive(Debug, TransitReflect)]
27pub struct TaggedLogStaticStrEvent {
28    pub desc: &'static LogMetadata<'static>,
29    #[transit(reference)]
30    pub properties: PropertySetId,
31    pub time: i64,
32}
33
34impl InProcSerialize for TaggedLogStaticStrEvent {}
35
36#[derive(Debug)]
37pub struct LogStringEvent {
38    pub desc: &'static LogMetadata<'static>,
39    pub time: i64,
40    pub msg: DynString,
41}
42
43impl InProcSerialize for LogStringEvent {
44    const IN_PROC_SIZE: InProcSize = InProcSize::Dynamic;
45
46    fn get_value_size(&self) -> Option<u32> {
47        Some(
48            std::mem::size_of::<usize>() as u32 //desc reference
49                + std::mem::size_of::<i64>() as u32 //time
50                + self.msg.get_value_size().unwrap(), //dyn string
51        )
52    }
53
54    fn write_value(&self, buffer: &mut Vec<u8>) {
55        let desc_id = self.desc as *const _ as usize;
56        write_any(buffer, &desc_id);
57        write_any(buffer, &self.time);
58        self.msg.write_value(buffer);
59    }
60
61    unsafe fn read_value(mut window: &[u8]) -> Self {
62        // it does no good to parse this object when looking for dependencies, we should skip this code
63        let desc_id: usize = read_consume_pod(&mut window);
64        let desc = unsafe { &*(desc_id as *const LogMetadata) };
65        let time: i64 = read_consume_pod(&mut window);
66        let msg = DynString(read_advance_string(&mut window).unwrap());
67        assert_eq!(window.len(), 0);
68        Self { desc, time, msg }
69    }
70}
71
72//todo: change this interface to make clear that there are two serialization
73// strategies: pod and custom
74impl Reflect for LogStringEvent {
75    fn reflect() -> UserDefinedType {
76        lazy_static::lazy_static! {
77            static ref TYPE_NAME: Arc<String> = Arc::new("LogStringEventV2".into());
78        }
79        UserDefinedType {
80            name: TYPE_NAME.clone(),
81            size: 0,
82            members: vec![],
83            is_reference: false,
84            secondary_udts: vec![],
85        }
86    }
87}
88
89#[derive(Debug, TransitReflect)]
90pub struct LogStaticStrInteropEvent {
91    pub time: i64,
92    pub level: u32,
93    pub target: StringId,
94    pub msg: StringId,
95}
96
97impl InProcSerialize for LogStaticStrInteropEvent {}
98
99#[derive(Debug, TransitReflect)]
100pub struct LogStaticStrInteropEventV2 {
101    pub time: i64,
102    pub level: u32,
103    pub target: DynStringId,
104    pub msg: StringId,
105}
106
107impl InProcSerialize for LogStaticStrInteropEventV2 {}
108
109#[derive(Debug)]
110pub struct LogStringInteropEvent {
111    pub time: i64,
112    pub level: u8,
113    // The id of a string record in the block's queue, laid out as a `StaticStringRef` for
114    // unreal compatibility.
115    pub target: BlockStringRef,
116    pub msg: DynString,
117}
118
119impl InProcSerialize for LogStringInteropEvent {
120    const IN_PROC_SIZE: InProcSize = InProcSize::Dynamic;
121
122    fn get_value_size(&self) -> Option<u32> {
123        Some(
124            std::mem::size_of::<i64>() as u32 //time
125                + std::mem::size_of::<u8>() as u32 //level
126                + std::mem::size_of::<BlockStringRef>() as u32 //target
127                + self.msg.get_value_size().unwrap(), //message
128        )
129    }
130
131    fn write_value(&self, buffer: &mut Vec<u8>) {
132        write_any(buffer, &self.time);
133        write_any(buffer, &self.level);
134        write_any(buffer, &self.target);
135        self.msg.write_value(buffer);
136    }
137
138    unsafe fn read_value(mut window: &[u8]) -> Self {
139        let time: i64 = read_consume_pod(&mut window);
140        let level: u8 = read_consume_pod(&mut window);
141        let target: BlockStringRef = read_consume_pod(&mut window);
142        let msg = DynString(read_advance_string(&mut window).unwrap());
143        Self {
144            time,
145            level,
146            target,
147            msg,
148        }
149    }
150}
151
152//todo: change this interface to make clear that there are two serialization
153// strategies: pod and custom
154impl Reflect for LogStringInteropEvent {
155    fn reflect() -> UserDefinedType {
156        lazy_static::lazy_static! {
157            static ref TYPE_NAME: Arc<String> = Arc::new("LogStringInteropEventV3".into());
158        }
159        UserDefinedType {
160            name: TYPE_NAME.clone(),
161            size: 0,
162            members: vec![],
163            is_reference: false,
164            secondary_udts: vec![StaticStringRef::reflect()],
165        }
166    }
167}
168
169/// Interop log with properties. Mirrors the event of the same name in the Unreal
170/// instrumentation so that one analytics parser reads both.
171#[derive(Debug)]
172pub struct TaggedLogInteropEvent {
173    pub time: i64,
174    pub level: u8,
175    pub target: BlockStringRef,
176    pub properties: PropertySetId,
177    pub msg: DynString,
178}
179
180impl InProcSerialize for TaggedLogInteropEvent {
181    const IN_PROC_SIZE: InProcSize = InProcSize::Dynamic;
182
183    fn get_value_size(&self) -> Option<u32> {
184        Some(
185            std::mem::size_of::<i64>() as u32 // time
186                + std::mem::size_of::<u8>() as u32 // level
187                + std::mem::size_of::<BlockStringRef>() as u32 // target
188                + std::mem::size_of::<u64>() as u32 // properties ptr
189                + self.msg.get_value_size().unwrap(), // message
190        )
191    }
192
193    fn write_value(&self, buffer: &mut Vec<u8>) {
194        write_any(buffer, &self.time);
195        write_any(buffer, &self.level);
196        write_any(buffer, &self.target);
197        write_any(buffer, &self.properties.0);
198        self.msg.write_value(buffer);
199    }
200
201    unsafe fn read_value(mut window: &[u8]) -> Self {
202        let time: i64 = read_consume_pod(&mut window);
203        let level: u8 = read_consume_pod(&mut window);
204        let target: BlockStringRef = read_consume_pod(&mut window);
205        let properties_id: u64 = read_consume_pod(&mut window);
206        let msg = DynString(read_advance_string(&mut window).unwrap());
207        Self {
208            time,
209            level,
210            target,
211            properties: PropertySetId(properties_id),
212            msg,
213        }
214    }
215}
216
217impl Reflect for TaggedLogInteropEvent {
218    fn reflect() -> UserDefinedType {
219        lazy_static::lazy_static! {
220            static ref TYPE_NAME: Arc<String> = Arc::new("TaggedLogInteropEvent".into());
221        }
222        UserDefinedType {
223            name: TYPE_NAME.clone(),
224            size: 0,
225            members: vec![],
226            is_reference: false,
227            secondary_udts: vec![StaticStringRef::reflect()],
228        }
229    }
230}
231
232#[derive(Debug, TransitReflect)]
233pub struct LogMetadataRecord {
234    pub id: u64,
235    pub fmt_str: *const u8,
236    pub target: *const u8,
237    pub module_path: *const u8,
238    pub file: *const u8,
239    pub line: u32,
240    pub level: u32,
241}
242
243impl InProcSerialize for LogMetadataRecord {}
244
245/// A log with a property set attached, either interned or built from dynamic values.
246#[derive(Debug)]
247pub struct TaggedLogString {
248    pub desc: &'static LogMetadata<'static>,
249    pub properties: PropertySetId,
250    pub time: i64,
251    pub msg: DynString,
252}
253
254impl Reflect for TaggedLogString {
255    fn reflect() -> UserDefinedType {
256        lazy_static::lazy_static! {
257            static ref TYPE_NAME: Arc<String> = Arc::new("TaggedLogString".into());
258        }
259        UserDefinedType {
260            name: TYPE_NAME.clone(),
261            size: 0,
262            members: vec![],
263            is_reference: false,
264            secondary_udts: vec![],
265        }
266    }
267}
268
269impl InProcSerialize for TaggedLogString {
270    const IN_PROC_SIZE: InProcSize = InProcSize::Dynamic;
271
272    fn get_value_size(&self) -> Option<u32> {
273        Some(
274            std::mem::size_of::<u64>() as u32 // desc ptr
275            + std::mem::size_of::<u64>() as u32 // properties ptr
276            + std::mem::size_of::<i64>() as u32 // time
277                + self.msg.get_value_size().unwrap(), // message
278        )
279    }
280
281    fn write_value(&self, buffer: &mut Vec<u8>) {
282        write_any(buffer, &self.desc);
283        write_any(buffer, &self.properties.0);
284        write_any(buffer, &self.time);
285        self.msg.write_value(buffer);
286    }
287
288    #[allow(unknown_lints)]
289    #[allow(integer_to_ptr_transmutes)] // TODO: Fix pointer provenance properly (see tasks/pointer-provenance.md)
290    unsafe fn read_value(mut window: &[u8]) -> Self {
291        let desc_id: u64 = read_consume_pod(&mut window);
292        let properties_id: u64 = read_consume_pod(&mut window);
293        let time: i64 = read_consume_pod(&mut window);
294        let msg = DynString(read_advance_string(&mut window).unwrap());
295        Self {
296            desc: unsafe { std::mem::transmute::<u64, &LogMetadata<'static>>(desc_id) },
297            properties: PropertySetId(properties_id),
298            time,
299            msg,
300        }
301    }
302}