relay_event_schema/protocol/contexts/
memory_info.rs

1use relay_protocol::{Annotated, Array, Empty, FromValue, IntoValue, Object, Value};
2
3use crate::processor::ProcessValue;
4
5/// Memory Info Context
6#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
7pub struct MemoryInfoContext {
8    /// Currently allocated memory in bytes.
9    pub allocated_bytes: Annotated<u64>,
10
11    /// Boolean indicating if memory was compacted.
12    pub compacted: Annotated<bool>,
13
14    /// Boolean indicating if concurrent garbage collection occurred.
15    pub concurrent: Annotated<bool>,
16
17    /// Number of objects awaiting finalization.
18    pub finalization_pending_count: Annotated<u64>,
19
20    /// Fragmented memory that cannot be used in bytes.
21    pub fragmented_bytes: Annotated<u64>,
22
23    /// Total heap size in bytes.
24    pub heap_size_bytes: Annotated<u64>,
25
26    /// Threshold for high memory load detection in bytes.
27    pub high_memory_load_threshold_bytes: Annotated<u64>,
28
29    /// GC generation index.
30    pub index: Annotated<u64>,
31
32    /// Current memory load in bytes.
33    pub memory_load_bytes: Annotated<u64>,
34
35    /// Array of GC pause durations in milliseconds.
36    pub pause_durations: Annotated<Array<u64>>,
37
38    /// Percentage of time spent in GC pauses.
39    pub pause_time_percentage: Annotated<f64>,
40
41    /// Number of pinned objects in memory.
42    pub pinned_objects_count: Annotated<u64>,
43
44    /// Bytes promoted to higher generation.
45    pub promoted_bytes: Annotated<u64>,
46
47    /// Total memory allocated since start in bytes.
48    pub total_allocated_bytes: Annotated<u64>,
49
50    /// Total memory available to the application in bytes.
51    pub total_available_memory_bytes: Annotated<u64>,
52
53    /// Total committed virtual memory in bytes.
54    pub total_committed_bytes: Annotated<u64>,
55
56    /// Additional arbitrary fields for forwards compatibility.
57    #[metastructure(additional_properties, retain = true, pii = "maybe")]
58    pub other: Object<Value>,
59}
60
61impl super::DefaultContext for MemoryInfoContext {
62    fn default_key() -> &'static str {
63        "memory_info"
64    }
65
66    fn from_context(context: super::Context) -> Option<Self> {
67        match context {
68            super::Context::MemoryInfo(c) => Some(*c),
69            _ => None,
70        }
71    }
72
73    fn cast(context: &super::Context) -> Option<&Self> {
74        match context {
75            super::Context::MemoryInfo(c) => Some(c),
76            _ => None,
77        }
78    }
79
80    fn cast_mut(context: &mut super::Context) -> Option<&mut Self> {
81        match context {
82            super::Context::MemoryInfo(c) => Some(c),
83            _ => None,
84        }
85    }
86
87    fn into_context(self) -> super::Context {
88        super::Context::MemoryInfo(Box::new(self))
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use crate::protocol::Context;
96
97    #[test]
98    fn test_memory_info_context_roundtrip() {
99        let json = r#"{
100  "allocated_bytes": 1048576,
101  "compacted": true,
102  "concurrent": true,
103  "finalization_pending_count": 42,
104  "fragmented_bytes": 2048,
105  "heap_size_bytes": 3145728,
106  "high_memory_load_threshold_bytes": 8388608,
107  "index": 2,
108  "memory_load_bytes": 5242880,
109  "pause_durations": [
110    10,
111    5,
112    3
113  ],
114  "pause_time_percentage": 25.5,
115  "pinned_objects_count": 150,
116  "promoted_bytes": 524288,
117  "total_allocated_bytes": 9437184,
118  "total_available_memory_bytes": 16777216,
119  "total_committed_bytes": 12582912,
120  "other": "value",
121  "type": "memory_info"
122}"#;
123        let context = Annotated::new(Context::MemoryInfo(Box::new(MemoryInfoContext {
124            allocated_bytes: Annotated::new(1048576),
125            total_allocated_bytes: Annotated::new(9437184),
126            heap_size_bytes: Annotated::new(3145728),
127            pinned_objects_count: Annotated::new(150),
128            pause_time_percentage: Annotated::new(25.5),
129            compacted: Annotated::new(true),
130            concurrent: Annotated::new(true),
131            pause_durations: Annotated::new(vec![
132                Annotated::new(10),
133                Annotated::new(5),
134                Annotated::new(3),
135            ]),
136            finalization_pending_count: Annotated::new(42),
137            fragmented_bytes: Annotated::new(2048),
138            high_memory_load_threshold_bytes: Annotated::new(8388608),
139            index: Annotated::new(2),
140            memory_load_bytes: Annotated::new(5242880),
141            promoted_bytes: Annotated::new(524288),
142            total_available_memory_bytes: Annotated::new(16777216),
143            total_committed_bytes: Annotated::new(12582912),
144            other: {
145                let mut map = Object::new();
146                map.insert(
147                    "other".to_owned(),
148                    Annotated::new(Value::String("value".to_owned())),
149                );
150                map
151            },
152        })));
153
154        assert_eq!(context, Annotated::from_json(json).unwrap());
155        assert_eq!(json, context.to_json_pretty().unwrap());
156    }
157
158    #[test]
159    fn test_memory_info_context_minimal() {
160        let json = r#"{
161  "type": "memory_info"
162}"#;
163        let context = Annotated::new(Context::MemoryInfo(Box::default()));
164
165        assert_eq!(context, Annotated::from_json(json).unwrap());
166        assert_eq!(json, context.to_json_pretty().unwrap());
167    }
168}