1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Defines types related to Sentry events.
//!
//! As opposed to the event protocol defined in `relay-event-schema`, these types are meant to be
//! used outside of the event protocol, for instance to reference Events from other places.

use std::fmt;
use std::str::FromStr;

use relay_protocol::{Annotated, Empty, ErrorKind, FromValue, IntoValue, SkipSerialization, Value};
#[cfg(feature = "jsonschema")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

/// The type of an event.
///
/// The event type determines how Sentry handles the event and has an impact on processing, rate
/// limiting, and quotas. There are three fundamental classes of event types:
///
///  - **Error monitoring events** (`default`, `error`): Processed and grouped into unique issues
///    based on their exception stack traces and error messages.
///  - **Security events** (`csp`, `hpkp`, `expectct`, `expectstaple`): Derived from Browser
///    security violation reports and grouped into unique issues based on the endpoint and
///    violation. SDKs do not send such events.
///  - **Transaction events** (`transaction`): Contain operation spans and collected into traces for
///    performance monitoring.
#[derive(
    Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize, Default,
)]
#[cfg_attr(feature = "jsonschema", derive(JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum EventType {
    /// Events that carry an exception payload.
    Error,
    /// A CSP violation payload.
    Csp,
    /// An HPKP violation payload.
    Hpkp,
    /// An ExpectCT violation payload.
    ExpectCt,
    /// An ExpectStaple violation payload.
    ExpectStaple,
    /// Network Error Logging report.
    Nel,
    /// Performance monitoring transactions carrying spans.
    Transaction,
    /// User feedback payload.
    ///
    /// TODO(Jferg): Change this to UserFeedback once old UserReport logic is deprecated.
    UserReportV2,
    /// All events that do not qualify as any other type.
    #[serde(other)]
    #[default]
    Default,
}

/// An error used when parsing `EventType`.
#[derive(Clone, Copy, Debug)]
pub struct ParseEventTypeError;

impl fmt::Display for ParseEventTypeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "invalid event type")
    }
}

impl std::error::Error for ParseEventTypeError {}

impl FromStr for EventType {
    type Err = ParseEventTypeError;

    fn from_str(string: &str) -> Result<Self, Self::Err> {
        Ok(match string {
            "default" => EventType::Default,
            "error" => EventType::Error,
            "csp" => EventType::Csp,
            "hpkp" => EventType::Hpkp,
            "expectct" => EventType::ExpectCt,
            "expectstaple" => EventType::ExpectStaple,
            "nel" => EventType::Nel,
            "transaction" => EventType::Transaction,
            "feedback" => EventType::UserReportV2,
            _ => return Err(ParseEventTypeError),
        })
    }
}

impl fmt::Display for EventType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            EventType::Default => write!(f, "default"),
            EventType::Error => write!(f, "error"),
            EventType::Csp => write!(f, "csp"),
            EventType::Hpkp => write!(f, "hpkp"),
            EventType::ExpectCt => write!(f, "expectct"),
            EventType::ExpectStaple => write!(f, "expectstaple"),
            EventType::Nel => write!(f, "nel"),
            EventType::Transaction => write!(f, "transaction"),
            EventType::UserReportV2 => write!(f, "feedback"),
        }
    }
}

impl Empty for EventType {
    #[inline]
    fn is_empty(&self) -> bool {
        false
    }
}

impl FromValue for EventType {
    fn from_value(value: Annotated<Value>) -> Annotated<Self> {
        match String::from_value(value) {
            Annotated(Some(value), mut meta) => match value.parse() {
                Ok(eventtype) => Annotated(Some(eventtype), meta),
                Err(_) => {
                    meta.add_error(ErrorKind::InvalidData);
                    meta.set_original_value(Some(value));
                    Annotated(None, meta)
                }
            },
            Annotated(None, meta) => Annotated(None, meta),
        }
    }
}

impl IntoValue for EventType {
    fn into_value(self) -> Value
    where
        Self: Sized,
    {
        Value::String(format!("{self}"))
    }

    fn serialize_payload<S>(&self, s: S, _behavior: SkipSerialization) -> Result<S::Ok, S::Error>
    where
        Self: Sized,
        S: serde::Serializer,
    {
        Serialize::serialize(&self.to_string(), s)
    }
}