relay_event_schema/protocol/contexts/
app.rs1use relay_protocol::{Annotated, Empty, FromValue, IntoValue, Object, Value};
2
3use crate::processor::ProcessValue;
4use crate::protocol::LenientString;
5
6#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
11pub struct AppContext {
12 #[metastructure(pii = "maybe")]
16 pub app_start_time: Annotated<String>,
17
18 #[metastructure(pii = "maybe")]
20 pub device_app_hash: Annotated<String>,
21
22 pub build_type: Annotated<String>,
24
25 pub app_identifier: Annotated<String>,
27
28 pub app_name: Annotated<String>,
30
31 pub app_version: Annotated<String>,
33
34 pub app_build: Annotated<LenientString>,
36
37 pub app_memory: Annotated<u64>,
39
40 pub in_foreground: Annotated<bool>,
42
43 #[metastructure(skip_serialization = "empty")]
45 pub view_names: Annotated<Vec<Annotated<String>>>,
46
47 #[metastructure(additional_properties, retain = true, pii = "maybe")]
49 pub other: Object<Value>,
50}
51
52impl super::DefaultContext for AppContext {
53 fn default_key() -> &'static str {
54 "app"
55 }
56
57 fn from_context(context: super::Context) -> Option<Self> {
58 match context {
59 super::Context::App(c) => Some(*c),
60 _ => None,
61 }
62 }
63
64 fn cast(context: &super::Context) -> Option<&Self> {
65 match context {
66 super::Context::App(c) => Some(c),
67 _ => None,
68 }
69 }
70
71 fn cast_mut(context: &mut super::Context) -> Option<&mut Self> {
72 match context {
73 super::Context::App(c) => Some(c),
74 _ => None,
75 }
76 }
77
78 fn into_context(self) -> super::Context {
79 super::Context::App(Box::new(self))
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use crate::protocol::Context;
87
88 #[test]
89 fn test_app_context_roundtrip() {
90 let json = r#"{
91 "app_start_time": "2018-02-08T22:21:57Z",
92 "device_app_hash": "4c793e3776474877ae30618378e9662a",
93 "build_type": "testflight",
94 "app_identifier": "foo.bar.baz",
95 "app_name": "Baz App",
96 "app_version": "1.0",
97 "app_build": "100001",
98 "app_memory": 22883948,
99 "in_foreground": true,
100 "view_names": [
101 "FooViewController",
102 "BarViewController"
103 ],
104 "other": "value",
105 "type": "app"
106}"#;
107 let context = Annotated::new(Context::App(Box::new(AppContext {
108 app_start_time: Annotated::new("2018-02-08T22:21:57Z".to_string()),
109 device_app_hash: Annotated::new("4c793e3776474877ae30618378e9662a".to_string()),
110 build_type: Annotated::new("testflight".to_string()),
111 app_identifier: Annotated::new("foo.bar.baz".to_string()),
112 app_name: Annotated::new("Baz App".to_string()),
113 app_version: Annotated::new("1.0".to_string()),
114 app_build: Annotated::new("100001".to_string().into()),
115 app_memory: Annotated::new(22883948),
116 in_foreground: Annotated::new(true),
117 view_names: Annotated::new(vec![
118 Annotated::new("FooViewController".to_string()),
119 Annotated::new("BarViewController".to_string()),
120 ]),
121 other: {
122 let mut map = Object::new();
123 map.insert(
124 "other".to_string(),
125 Annotated::new(Value::String("value".to_string())),
126 );
127 map
128 },
129 })));
130
131 assert_eq!(context, Annotated::from_json(json).unwrap());
132 assert_eq!(json, context.to_json_pretty().unwrap());
133 }
134}