relay_event_schema/protocol/contexts/
cloud_resource.rs

1use relay_protocol::{Annotated, Empty, FromValue, IntoValue, Object, Value};
2
3use crate::processor::ProcessValue;
4
5/// Cloud Resource Context.
6///
7/// This context describes the cloud resource the event originated from.
8///
9/// Example:
10///
11/// ```json
12/// "cloud_resource": {
13///     "cloud.account.id": "499517922981",
14///     "cloud.provider": "aws",
15///     "cloud.platform": "aws_ec2",
16///     "cloud.region": "us-east-1",
17///     "cloud.vavailability_zone": "us-east-1e",
18///     "host.id": "i-07d3301208fe0a55a",
19///     "host.type": "t2.large"
20/// }
21/// ```
22#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
23pub struct CloudResourceContext {
24    /// The cloud account ID the resource is assigned to.
25    #[metastructure(pii = "maybe")]
26    #[metastructure(field = "cloud.account.id")]
27    pub cloud_account_id: Annotated<String>,
28
29    /// Name of the cloud provider.
30    #[metastructure(field = "cloud.provider")]
31    pub cloud_provider: Annotated<String>,
32
33    /// The cloud platform in use.
34    /// The prefix of the service SHOULD match the one specified in cloud_provider.
35    #[metastructure(field = "cloud.platform")]
36    pub cloud_platform: Annotated<String>,
37
38    /// The geographical region the resource is running.
39    #[metastructure(field = "cloud.region")]
40    pub cloud_region: Annotated<String>,
41
42    /// The zone where the resource is running.
43    #[metastructure(field = "cloud.availability_zone")]
44    pub cloud_availability_zone: Annotated<String>,
45
46    /// Unique host ID.
47    #[metastructure(pii = "maybe")]
48    #[metastructure(field = "host.id")]
49    pub host_id: Annotated<String>,
50
51    /// Machine type of the host.
52    #[metastructure(field = "host.type")]
53    pub host_type: Annotated<String>,
54
55    /// Additional arbitrary fields for forwards compatibility.
56    #[metastructure(additional_properties, retain = true, pii = "maybe")]
57    pub other: Object<Value>,
58}
59
60impl super::DefaultContext for CloudResourceContext {
61    fn default_key() -> &'static str {
62        "cloud_resource"
63    }
64
65    fn from_context(context: super::Context) -> Option<Self> {
66        match context {
67            super::Context::CloudResource(c) => Some(*c),
68            _ => None,
69        }
70    }
71
72    fn cast(context: &super::Context) -> Option<&Self> {
73        match context {
74            super::Context::CloudResource(c) => Some(c),
75            _ => None,
76        }
77    }
78
79    fn cast_mut(context: &mut super::Context) -> Option<&mut Self> {
80        match context {
81            super::Context::CloudResource(c) => Some(c),
82            _ => None,
83        }
84    }
85
86    fn into_context(self) -> super::Context {
87        super::Context::CloudResource(Box::new(self))
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94    use crate::protocol::Context;
95
96    #[test]
97    fn test_cloud_resource_context_roundtrip() {
98        let json = r#"{
99  "cloud.account.id": "499517922981",
100  "cloud.provider": "aws",
101  "cloud.platform": "aws_ec2",
102  "cloud.region": "us-east-1",
103  "cloud.availability_zone": "us-east-1e",
104  "host.id": "i-07d3301208fe0a55a",
105  "host.type": "t2.large",
106  "other": "value",
107  "type": "cloudresource"
108}"#;
109        let context = Annotated::new(Context::CloudResource(Box::new(CloudResourceContext {
110            cloud_account_id: Annotated::new("499517922981".into()),
111            cloud_provider: Annotated::new("aws".into()),
112            cloud_platform: Annotated::new("aws_ec2".into()),
113            cloud_region: Annotated::new("us-east-1".into()),
114            cloud_availability_zone: Annotated::new("us-east-1e".into()),
115            host_id: Annotated::new("i-07d3301208fe0a55a".into()),
116            host_type: Annotated::new("t2.large".into()),
117            other: {
118                let mut map = Object::new();
119                map.insert(
120                    "other".to_string(),
121                    Annotated::new(Value::String("value".to_string())),
122                );
123                map
124            },
125        })));
126
127        assert_eq!(context, Annotated::from_json(json).unwrap());
128        assert_eq!(json, context.to_json_pretty().unwrap());
129    }
130}