Skip to main content

ckb_sentry_types/protocol/
v7.rs

1//! The current latest sentry protocol version.
2//!
3//! Most constructs in the protocol map directly to types here but some
4//! cleanup by renaming attributes has been applied.  The idea here is that
5//! a future sentry protocol will be a cleanup of the old one and is mapped
6//! to similar values on the rust side.
7#![allow(clippy::trivially_copy_pass_by_ref)]
8
9use std::borrow::Cow;
10use std::cmp;
11use std::fmt;
12use std::iter::FromIterator;
13use std::net::{AddrParseError, IpAddr};
14use std::ops;
15use std::str;
16
17use ::debugid::DebugId;
18use chrono::{DateTime, Utc};
19use serde::Serializer;
20use serde::{Deserialize, Serialize};
21use thiserror::Error;
22use url::Url;
23use uuid::Uuid;
24
25use crate::utils::ts_seconds_float;
26
27pub use super::envelope::*;
28pub use super::session::*;
29
30/// An arbitrary (JSON) value.
31pub mod value {
32    pub use serde_json::value::{from_value, to_value, Index, Map, Number, Value};
33}
34
35/// The internally used arbitrary data map type.
36pub mod map {
37    pub use std::collections::btree_map::{BTreeMap as Map, *};
38}
39
40/// Represents a debug ID.
41pub mod debugid {
42    pub use debugid::{BreakpadFormat, DebugId, ParseDebugIdError};
43}
44
45/// An arbitrary (JSON) value.
46pub use self::value::Value;
47
48/// The internally useed map type.
49pub use self::map::Map;
50
51/// A wrapper type for collections with attached meta data.
52///
53/// The JSON payload can either directly be an array or an object containing a `values` field and
54/// arbitrary other fields. All other fields will be collected into `Values::data` when
55/// deserializing and re-serialized in the same place. The shorthand array notation is always
56/// reserialized as object.
57#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
58pub struct Values<T> {
59    /// The values of the collection.
60    pub values: Vec<T>,
61}
62
63impl<T> Values<T> {
64    /// Creates an empty values struct.
65    pub fn new() -> Values<T> {
66        Values { values: Vec::new() }
67    }
68
69    /// Checks whether this struct is empty in both values and data.
70    pub fn is_empty(&self) -> bool {
71        self.values.is_empty()
72    }
73}
74
75impl<T> Default for Values<T> {
76    fn default() -> Self {
77        // Default implemented manually even if <T> does not impl Default.
78        Values::new()
79    }
80}
81
82impl<T> From<Vec<T>> for Values<T> {
83    fn from(values: Vec<T>) -> Self {
84        Values { values }
85    }
86}
87
88impl<T> AsRef<[T]> for Values<T> {
89    fn as_ref(&self) -> &[T] {
90        &self.values
91    }
92}
93
94impl<T> AsMut<Vec<T>> for Values<T> {
95    fn as_mut(&mut self) -> &mut Vec<T> {
96        &mut self.values
97    }
98}
99
100impl<T> ops::Deref for Values<T> {
101    type Target = [T];
102
103    fn deref(&self) -> &Self::Target {
104        &self.values
105    }
106}
107
108impl<T> ops::DerefMut for Values<T> {
109    fn deref_mut(&mut self) -> &mut Self::Target {
110        &mut self.values
111    }
112}
113
114impl<T> FromIterator<T> for Values<T> {
115    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
116        Vec::<T>::from_iter(iter).into()
117    }
118}
119
120impl<T> Extend<T> for Values<T> {
121    fn extend<I>(&mut self, iter: I)
122    where
123        I: IntoIterator<Item = T>,
124    {
125        self.values.extend(iter)
126    }
127}
128
129impl<'a, T> IntoIterator for &'a mut Values<T> {
130    type Item = <&'a mut Vec<T> as IntoIterator>::Item;
131    type IntoIter = <&'a mut Vec<T> as IntoIterator>::IntoIter;
132
133    fn into_iter(self) -> Self::IntoIter {
134        self.values.iter_mut()
135    }
136}
137
138impl<'a, T> IntoIterator for &'a Values<T> {
139    type Item = <&'a Vec<T> as IntoIterator>::Item;
140    type IntoIter = <&'a Vec<T> as IntoIterator>::IntoIter;
141
142    fn into_iter(self) -> Self::IntoIter {
143        self.values.iter()
144    }
145}
146
147impl<T> IntoIterator for Values<T> {
148    type Item = <Vec<T> as IntoIterator>::Item;
149    type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
150
151    fn into_iter(self) -> Self::IntoIter {
152        self.values.into_iter()
153    }
154}
155
156/// Represents a log entry message.
157///
158/// A log message is similar to the `message` attribute on the event itself but
159/// can additionally hold optional parameters.
160#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
161pub struct LogEntry {
162    /// The log message with parameters replaced by `%s`
163    pub message: String,
164    /// Positional parameters to be inserted into the log entry.
165    #[serde(default, skip_serializing_if = "Vec::is_empty")]
166    pub params: Vec<Value>,
167}
168
169/// Represents a frame.
170#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
171pub struct Frame {
172    /// The name of the function is known.
173    ///
174    /// Note that this might include the name of a class as well if that makes
175    /// sense for the language.
176    #[serde(default, skip_serializing_if = "Option::is_none")]
177    pub function: Option<String>,
178    /// The potentially mangled name of the symbol as it appears in an executable.
179    ///
180    /// This is different from a function name by generally being the mangled
181    /// name that appears natively in the binary.  This is relevant for languages
182    /// like Swift, C++ or Rust.
183    #[serde(default, skip_serializing_if = "Option::is_none")]
184    pub symbol: Option<String>,
185    /// The name of the module the frame is contained in.
186    ///
187    /// Note that this might also include a class name if that is something the
188    /// language natively considers to be part of the stack (for instance in Java).
189    #[serde(default, skip_serializing_if = "Option::is_none")]
190    pub module: Option<String>,
191    /// The name of the package that contains the frame.
192    ///
193    /// For instance this can be a dylib for native languages, the name of the jar
194    /// or .NET assembly.
195    #[serde(default, skip_serializing_if = "Option::is_none")]
196    pub package: Option<String>,
197    /// The filename (basename only).
198    #[serde(default, skip_serializing_if = "Option::is_none")]
199    pub filename: Option<String>,
200    /// If known the absolute path.
201    #[serde(default, skip_serializing_if = "Option::is_none")]
202    pub abs_path: Option<String>,
203    /// The line number if known.
204    #[serde(default, skip_serializing_if = "Option::is_none")]
205    pub lineno: Option<u64>,
206    /// The column number if known.
207    #[serde(default, skip_serializing_if = "Option::is_none")]
208    pub colno: Option<u64>,
209    /// The sources of the lines leading up to the current line.
210    #[serde(default, skip_serializing_if = "Vec::is_empty")]
211    pub pre_context: Vec<String>,
212    /// The current line as source.
213    #[serde(default, skip_serializing_if = "Option::is_none")]
214    pub context_line: Option<String>,
215    /// The sources of the lines after the current line.
216    #[serde(default, skip_serializing_if = "Vec::is_empty")]
217    pub post_context: Vec<String>,
218    /// In-app indicator.
219    #[serde(default, skip_serializing_if = "Option::is_none")]
220    pub in_app: Option<bool>,
221    /// Optional local variables.
222    #[serde(default, skip_serializing_if = "Map::is_empty")]
223    pub vars: Map<String, Value>,
224    /// If known the location of the image.
225    #[serde(default, skip_serializing_if = "Option::is_none")]
226    pub image_addr: Option<Addr>,
227    /// If known the location of the instruction.
228    #[serde(default, skip_serializing_if = "Option::is_none")]
229    pub instruction_addr: Option<Addr>,
230    /// If known the location of symbol.
231    #[serde(default, skip_serializing_if = "Option::is_none")]
232    pub symbol_addr: Option<Addr>,
233}
234
235/// Represents template debug info.
236#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
237pub struct TemplateInfo {
238    /// The filename (basename only).
239    #[serde(default, skip_serializing_if = "Option::is_none")]
240    pub filename: Option<String>,
241    /// If known the absolute path.
242    #[serde(default, skip_serializing_if = "Option::is_none")]
243    pub abs_path: Option<String>,
244    /// The line number if known.
245    #[serde(default, skip_serializing_if = "Option::is_none")]
246    pub lineno: Option<u64>,
247    /// The column number if known.
248    #[serde(default, skip_serializing_if = "Option::is_none")]
249    pub colno: Option<u64>,
250    /// The sources of the lines leading up to the current line.
251    #[serde(default, skip_serializing_if = "Vec::is_empty")]
252    pub pre_context: Vec<String>,
253    /// The current line as source.
254    #[serde(default, skip_serializing_if = "Option::is_none")]
255    pub context_line: Option<String>,
256    /// The sources of the lines after the current line.
257    #[serde(default, skip_serializing_if = "Vec::is_empty")]
258    pub post_context: Vec<String>,
259}
260
261/// Represents a stacktrace.
262#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
263pub struct Stacktrace {
264    /// The list of frames in the stacktrace.
265    #[serde(default)]
266    pub frames: Vec<Frame>,
267    /// Optionally a segment of frames removed (`start`, `end`).
268    #[serde(default, skip_serializing_if = "Option::is_none")]
269    pub frames_omitted: Option<(u64, u64)>,
270    /// Optional register values of the thread.
271    #[serde(default, skip_serializing_if = "Map::is_empty")]
272    pub registers: Map<String, RegVal>,
273}
274
275impl Stacktrace {
276    /// Optionally creates a stacktrace from a list of stack frames.
277    pub fn from_frames_reversed(mut frames: Vec<Frame>) -> Option<Stacktrace> {
278        if frames.is_empty() {
279            None
280        } else {
281            frames.reverse();
282            Some(Stacktrace {
283                frames,
284                ..Default::default()
285            })
286        }
287    }
288}
289
290/// Represents a thread id.
291#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
292#[serde(untagged)]
293pub enum ThreadId {
294    /// Integer representation for the thread id
295    Int(u64),
296    /// String representation for the thread id
297    String(String),
298}
299
300impl Default for ThreadId {
301    fn default() -> ThreadId {
302        ThreadId::Int(0)
303    }
304}
305
306impl<'a> From<&'a str> for ThreadId {
307    fn from(id: &'a str) -> ThreadId {
308        ThreadId::String(id.to_string())
309    }
310}
311
312impl From<String> for ThreadId {
313    fn from(id: String) -> ThreadId {
314        ThreadId::String(id)
315    }
316}
317
318impl From<i64> for ThreadId {
319    fn from(id: i64) -> ThreadId {
320        ThreadId::Int(id as u64)
321    }
322}
323
324impl From<i32> for ThreadId {
325    fn from(id: i32) -> ThreadId {
326        ThreadId::Int(id as u64)
327    }
328}
329
330impl From<u32> for ThreadId {
331    fn from(id: u32) -> ThreadId {
332        ThreadId::Int(id as u64)
333    }
334}
335
336impl From<u16> for ThreadId {
337    fn from(id: u16) -> ThreadId {
338        ThreadId::Int(id as u64)
339    }
340}
341
342impl fmt::Display for ThreadId {
343    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
344        match *self {
345            ThreadId::Int(i) => write!(f, "{}", i),
346            ThreadId::String(ref s) => write!(f, "{}", s),
347        }
348    }
349}
350
351/// Represents an address.
352#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
353pub struct Addr(pub u64);
354
355impl Addr {
356    /// Returns `true` if this address is the null pointer.
357    pub fn is_null(&self) -> bool {
358        self.0 == 0
359    }
360}
361
362impl_hex_serde!(Addr, u64);
363
364impl From<u64> for Addr {
365    fn from(addr: u64) -> Addr {
366        Addr(addr)
367    }
368}
369
370impl From<i32> for Addr {
371    fn from(addr: i32) -> Addr {
372        Addr(addr as u64)
373    }
374}
375
376impl From<u32> for Addr {
377    fn from(addr: u32) -> Addr {
378        Addr(addr as u64)
379    }
380}
381
382impl From<usize> for Addr {
383    fn from(addr: usize) -> Addr {
384        Addr(addr as u64)
385    }
386}
387
388impl<T> From<*const T> for Addr {
389    fn from(addr: *const T) -> Addr {
390        Addr(addr as u64)
391    }
392}
393
394impl<T> From<*mut T> for Addr {
395    fn from(addr: *mut T) -> Addr {
396        Addr(addr as u64)
397    }
398}
399
400impl Into<u64> for Addr {
401    fn into(self) -> u64 {
402        self.0
403    }
404}
405
406fn is_false(value: &bool) -> bool {
407    !*value
408}
409
410/// Represents a register value.
411#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
412pub struct RegVal(pub u64);
413
414impl_hex_serde!(RegVal, u64);
415
416impl From<u64> for RegVal {
417    fn from(addr: u64) -> RegVal {
418        RegVal(addr)
419    }
420}
421
422impl From<i32> for RegVal {
423    fn from(addr: i32) -> RegVal {
424        RegVal(addr as u64)
425    }
426}
427
428impl From<u32> for RegVal {
429    fn from(addr: u32) -> RegVal {
430        RegVal(addr as u64)
431    }
432}
433
434impl From<usize> for RegVal {
435    fn from(addr: usize) -> RegVal {
436        RegVal(addr as u64)
437    }
438}
439
440impl<T> From<*const T> for RegVal {
441    fn from(addr: *const T) -> RegVal {
442        RegVal(addr as u64)
443    }
444}
445
446impl<T> From<*mut T> for RegVal {
447    fn from(addr: *mut T) -> RegVal {
448        RegVal(addr as u64)
449    }
450}
451
452impl Into<u64> for RegVal {
453    fn into(self) -> u64 {
454        self.0
455    }
456}
457
458/// Represents a single thread.
459#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
460pub struct Thread {
461    /// The optional ID of the thread (usually an integer)
462    #[serde(default, skip_serializing_if = "Option::is_none")]
463    pub id: Option<ThreadId>,
464    /// The optional name of the thread.
465    #[serde(default, skip_serializing_if = "Option::is_none")]
466    pub name: Option<String>,
467    /// If the thread suspended or crashed a stacktrace can be
468    /// attached here.
469    #[serde(default, skip_serializing_if = "Option::is_none")]
470    pub stacktrace: Option<Stacktrace>,
471    /// Optional raw stacktrace.
472    #[serde(default, skip_serializing_if = "Option::is_none")]
473    pub raw_stacktrace: Option<Stacktrace>,
474    /// True if this is the crashed thread.
475    #[serde(default, skip_serializing_if = "is_false")]
476    pub crashed: bool,
477    /// Indicates that the thread was not suspended when the
478    /// event was created.
479    #[serde(default, skip_serializing_if = "is_false")]
480    pub current: bool,
481}
482
483/// POSIX signal with optional extended data.
484#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
485pub struct CError {
486    /// The error code as specified by ISO C99, POSIX.1-2001 or POSIX.1-2008.
487    pub number: i32,
488    /// Optional name of the errno constant.
489    #[serde(default, skip_serializing_if = "Option::is_none")]
490    pub name: Option<String>,
491}
492
493impl From<i32> for CError {
494    fn from(number: i32) -> CError {
495        CError { number, name: None }
496    }
497}
498
499impl Into<i32> for CError {
500    fn into(self) -> i32 {
501        self.number
502    }
503}
504
505/// Mach exception information.
506#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
507pub struct MachException {
508    /// The mach exception type.
509    pub exception: i32,
510    /// The mach exception code.
511    pub code: u64,
512    /// The mach exception subcode.
513    pub subcode: u64,
514    /// Optional name of the mach exception.
515    #[serde(default, skip_serializing_if = "Option::is_none")]
516    pub name: Option<String>,
517}
518
519/// POSIX signal with optional extended data.
520#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
521pub struct PosixSignal {
522    /// The POSIX signal number.
523    pub number: i32,
524    /// An optional signal code present on Apple systems.
525    #[serde(default, skip_serializing_if = "Option::is_none")]
526    pub code: Option<i32>,
527    /// Optional name of the errno constant.
528    #[serde(default, skip_serializing_if = "Option::is_none")]
529    pub name: Option<String>,
530    /// Optional name of the errno constant.
531    #[serde(default, skip_serializing_if = "Option::is_none")]
532    pub code_name: Option<String>,
533}
534
535impl From<i32> for PosixSignal {
536    fn from(number: i32) -> PosixSignal {
537        PosixSignal {
538            number,
539            code: None,
540            name: None,
541            code_name: None,
542        }
543    }
544}
545
546impl From<(i32, i32)> for PosixSignal {
547    fn from(tuple: (i32, i32)) -> PosixSignal {
548        let (number, code) = tuple;
549        PosixSignal {
550            number,
551            code: Some(code),
552            name: None,
553            code_name: None,
554        }
555    }
556}
557
558impl Into<i32> for PosixSignal {
559    fn into(self) -> i32 {
560        self.number
561    }
562}
563
564/// Operating system or runtime meta information to an exception mechanism.
565#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
566pub struct MechanismMeta {
567    /// Optional ISO C standard error code.
568    #[serde(default, skip_serializing_if = "Option::is_none")]
569    pub errno: Option<CError>,
570    /// Optional POSIX signal number.
571    #[serde(default, skip_serializing_if = "Option::is_none")]
572    pub signal: Option<PosixSignal>,
573    /// Optional mach exception information.
574    #[serde(default, skip_serializing_if = "Option::is_none")]
575    pub mach_exception: Option<MachException>,
576}
577
578impl MechanismMeta {
579    fn is_empty(&self) -> bool {
580        self.errno.is_none() && self.signal.is_none() && self.mach_exception.is_none()
581    }
582}
583
584/// Represents a single exception.
585#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
586pub struct Mechanism {
587    /// The mechanism type identifier.
588    #[serde(rename = "type")]
589    pub ty: String,
590    /// Human readable detail description.
591    #[serde(default, skip_serializing_if = "Option::is_none")]
592    pub description: Option<String>,
593    /// An optional link to online resources describing this error.
594    #[serde(default, skip_serializing_if = "Option::is_none")]
595    pub help_link: Option<Url>,
596    /// An optional flag indicating whether this exception was handled.
597    #[serde(default, skip_serializing_if = "Option::is_none")]
598    pub handled: Option<bool>,
599    /// An optional flag indicating a synthetic exception.
600    #[serde(default, skip_serializing_if = "Option::is_none")]
601    pub synthetic: Option<bool>,
602    /// Additional attributes depending on the mechanism type.
603    #[serde(default, skip_serializing_if = "Map::is_empty")]
604    pub data: Map<String, Value>,
605    /// Operating system or runtime meta information.
606    #[serde(default, skip_serializing_if = "MechanismMeta::is_empty")]
607    pub meta: MechanismMeta,
608}
609
610/// Represents a single exception.
611#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
612pub struct Exception {
613    /// The type of the exception.
614    #[serde(rename = "type")]
615    pub ty: String,
616    /// The optional value of the exception.
617    #[serde(skip_serializing_if = "Option::is_none")]
618    pub value: Option<String>,
619    /// An optional module for this exception.
620    #[serde(default, skip_serializing_if = "Option::is_none")]
621    pub module: Option<String>,
622    /// Optionally the stacktrace.
623    #[serde(default, skip_serializing_if = "Option::is_none")]
624    pub stacktrace: Option<Stacktrace>,
625    /// An optional raw stacktrace.
626    #[serde(default, skip_serializing_if = "Option::is_none")]
627    pub raw_stacktrace: Option<Stacktrace>,
628    /// Optional identifier referring to a thread.
629    #[serde(default, skip_serializing_if = "Option::is_none")]
630    pub thread_id: Option<ThreadId>,
631    /// The mechanism of the exception including OS specific exception values.
632    #[serde(default, skip_serializing_if = "Option::is_none")]
633    pub mechanism: Option<Mechanism>,
634}
635
636/// An error used when parsing `Level`.
637#[derive(Debug, Error)]
638#[error("invalid level")]
639pub struct ParseLevelError;
640
641/// Represents the level of severity of an event or breadcrumb.
642#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
643pub enum Level {
644    /// Indicates very spammy debug information.
645    Debug,
646    /// Informational messages.
647    Info,
648    /// A warning.
649    Warning,
650    /// An error.
651    Error,
652    /// Similar to error but indicates a critical event that usually causes a shutdown.
653    Fatal,
654}
655
656impl Default for Level {
657    fn default() -> Level {
658        Level::Info
659    }
660}
661
662impl str::FromStr for Level {
663    type Err = ParseLevelError;
664
665    fn from_str(string: &str) -> Result<Level, Self::Err> {
666        Ok(match string {
667            "debug" => Level::Debug,
668            "info" | "log" => Level::Info,
669            "warning" => Level::Warning,
670            "error" => Level::Error,
671            "fatal" => Level::Fatal,
672            _ => return Err(ParseLevelError),
673        })
674    }
675}
676
677impl fmt::Display for Level {
678    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
679        match *self {
680            Level::Debug => write!(f, "debug"),
681            Level::Info => write!(f, "info"),
682            Level::Warning => write!(f, "warning"),
683            Level::Error => write!(f, "error"),
684            Level::Fatal => write!(f, "fatal"),
685        }
686    }
687}
688
689impl Level {
690    /// A quick way to check if the level is `debug`.
691    pub fn is_debug(&self) -> bool {
692        *self == Level::Debug
693    }
694
695    /// A quick way to check if the level is `info`.
696    pub fn is_info(&self) -> bool {
697        *self == Level::Info
698    }
699
700    /// A quick way to check if the level is `warning`.
701    pub fn is_warning(&self) -> bool {
702        *self == Level::Warning
703    }
704
705    /// A quick way to check if the level is `error`.
706    pub fn is_error(&self) -> bool {
707        *self == Level::Error
708    }
709
710    /// A quick way to check if the level is `fatal`.
711    pub fn is_fatal(&self) -> bool {
712        *self == Level::Fatal
713    }
714}
715
716impl_str_serde!(Level);
717
718mod breadcrumb {
719    use super::*;
720
721    pub fn default_timestamp() -> DateTime<Utc> {
722        Utc::now()
723    }
724
725    pub fn default_type() -> String {
726        "default".to_string()
727    }
728
729    pub fn is_default_type(ty: &str) -> bool {
730        ty == "default"
731    }
732
733    pub fn default_level() -> Level {
734        Level::Info
735    }
736}
737
738/// Represents a single breadcrumb.
739#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
740pub struct Breadcrumb {
741    /// The timestamp of the breadcrumb.  This is required.
742    #[serde(default = "breadcrumb::default_timestamp", with = "ts_seconds_float")]
743    pub timestamp: DateTime<Utc>,
744    /// The type of the breadcrumb.
745    #[serde(
746        rename = "type",
747        default = "breadcrumb::default_type",
748        skip_serializing_if = "breadcrumb::is_default_type"
749    )]
750    pub ty: String,
751    /// The optional category of the breadcrumb.
752    #[serde(default, skip_serializing_if = "Option::is_none")]
753    pub category: Option<String>,
754    /// The non optional level of the breadcrumb.  It
755    /// defaults to info.
756    #[serde(
757        default = "breadcrumb::default_level",
758        skip_serializing_if = "Level::is_info"
759    )]
760    pub level: Level,
761    /// An optional human readbale message for the breadcrumb.
762    #[serde(default, skip_serializing_if = "Option::is_none")]
763    pub message: Option<String>,
764    /// Arbitrary breadcrumb data that should be send along.
765    #[serde(default, skip_serializing_if = "Map::is_empty")]
766    pub data: Map<String, Value>,
767}
768
769impl Default for Breadcrumb {
770    fn default() -> Breadcrumb {
771        Breadcrumb {
772            timestamp: breadcrumb::default_timestamp(),
773            ty: breadcrumb::default_type(),
774            category: Default::default(),
775            level: breadcrumb::default_level(),
776            message: Default::default(),
777            data: Default::default(),
778        }
779    }
780}
781
782/// An IP address, either IPv4, IPv6 or Auto.
783#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
784pub enum IpAddress {
785    /// The IP address needs to be infered from the user's context.
786    Auto,
787    /// The exact given IP address (v4 or v6).
788    Exact(IpAddr),
789}
790
791impl PartialEq<IpAddr> for IpAddress {
792    fn eq(&self, other: &IpAddr) -> bool {
793        match *self {
794            IpAddress::Auto => false,
795            IpAddress::Exact(ref addr) => addr == other,
796        }
797    }
798}
799
800impl cmp::PartialOrd<IpAddr> for IpAddress {
801    fn partial_cmp(&self, other: &IpAddr) -> Option<cmp::Ordering> {
802        match *self {
803            IpAddress::Auto => None,
804            IpAddress::Exact(ref addr) => addr.partial_cmp(other),
805        }
806    }
807}
808
809impl Default for IpAddress {
810    fn default() -> IpAddress {
811        IpAddress::Auto
812    }
813}
814
815impl fmt::Display for IpAddress {
816    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
817        match *self {
818            IpAddress::Auto => write!(f, "{{{{auto}}}}"),
819            IpAddress::Exact(ref addr) => write!(f, "{}", addr),
820        }
821    }
822}
823
824impl From<IpAddr> for IpAddress {
825    fn from(addr: IpAddr) -> IpAddress {
826        IpAddress::Exact(addr)
827    }
828}
829
830impl str::FromStr for IpAddress {
831    type Err = AddrParseError;
832
833    fn from_str(string: &str) -> Result<IpAddress, AddrParseError> {
834        match string {
835            "{{auto}}" => Ok(IpAddress::Auto),
836            other => other.parse().map(IpAddress::Exact),
837        }
838    }
839}
840
841impl_str_serde!(IpAddress);
842
843/// Represents user info.
844#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
845pub struct User {
846    /// The ID of the user.
847    #[serde(default, skip_serializing_if = "Option::is_none")]
848    pub id: Option<String>,
849    /// The email address of the user.
850    #[serde(default, skip_serializing_if = "Option::is_none")]
851    pub email: Option<String>,
852    /// The remote ip address of the user.
853    #[serde(default, skip_serializing_if = "Option::is_none")]
854    pub ip_address: Option<IpAddress>,
855    /// A human readable username of the user.
856    #[serde(default, skip_serializing_if = "Option::is_none")]
857    pub username: Option<String>,
858    /// Additional arbitrary fields for forwards compatibility.
859    #[serde(flatten)]
860    pub other: Map<String, Value>,
861}
862
863/// Represents http request data.
864#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
865pub struct Request {
866    /// The current URL of the request.
867    #[serde(default, skip_serializing_if = "Option::is_none")]
868    pub url: Option<Url>,
869    /// The HTTP request method.
870    #[serde(default, skip_serializing_if = "Option::is_none")]
871    pub method: Option<String>,
872    /// Optionally some associated request data (human readable)
873    // XXX: this makes absolutely no sense because of unicode
874    #[serde(default, skip_serializing_if = "Option::is_none")]
875    pub data: Option<String>,
876    /// Optionally the encoded query string.
877    #[serde(default, skip_serializing_if = "Option::is_none")]
878    pub query_string: Option<String>,
879    /// An encoded cookie string if available.
880    #[serde(default, skip_serializing_if = "Option::is_none")]
881    pub cookies: Option<String>,
882    /// HTTP request headers.
883    #[serde(default, skip_serializing_if = "Map::is_empty")]
884    pub headers: Map<String, String>,
885    /// Optionally a CGI/WSGI etc. environment dictionary.
886    #[serde(default, skip_serializing_if = "Map::is_empty")]
887    pub env: Map<String, String>,
888}
889
890/// Holds information about the system SDK.
891///
892/// This is relevant for iOS and other platforms that have a system
893/// SDK.  Not to be confused with the client SDK.
894#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
895pub struct SystemSdkInfo {
896    /// The internal name of the SDK
897    pub sdk_name: String,
898    /// the major version of the SDK as integer or 0
899    pub version_major: u32,
900    /// the minor version of the SDK as integer or 0
901    pub version_minor: u32,
902    /// the patch version of the SDK as integer or 0
903    pub version_patchlevel: u32,
904}
905
906/// Represents a debug image.
907#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
908#[serde(rename_all = "snake_case", tag = "type")]
909pub enum DebugImage {
910    /// Apple debug images (machos).  This is currently also used for
911    /// non apple platforms with similar debug setups.
912    Apple(AppleDebugImage),
913    /// Symbolic (new style) debug infos.
914    Symbolic(SymbolicDebugImage),
915    /// A reference to a proguard debug file.
916    Proguard(ProguardDebugImage),
917}
918
919impl DebugImage {
920    /// Returns the name of the type on sentry.
921    pub fn type_name(&self) -> &str {
922        match *self {
923            DebugImage::Apple(..) => "apple",
924            DebugImage::Symbolic(..) => "symbolic",
925            DebugImage::Proguard(..) => "proguard",
926        }
927    }
928}
929
930macro_rules! into_debug_image {
931    ($kind:ident, $ty:ty) => {
932        impl From<$ty> for DebugImage {
933            fn from(data: $ty) -> DebugImage {
934                DebugImage::$kind(data)
935            }
936        }
937    };
938}
939
940/// Represents an apple debug image in the debug meta.
941#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
942pub struct AppleDebugImage {
943    /// The name of the debug image (usually filename)
944    pub name: String,
945    /// The optional CPU architecture of the debug image.
946    pub arch: Option<String>,
947    /// Alternatively a macho cpu type.
948    pub cpu_type: Option<u32>,
949    /// Alternatively a macho cpu subtype.
950    pub cpu_subtype: Option<u32>,
951    /// The starting address of the image.
952    pub image_addr: Addr,
953    /// The size of the image in bytes.
954    pub image_size: u64,
955    /// The address where the image is loaded at runtime.
956    #[serde(default, skip_serializing_if = "Addr::is_null")]
957    pub image_vmaddr: Addr,
958    /// The unique UUID of the image.
959    pub uuid: Uuid,
960}
961
962/// Represents a symbolic debug image.
963#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
964pub struct SymbolicDebugImage {
965    /// The name of the debug image (usually filename)
966    pub name: String,
967    /// The optional CPU architecture of the debug image.
968    pub arch: Option<String>,
969    /// The starting address of the image.
970    pub image_addr: Addr,
971    /// The size of the image in bytes.
972    pub image_size: u64,
973    /// The address where the image is loaded at runtime.
974    #[serde(default, skip_serializing_if = "Addr::is_null")]
975    pub image_vmaddr: Addr,
976    /// The unique debug id of the image.
977    pub id: DebugId,
978}
979
980/// Represents a proguard mapping file reference.
981#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
982pub struct ProguardDebugImage {
983    /// The UUID of the associated proguard file.
984    pub uuid: Uuid,
985}
986
987into_debug_image!(Apple, AppleDebugImage);
988into_debug_image!(Symbolic, SymbolicDebugImage);
989into_debug_image!(Proguard, ProguardDebugImage);
990
991/// Represents debug meta information.
992#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
993pub struct DebugMeta {
994    /// Optional system SDK information.
995    #[serde(default, skip_serializing_if = "Option::is_none")]
996    pub sdk_info: Option<SystemSdkInfo>,
997    /// A list of debug information files.
998    #[serde(default, skip_serializing_if = "Vec::is_empty")]
999    pub images: Vec<DebugImage>,
1000}
1001
1002impl DebugMeta {
1003    /// Returns true if the debug meta is empty.
1004    ///
1005    /// This is used by the serializer to entirely skip the section.
1006    pub fn is_empty(&self) -> bool {
1007        self.sdk_info.is_none() && self.images.is_empty()
1008    }
1009}
1010
1011/// Information on the SDK client.
1012#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1013pub struct ClientSdkInfo {
1014    /// The name of the SDK.
1015    pub name: String,
1016    /// The version of the SDK.
1017    pub version: String,
1018    /// An optional list of integrations that are enabled in this SDK.
1019    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1020    pub integrations: Vec<String>,
1021    /// An optional list of packages that are installed in the SDK's environment.
1022    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1023    pub packages: Vec<ClientSdkPackage>,
1024}
1025
1026/// Represents an installed package relevant to the SDK.
1027#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1028pub struct ClientSdkPackage {
1029    /// The name of the package installed.
1030    pub name: String,
1031    /// The version of the package.
1032    pub version: String,
1033}
1034
1035/// Typed contextual data.
1036///
1037/// Types like `OsContext` can be directly converted with `.into()`
1038/// to `Context`.
1039#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1040#[serde(rename_all = "snake_case", tag = "type")]
1041#[non_exhaustive]
1042pub enum Context {
1043    /// Device data.
1044    Device(Box<DeviceContext>),
1045    /// Operating system data.
1046    Os(Box<OsContext>),
1047    /// Runtime data.
1048    Runtime(Box<RuntimeContext>),
1049    /// Application data.
1050    App(Box<AppContext>),
1051    /// Web browser data.
1052    Browser(Box<BrowserContext>),
1053    /// Tracing data.
1054    Trace(Box<TraceContext>),
1055    /// Generic other context data.
1056    #[serde(rename = "unknown")]
1057    Other(Map<String, Value>),
1058}
1059
1060impl Context {
1061    /// Returns the name of the type for sentry.
1062    pub fn type_name(&self) -> &str {
1063        match *self {
1064            Context::Device(..) => "device",
1065            Context::Os(..) => "os",
1066            Context::Runtime(..) => "runtime",
1067            Context::App(..) => "app",
1068            Context::Browser(..) => "browser",
1069            Context::Trace(..) => "trace",
1070            Context::Other(..) => "unknown",
1071        }
1072    }
1073}
1074
1075/// Optional device screen orientation
1076#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
1077#[serde(rename_all = "lowercase")]
1078pub enum Orientation {
1079    /// Portrait device orientation.
1080    Portrait,
1081    /// Landscape device orientation.
1082    Landscape,
1083}
1084
1085/// Holds device information.
1086#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1087pub struct DeviceContext {
1088    /// The name of the device.
1089    #[serde(default, skip_serializing_if = "Option::is_none")]
1090    pub name: Option<String>,
1091    /// The family of the device model.
1092    #[serde(default, skip_serializing_if = "Option::is_none")]
1093    pub family: Option<String>,
1094    /// The device model (human readable).
1095    #[serde(default, skip_serializing_if = "Option::is_none")]
1096    pub model: Option<String>,
1097    /// The device model (internal identifier).
1098    #[serde(default, skip_serializing_if = "Option::is_none")]
1099    pub model_id: Option<String>,
1100    /// The native cpu architecture of the device.
1101    #[serde(default, skip_serializing_if = "Option::is_none")]
1102    pub arch: Option<String>,
1103    /// The current battery level (0-100).
1104    #[serde(default, skip_serializing_if = "Option::is_none")]
1105    pub battery_level: Option<f32>,
1106    /// The current screen orientation.
1107    #[serde(default, skip_serializing_if = "Option::is_none")]
1108    pub orientation: Option<Orientation>,
1109    /// Simulator/prod indicator.
1110    #[serde(default, skip_serializing_if = "Option::is_none")]
1111    pub simulator: Option<bool>,
1112    /// Total memory available in byts.
1113    #[serde(default, skip_serializing_if = "Option::is_none")]
1114    pub memory_size: Option<u64>,
1115    /// How much memory is still available in bytes.
1116    #[serde(default, skip_serializing_if = "Option::is_none")]
1117    pub free_memory: Option<u64>,
1118    /// How much memory is usable for the app in bytes.
1119    #[serde(default, skip_serializing_if = "Option::is_none")]
1120    pub usable_memory: Option<u64>,
1121    /// Total storage size of the device in bytes.
1122    #[serde(default, skip_serializing_if = "Option::is_none")]
1123    pub storage_size: Option<u64>,
1124    /// How much storage is free in bytes.
1125    #[serde(default, skip_serializing_if = "Option::is_none")]
1126    pub free_storage: Option<u64>,
1127    /// Total size of the attached external storage in bytes (eg: android SDK card).
1128    #[serde(default, skip_serializing_if = "Option::is_none")]
1129    pub external_storage_size: Option<u64>,
1130    /// Free size of the attached external storage in bytes (eg: android SDK card).
1131    #[serde(default, skip_serializing_if = "Option::is_none")]
1132    pub external_free_storage: Option<u64>,
1133    /// Optionally an indicator when the device was booted.
1134    #[serde(default, skip_serializing_if = "Option::is_none")]
1135    pub boot_time: Option<DateTime<Utc>>,
1136    /// The timezone of the device.
1137    #[serde(default, skip_serializing_if = "Option::is_none")]
1138    pub timezone: Option<String>,
1139    /// Additional arbitrary fields for forwards compatibility.
1140    #[serde(flatten)]
1141    pub other: Map<String, Value>,
1142}
1143
1144/// Holds operating system information.
1145#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1146pub struct OsContext {
1147    /// The name of the operating system.
1148    #[serde(default, skip_serializing_if = "Option::is_none")]
1149    pub name: Option<String>,
1150    /// The version of the operating system.
1151    #[serde(default, skip_serializing_if = "Option::is_none")]
1152    pub version: Option<String>,
1153    /// The internal build number of the operating system.
1154    #[serde(default, skip_serializing_if = "Option::is_none")]
1155    pub build: Option<String>,
1156    /// The current kernel version.
1157    #[serde(default, skip_serializing_if = "Option::is_none")]
1158    pub kernel_version: Option<String>,
1159    /// An indicator if the os is rooted (mobile mostly).
1160    #[serde(default, skip_serializing_if = "Option::is_none")]
1161    pub rooted: Option<bool>,
1162    /// Additional arbitrary fields for forwards compatibility.
1163    #[serde(flatten)]
1164    pub other: Map<String, Value>,
1165}
1166
1167/// Holds information about the runtime.
1168#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1169pub struct RuntimeContext {
1170    /// The name of the runtime (for instance JVM).
1171    #[serde(default, skip_serializing_if = "Option::is_none")]
1172    pub name: Option<String>,
1173    /// The version of the runtime.
1174    #[serde(default, skip_serializing_if = "Option::is_none")]
1175    pub version: Option<String>,
1176    /// Additional arbitrary fields for forwards compatibility.
1177    #[serde(flatten)]
1178    pub other: Map<String, Value>,
1179}
1180
1181/// Holds app information.
1182#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1183pub struct AppContext {
1184    /// Optional start time of the app.
1185    #[serde(default, skip_serializing_if = "Option::is_none")]
1186    pub app_start_time: Option<DateTime<Utc>>,
1187    /// Optional device app hash (app specific device ID)
1188    #[serde(default, skip_serializing_if = "Option::is_none")]
1189    pub device_app_hash: Option<String>,
1190    /// Optional build identicator.
1191    #[serde(default, skip_serializing_if = "Option::is_none")]
1192    pub build_type: Option<String>,
1193    /// Optional app identifier (dotted bundle id).
1194    #[serde(default, skip_serializing_if = "Option::is_none")]
1195    pub app_identifier: Option<String>,
1196    /// Application name as it appears on the platform.
1197    #[serde(default, skip_serializing_if = "Option::is_none")]
1198    pub app_name: Option<String>,
1199    /// Application version as it appears on the platform.
1200    #[serde(default, skip_serializing_if = "Option::is_none")]
1201    pub app_version: Option<String>,
1202    /// Internal build ID as it appears on the platform.
1203    #[serde(default, skip_serializing_if = "Option::is_none")]
1204    pub app_build: Option<String>,
1205    /// Additional arbitrary fields for forwards compatibility.
1206    #[serde(flatten)]
1207    pub other: Map<String, Value>,
1208}
1209
1210/// Holds information about the web browser.
1211#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1212pub struct BrowserContext {
1213    /// The name of the browser (for instance "Chrome").
1214    #[serde(default, skip_serializing_if = "Option::is_none")]
1215    pub name: Option<String>,
1216    /// The version of the browser.
1217    #[serde(default, skip_serializing_if = "Option::is_none")]
1218    pub version: Option<String>,
1219    /// Additional arbitrary fields for forwards compatibility.
1220    #[serde(flatten)]
1221    pub other: Map<String, Value>,
1222}
1223
1224/// Holds information about a tracing event.
1225#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1226pub struct TraceContext {
1227    /// The ID of the trace event
1228    #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
1229    pub span_id: Uuid,
1230    /// Determines which trace the transaction belongs to.
1231    #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
1232    pub trace_id: Uuid,
1233    /// Determines the parent of this transaction if any.
1234    #[serde(default, skip_serializing_if = "Option::is_none")]
1235    pub parent_span_id: Option<String>,
1236    /// Short code identifying the type of operation the transaction is measuring.
1237    #[serde(default, skip_serializing_if = "Option::is_none")]
1238    pub op: Option<String>,
1239    /// Human readable detail description.
1240    #[serde(default, skip_serializing_if = "Option::is_none")]
1241    pub description: Option<String>,
1242    /// Describes the status of the span (e.g. `ok`, `cancelled`, etc.)
1243    #[serde(default, skip_serializing_if = "Option::is_none")]
1244    pub status: Option<String>,
1245}
1246
1247macro_rules! into_context {
1248    ($kind:ident, $ty:ty) => {
1249        impl From<$ty> for Context {
1250            fn from(data: $ty) -> Self {
1251                Context::$kind(Box::new(data))
1252            }
1253        }
1254    };
1255}
1256
1257into_context!(App, AppContext);
1258into_context!(Device, DeviceContext);
1259into_context!(Os, OsContext);
1260into_context!(Runtime, RuntimeContext);
1261into_context!(Browser, BrowserContext);
1262into_context!(Trace, TraceContext);
1263
1264mod event {
1265    use super::*;
1266
1267    pub fn default_id() -> Uuid {
1268        Uuid::new_v4()
1269    }
1270
1271    pub fn serialize_id<S: Serializer>(uuid: &Uuid, serializer: S) -> Result<S::Ok, S::Error> {
1272        serializer.serialize_some(&uuid.to_simple_ref().to_string())
1273    }
1274
1275    pub fn default_level() -> Level {
1276        Level::Error
1277    }
1278
1279    pub fn default_platform() -> Cow<'static, str> {
1280        Cow::Borrowed("other")
1281    }
1282
1283    pub fn is_default_platform(value: &str) -> bool {
1284        value == "other"
1285    }
1286
1287    static DEFAULT_FINGERPRINT: &[Cow<'static, str>] = &[Cow::Borrowed("{{ default }}")];
1288
1289    pub fn default_fingerprint<'a>() -> Cow<'a, [Cow<'a, str>]> {
1290        Cow::Borrowed(DEFAULT_FINGERPRINT)
1291    }
1292
1293    #[allow(clippy::ptr_arg)]
1294    pub fn is_default_fingerprint<'a>(fp: &[Cow<'a, str>]) -> bool {
1295        fp.len() == 1 && ((&fp)[0] == "{{ default }}" || (&fp)[0] == "{{default}}")
1296    }
1297
1298    pub fn default_timestamp() -> DateTime<Utc> {
1299        Utc::now()
1300    }
1301}
1302
1303/// Represents a full event for Sentry.
1304#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1305pub struct Event<'a> {
1306    /// The ID of the event
1307    #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
1308    pub event_id: Uuid,
1309    /// The level of the event (defaults to error)
1310    #[serde(
1311        default = "event::default_level",
1312        skip_serializing_if = "Level::is_error"
1313    )]
1314    pub level: Level,
1315    /// An optional fingerprint configuration to override the default.
1316    #[serde(
1317        default = "event::default_fingerprint",
1318        skip_serializing_if = "event::is_default_fingerprint"
1319    )]
1320    pub fingerprint: Cow<'a, [Cow<'a, str>]>,
1321    /// The culprit of the event.
1322    #[serde(default, skip_serializing_if = "Option::is_none")]
1323    pub culprit: Option<String>,
1324    /// The transaction name of the event.
1325    #[serde(default, skip_serializing_if = "Option::is_none")]
1326    pub transaction: Option<String>,
1327    /// A message to be sent with the event.
1328    #[serde(default, skip_serializing_if = "Option::is_none")]
1329    pub message: Option<String>,
1330    /// Optionally a log entry that can be used instead of the message for
1331    /// more complex cases.
1332    #[serde(default, skip_serializing_if = "Option::is_none")]
1333    pub logentry: Option<LogEntry>,
1334    /// Optionally the name of the logger that created this event.
1335    #[serde(default, skip_serializing_if = "Option::is_none")]
1336    pub logger: Option<String>,
1337    /// Optionally a name to version mapping of installed modules.
1338    #[serde(default, skip_serializing_if = "Map::is_empty")]
1339    pub modules: Map<String, String>,
1340    /// A platform identifier for this event.
1341    #[serde(
1342        default = "event::default_platform",
1343        skip_serializing_if = "event::is_default_platform"
1344    )]
1345    pub platform: Cow<'a, str>,
1346    /// The timestamp of when the event was created.
1347    ///
1348    /// This can be set to `None` in which case the server will set a timestamp.
1349    #[serde(default = "event::default_timestamp", with = "ts_seconds_float")]
1350    pub timestamp: DateTime<Utc>,
1351    /// Optionally the server (or device) name of this event.
1352    #[serde(default, skip_serializing_if = "Option::is_none")]
1353    pub server_name: Option<Cow<'a, str>>,
1354    /// A release identifier.
1355    #[serde(default, skip_serializing_if = "Option::is_none")]
1356    pub release: Option<Cow<'a, str>>,
1357    /// An optional distribution identifer.
1358    #[serde(default, skip_serializing_if = "Option::is_none")]
1359    pub dist: Option<Cow<'a, str>>,
1360    /// An optional environment identifier.
1361    #[serde(default, skip_serializing_if = "Option::is_none")]
1362    pub environment: Option<Cow<'a, str>>,
1363    /// Optionally user data to be sent along.
1364    #[serde(default, skip_serializing_if = "Option::is_none")]
1365    pub user: Option<User>,
1366    /// Optionally HTTP request data to be sent along.
1367    #[serde(default, skip_serializing_if = "Option::is_none")]
1368    pub request: Option<Request>,
1369    /// Optional contexts.
1370    #[serde(default, skip_serializing_if = "Map::is_empty")]
1371    pub contexts: Map<String, Context>,
1372    /// List of breadcrumbs to send along.
1373    #[serde(default, skip_serializing_if = "Values::is_empty")]
1374    pub breadcrumbs: Values<Breadcrumb>,
1375    /// Exceptions to be attached (one or multiple if chained).
1376    #[serde(default, skip_serializing_if = "Values::is_empty")]
1377    pub exception: Values<Exception>,
1378    /// A single stacktrace (deprecated)
1379    #[serde(default, skip_serializing_if = "Option::is_none")]
1380    pub stacktrace: Option<Stacktrace>,
1381    /// Simplified template error location info
1382    #[serde(default, skip_serializing_if = "Option::is_none")]
1383    pub template: Option<TemplateInfo>,
1384    /// A list of threads.
1385    #[serde(default, skip_serializing_if = "Values::is_empty")]
1386    pub threads: Values<Thread>,
1387    /// Optional tags to be attached to the event.
1388    #[serde(default, skip_serializing_if = "Map::is_empty")]
1389    pub tags: Map<String, String>,
1390    /// Optional extra information to be sent with the event.
1391    #[serde(default, skip_serializing_if = "Map::is_empty")]
1392    pub extra: Map<String, Value>,
1393    /// Debug meta information.
1394    #[serde(default, skip_serializing_if = "DebugMeta::is_empty")]
1395    pub debug_meta: Cow<'a, DebugMeta>,
1396    /// SDK metadata
1397    #[serde(default, skip_serializing_if = "Option::is_none")]
1398    pub sdk: Option<Cow<'a, ClientSdkInfo>>,
1399}
1400
1401impl<'a> Default for Event<'a> {
1402    fn default() -> Self {
1403        Event {
1404            event_id: event::default_id(),
1405            level: event::default_level(),
1406            fingerprint: event::default_fingerprint(),
1407            culprit: Default::default(),
1408            transaction: Default::default(),
1409            message: Default::default(),
1410            logentry: Default::default(),
1411            logger: Default::default(),
1412            modules: Default::default(),
1413            platform: event::default_platform(),
1414            timestamp: event::default_timestamp(),
1415            server_name: Default::default(),
1416            release: Default::default(),
1417            dist: Default::default(),
1418            environment: Default::default(),
1419            user: Default::default(),
1420            request: Default::default(),
1421            contexts: Default::default(),
1422            breadcrumbs: Default::default(),
1423            exception: Default::default(),
1424            stacktrace: Default::default(),
1425            template: Default::default(),
1426            threads: Default::default(),
1427            tags: Default::default(),
1428            extra: Default::default(),
1429            debug_meta: Default::default(),
1430            sdk: Default::default(),
1431        }
1432    }
1433}
1434
1435impl<'a> Event<'a> {
1436    /// Creates a new event with the current timestamp and random id.
1437    pub fn new() -> Event<'a> {
1438        Default::default()
1439    }
1440
1441    /// Creates a fully owned version of the event.
1442    pub fn into_owned(self) -> Event<'static> {
1443        Event {
1444            event_id: self.event_id,
1445            level: self.level,
1446            fingerprint: Cow::Owned(
1447                self.fingerprint
1448                    .iter()
1449                    .map(|x| Cow::Owned(x.to_string()))
1450                    .collect(),
1451            ),
1452            culprit: self.culprit,
1453            transaction: self.transaction,
1454            message: self.message,
1455            logentry: self.logentry,
1456            logger: self.logger,
1457            modules: self.modules,
1458            platform: Cow::Owned(self.platform.into_owned()),
1459            timestamp: self.timestamp,
1460            server_name: self.server_name.map(|x| Cow::Owned(x.into_owned())),
1461            release: self.release.map(|x| Cow::Owned(x.into_owned())),
1462            dist: self.dist.map(|x| Cow::Owned(x.into_owned())),
1463            environment: self.environment.map(|x| Cow::Owned(x.into_owned())),
1464            user: self.user,
1465            request: self.request,
1466            contexts: self.contexts,
1467            breadcrumbs: self.breadcrumbs,
1468            exception: self.exception,
1469            stacktrace: self.stacktrace,
1470            template: self.template,
1471            threads: self.threads,
1472            tags: self.tags,
1473            extra: self.extra,
1474            debug_meta: Cow::Owned(self.debug_meta.into_owned()),
1475            sdk: self.sdk.map(|x| Cow::Owned(x.into_owned())),
1476        }
1477    }
1478}
1479
1480impl<'a> fmt::Display for Event<'a> {
1481    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1482        write!(f, "Event(id: {}, ts: {})", self.event_id, self.timestamp)
1483    }
1484}
1485
1486/// Represents a tracing span.
1487#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1488pub struct Span {
1489    /// The ID of the span
1490    #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
1491    pub span_id: Uuid,
1492    /// Determines which trace the span belongs to.
1493    #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
1494    pub trace_id: Uuid,
1495    /// Determines the parent of this span, if any.
1496    #[serde(default, skip_serializing_if = "Option::is_none")]
1497    pub parent_span_id: Option<String>,
1498    /// Determines whether this span is generated in the same process as its parent, if any.
1499    #[serde(default, skip_serializing_if = "Option::is_none")]
1500    pub same_process_as_parent: Option<bool>,
1501    /// Short code identifying the type of operation the span is measuring.
1502    #[serde(default, skip_serializing_if = "Option::is_none")]
1503    pub op: Option<String>,
1504    /// Longer description of the span's operation, which uniquely identifies the span
1505    /// but is consistent across instances of the span.
1506    #[serde(default, skip_serializing_if = "Option::is_none")]
1507    pub description: Option<String>,
1508    /// The timestamp at the measuring of the span finished.
1509    #[serde(default, skip_serializing_if = "Option::is_none")]
1510    pub timestamp: Option<DateTime<Utc>>,
1511    /// The timestamp at the measuring of the span started.
1512    #[serde(default = "event::default_timestamp", with = "ts_seconds_float")]
1513    pub start_timestamp: DateTime<Utc>,
1514    /// Describes the status of the span (e.g. `ok`, `cancelled`, etc.)
1515    #[serde(default, skip_serializing_if = "Option::is_none")]
1516    pub status: Option<String>,
1517    /// Optional tags to be attached to the span.
1518    #[serde(default, skip_serializing_if = "Map::is_empty")]
1519    pub tags: Map<String, String>,
1520    /// Optional extra information to be sent with the span.
1521    #[serde(default, skip_serializing_if = "Map::is_empty")]
1522    pub data: Map<String, Value>,
1523}
1524
1525impl Default for Span {
1526    fn default() -> Self {
1527        Span {
1528            span_id: event::default_id(),
1529            trace_id: event::default_id(),
1530            timestamp: Default::default(),
1531            tags: Default::default(),
1532            start_timestamp: event::default_timestamp(),
1533            description: Default::default(),
1534            status: Default::default(),
1535            parent_span_id: Default::default(),
1536            same_process_as_parent: Default::default(),
1537            op: Default::default(),
1538            data: Default::default(),
1539        }
1540    }
1541}
1542
1543impl Span {
1544    /// Creates a new span with the current timestamp and random id.
1545    pub fn new() -> Span {
1546        Default::default()
1547    }
1548
1549    /// Finalizes the span.
1550    pub fn finish(&mut self) {
1551        self.timestamp = Some(Utc::now());
1552    }
1553}
1554
1555impl fmt::Display for Span {
1556    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1557        write!(
1558            f,
1559            "Span(id: {}, ts: {})",
1560            self.span_id, self.start_timestamp
1561        )
1562    }
1563}
1564
1565/// Represents a tracing transaction.
1566#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1567pub struct Transaction<'a> {
1568    /// The ID of the event
1569    #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
1570    pub event_id: Uuid,
1571    /// The transaction name.
1572    #[serde(default, skip_serializing_if = "Option::is_none")]
1573    pub name: Option<String>,
1574    /// Optional tags to be attached to the event.
1575    #[serde(default, skip_serializing_if = "Map::is_empty")]
1576    pub tags: Map<String, String>,
1577    /// SDK metadata
1578    #[serde(default, skip_serializing_if = "Option::is_none")]
1579    pub sdk: Option<Cow<'a, ClientSdkInfo>>,
1580    /// A platform identifier for this event.
1581    #[serde(
1582        default = "event::default_platform",
1583        skip_serializing_if = "event::is_default_platform"
1584    )]
1585    pub platform: Cow<'a, str>,
1586    /// The end time of the transaction.
1587    #[serde(default, skip_serializing_if = "Option::is_none")]
1588    pub timestamp: Option<DateTime<Utc>>,
1589    /// The start time of the transaction.
1590    #[serde(default = "event::default_timestamp", with = "ts_seconds_float")]
1591    pub start_timestamp: DateTime<Utc>,
1592    /// The collection of finished spans part of this transaction.
1593    pub spans: Vec<Span>,
1594    /// Optional contexts.
1595    #[serde(default, skip_serializing_if = "Map::is_empty")]
1596    pub contexts: Map<String, Context>,
1597}
1598
1599impl<'a> Default for Transaction<'a> {
1600    fn default() -> Self {
1601        Transaction {
1602            event_id: event::default_id(),
1603            name: Default::default(),
1604            tags: Default::default(),
1605            sdk: Default::default(),
1606            platform: event::default_platform(),
1607            timestamp: Default::default(),
1608            start_timestamp: event::default_timestamp(),
1609            spans: Default::default(),
1610            contexts: Default::default(),
1611        }
1612    }
1613}
1614
1615impl<'a> Transaction<'a> {
1616    /// Creates a new span transaction the current timestamp and random id.
1617    pub fn new() -> Transaction<'a> {
1618        Default::default()
1619    }
1620
1621    /// Creates a fully owned version of the transaction.
1622    pub fn into_owned(self) -> Transaction<'static> {
1623        Transaction {
1624            event_id: self.event_id,
1625            name: self.name,
1626            tags: self.tags,
1627            sdk: self.sdk.map(|x| Cow::Owned(x.into_owned())),
1628            platform: Cow::Owned(self.platform.into_owned()),
1629            timestamp: self.timestamp,
1630            start_timestamp: self.start_timestamp,
1631            spans: self.spans,
1632            contexts: self.contexts,
1633        }
1634    }
1635
1636    /// Finalizes the transaction to be dispatched.
1637    pub fn finish(&mut self) {
1638        self.timestamp = Some(Utc::now());
1639    }
1640}
1641
1642impl<'a> fmt::Display for Transaction<'a> {
1643    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1644        write!(
1645            f,
1646            "Transaction(id: {}, ts: {})",
1647            self.event_id, self.start_timestamp
1648        )
1649    }
1650}