1use std::borrow::Cow;
9use std::cmp;
10use std::convert::TryFrom;
11use std::fmt;
12use std::iter::FromIterator;
13use std::net::{AddrParseError, IpAddr};
14use std::ops;
15use std::str;
16use std::time::SystemTime;
17
18use self::debugid::{CodeId, DebugId};
19use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
20use thiserror::Error;
21
22pub use url::Url;
23pub use uuid::Uuid;
24
25use crate::utils::{display_from_str_opt, ts_rfc3339_opt, ts_seconds_float};
26
27pub use super::attachment::*;
28pub use super::envelope::*;
29pub use super::monitor::*;
30pub use super::session::*;
31pub use super::unit::Unit;
32
33pub mod value {
35 pub use serde_json::value::{from_value, to_value, Index, Map, Number, Value};
36}
37
38pub mod map {
40 pub use std::collections::btree_map::{BTreeMap as Map, *};
41}
42
43pub mod debugid {
45 pub use debugid::{BreakpadFormat, CodeId, DebugId, ParseDebugIdError};
46}
47
48pub use self::value::Value;
50
51pub use self::map::Map;
53
54#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
61pub struct Values<T> {
62 pub values: Vec<T>,
64}
65
66impl<T> Values<T> {
67 pub fn new() -> Values<T> {
69 Values { values: Vec::new() }
70 }
71
72 pub fn is_empty(&self) -> bool {
74 self.values.is_empty()
75 }
76}
77
78impl<T> Default for Values<T> {
79 fn default() -> Self {
80 Values::new()
82 }
83}
84
85impl<T> From<Vec<T>> for Values<T> {
86 fn from(values: Vec<T>) -> Self {
87 Values { values }
88 }
89}
90
91impl<T> AsRef<[T]> for Values<T> {
92 fn as_ref(&self) -> &[T] {
93 &self.values
94 }
95}
96
97impl<T> AsMut<Vec<T>> for Values<T> {
98 fn as_mut(&mut self) -> &mut Vec<T> {
99 &mut self.values
100 }
101}
102
103impl<T> ops::Deref for Values<T> {
104 type Target = [T];
105
106 fn deref(&self) -> &Self::Target {
107 &self.values
108 }
109}
110
111impl<T> ops::DerefMut for Values<T> {
112 fn deref_mut(&mut self) -> &mut Self::Target {
113 &mut self.values
114 }
115}
116
117impl<T> FromIterator<T> for Values<T> {
118 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
119 Vec::<T>::from_iter(iter).into()
120 }
121}
122
123impl<T> Extend<T> for Values<T> {
124 fn extend<I>(&mut self, iter: I)
125 where
126 I: IntoIterator<Item = T>,
127 {
128 self.values.extend(iter)
129 }
130}
131
132impl<'a, T> IntoIterator for &'a mut Values<T> {
133 type Item = <&'a mut Vec<T> as IntoIterator>::Item;
134 type IntoIter = <&'a mut Vec<T> as IntoIterator>::IntoIter;
135
136 fn into_iter(self) -> Self::IntoIter {
137 self.values.iter_mut()
138 }
139}
140
141impl<'a, T> IntoIterator for &'a Values<T> {
142 type Item = <&'a Vec<T> as IntoIterator>::Item;
143 type IntoIter = <&'a Vec<T> as IntoIterator>::IntoIter;
144
145 fn into_iter(self) -> Self::IntoIter {
146 self.values.iter()
147 }
148}
149
150impl<T> IntoIterator for Values<T> {
151 type Item = <Vec<T> as IntoIterator>::Item;
152 type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
153
154 fn into_iter(self) -> Self::IntoIter {
155 self.values.into_iter()
156 }
157}
158
159#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
164pub struct LogEntry {
165 pub message: String,
167 #[serde(default, skip_serializing_if = "Vec::is_empty")]
169 pub params: Vec<Value>,
170}
171
172#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
174pub struct Frame {
175 #[serde(default, skip_serializing_if = "Option::is_none")]
180 pub function: Option<String>,
181 #[serde(default, skip_serializing_if = "Option::is_none")]
187 pub symbol: Option<String>,
188 #[serde(default, skip_serializing_if = "Option::is_none")]
193 pub module: Option<String>,
194 #[serde(default, skip_serializing_if = "Option::is_none")]
199 pub package: Option<String>,
200 #[serde(default, skip_serializing_if = "Option::is_none")]
202 pub filename: Option<String>,
203 #[serde(default, skip_serializing_if = "Option::is_none")]
205 pub abs_path: Option<String>,
206 #[serde(default, skip_serializing_if = "Option::is_none")]
208 pub lineno: Option<u64>,
209 #[serde(default, skip_serializing_if = "Option::is_none")]
211 pub colno: Option<u64>,
212 #[serde(default, skip_serializing_if = "Vec::is_empty")]
214 pub pre_context: Vec<String>,
215 #[serde(default, skip_serializing_if = "Option::is_none")]
217 pub context_line: Option<String>,
218 #[serde(default, skip_serializing_if = "Vec::is_empty")]
220 pub post_context: Vec<String>,
221 #[serde(default, skip_serializing_if = "Option::is_none")]
223 pub in_app: Option<bool>,
224 #[serde(default, skip_serializing_if = "Map::is_empty")]
226 pub vars: Map<String, Value>,
227 #[serde(default, skip_serializing_if = "Option::is_none")]
229 pub image_addr: Option<Addr>,
230 #[serde(default, skip_serializing_if = "Option::is_none")]
232 pub instruction_addr: Option<Addr>,
233 #[serde(default, skip_serializing_if = "Option::is_none")]
235 pub symbol_addr: Option<Addr>,
236 #[serde(default, skip_serializing_if = "Option::is_none")]
242 pub addr_mode: Option<String>,
243}
244
245#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
247pub struct TemplateInfo {
248 #[serde(default, skip_serializing_if = "Option::is_none")]
250 pub filename: Option<String>,
251 #[serde(default, skip_serializing_if = "Option::is_none")]
253 pub abs_path: Option<String>,
254 #[serde(default, skip_serializing_if = "Option::is_none")]
256 pub lineno: Option<u64>,
257 #[serde(default, skip_serializing_if = "Option::is_none")]
259 pub colno: Option<u64>,
260 #[serde(default, skip_serializing_if = "Vec::is_empty")]
262 pub pre_context: Vec<String>,
263 #[serde(default, skip_serializing_if = "Option::is_none")]
265 pub context_line: Option<String>,
266 #[serde(default, skip_serializing_if = "Vec::is_empty")]
268 pub post_context: Vec<String>,
269}
270
271#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
273pub struct Stacktrace {
274 #[serde(default)]
276 pub frames: Vec<Frame>,
277 #[serde(default, skip_serializing_if = "Option::is_none")]
279 pub frames_omitted: Option<(u64, u64)>,
280 #[serde(default, skip_serializing_if = "Map::is_empty")]
282 pub registers: Map<String, RegVal>,
283}
284
285impl Stacktrace {
286 pub fn from_frames_reversed(mut frames: Vec<Frame>) -> Option<Stacktrace> {
288 if frames.is_empty() {
289 None
290 } else {
291 frames.reverse();
292 Some(Stacktrace {
293 frames,
294 ..Default::default()
295 })
296 }
297 }
298}
299
300#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
302#[serde(untagged)]
303pub enum ThreadId {
304 Int(u64),
306 String(String),
308}
309
310impl Default for ThreadId {
311 fn default() -> ThreadId {
312 ThreadId::Int(0)
313 }
314}
315
316impl<'a> From<&'a str> for ThreadId {
317 fn from(id: &'a str) -> ThreadId {
318 ThreadId::String(id.to_string())
319 }
320}
321
322impl From<String> for ThreadId {
323 fn from(id: String) -> ThreadId {
324 ThreadId::String(id)
325 }
326}
327
328impl From<i64> for ThreadId {
329 fn from(id: i64) -> ThreadId {
330 ThreadId::Int(id as u64)
331 }
332}
333
334impl From<i32> for ThreadId {
335 fn from(id: i32) -> ThreadId {
336 ThreadId::Int(id as u64)
337 }
338}
339
340impl From<u32> for ThreadId {
341 fn from(id: u32) -> ThreadId {
342 ThreadId::Int(id as u64)
343 }
344}
345
346impl From<u16> for ThreadId {
347 fn from(id: u16) -> ThreadId {
348 ThreadId::Int(id as u64)
349 }
350}
351
352impl fmt::Display for ThreadId {
353 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
354 match *self {
355 ThreadId::Int(i) => write!(f, "{i}"),
356 ThreadId::String(ref s) => write!(f, "{s}"),
357 }
358 }
359}
360
361#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
363pub struct Addr(pub u64);
364
365impl Addr {
366 pub fn is_null(&self) -> bool {
368 self.0 == 0
369 }
370}
371
372impl_hex_serde!(Addr, u64);
373
374impl From<u64> for Addr {
375 fn from(addr: u64) -> Addr {
376 Addr(addr)
377 }
378}
379
380impl From<i32> for Addr {
381 fn from(addr: i32) -> Addr {
382 Addr(addr as u64)
383 }
384}
385
386impl From<u32> for Addr {
387 fn from(addr: u32) -> Addr {
388 Addr(addr as u64)
389 }
390}
391
392impl From<usize> for Addr {
393 fn from(addr: usize) -> Addr {
394 Addr(addr as u64)
395 }
396}
397
398impl<T> From<*const T> for Addr {
399 fn from(addr: *const T) -> Addr {
400 Addr(addr as u64)
401 }
402}
403
404impl<T> From<*mut T> for Addr {
405 fn from(addr: *mut T) -> Addr {
406 Addr(addr as u64)
407 }
408}
409
410impl From<Addr> for u64 {
411 fn from(addr: Addr) -> Self {
412 addr.0
413 }
414}
415
416fn is_false(value: &bool) -> bool {
417 !*value
418}
419
420#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
422pub struct RegVal(pub u64);
423
424impl_hex_serde!(RegVal, u64);
425
426impl From<u64> for RegVal {
427 fn from(addr: u64) -> RegVal {
428 RegVal(addr)
429 }
430}
431
432impl From<i32> for RegVal {
433 fn from(addr: i32) -> RegVal {
434 RegVal(addr as u64)
435 }
436}
437
438impl From<u32> for RegVal {
439 fn from(addr: u32) -> RegVal {
440 RegVal(addr as u64)
441 }
442}
443
444impl From<usize> for RegVal {
445 fn from(addr: usize) -> RegVal {
446 RegVal(addr as u64)
447 }
448}
449
450impl<T> From<*const T> for RegVal {
451 fn from(addr: *const T) -> RegVal {
452 RegVal(addr as u64)
453 }
454}
455
456impl<T> From<*mut T> for RegVal {
457 fn from(addr: *mut T) -> RegVal {
458 RegVal(addr as u64)
459 }
460}
461
462impl From<RegVal> for u64 {
463 fn from(reg: RegVal) -> Self {
464 reg.0
465 }
466}
467
468#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
470pub struct Thread {
471 #[serde(default, skip_serializing_if = "Option::is_none")]
473 pub id: Option<ThreadId>,
474 #[serde(default, skip_serializing_if = "Option::is_none")]
476 pub name: Option<String>,
477 #[serde(default, skip_serializing_if = "Option::is_none")]
480 pub stacktrace: Option<Stacktrace>,
481 #[serde(default, skip_serializing_if = "Option::is_none")]
483 pub raw_stacktrace: Option<Stacktrace>,
484 #[serde(default, skip_serializing_if = "is_false")]
486 pub crashed: bool,
487 #[serde(default, skip_serializing_if = "is_false")]
490 pub current: bool,
491}
492
493#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
495pub struct CError {
496 pub number: i32,
498 #[serde(default, skip_serializing_if = "Option::is_none")]
500 pub name: Option<String>,
501}
502
503impl From<i32> for CError {
504 fn from(number: i32) -> CError {
505 CError { number, name: None }
506 }
507}
508
509impl From<CError> for i32 {
510 fn from(err: CError) -> Self {
511 err.number
512 }
513}
514
515#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
517pub struct MachException {
518 pub exception: i32,
520 pub code: u64,
522 pub subcode: u64,
524 #[serde(default, skip_serializing_if = "Option::is_none")]
526 pub name: Option<String>,
527}
528
529#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
531pub struct PosixSignal {
532 pub number: i32,
534 #[serde(default, skip_serializing_if = "Option::is_none")]
536 pub code: Option<i32>,
537 #[serde(default, skip_serializing_if = "Option::is_none")]
539 pub name: Option<String>,
540 #[serde(default, skip_serializing_if = "Option::is_none")]
542 pub code_name: Option<String>,
543}
544
545impl From<i32> for PosixSignal {
546 fn from(number: i32) -> PosixSignal {
547 PosixSignal {
548 number,
549 code: None,
550 name: None,
551 code_name: None,
552 }
553 }
554}
555
556impl From<(i32, i32)> for PosixSignal {
557 fn from(tuple: (i32, i32)) -> PosixSignal {
558 let (number, code) = tuple;
559 PosixSignal {
560 number,
561 code: Some(code),
562 name: None,
563 code_name: None,
564 }
565 }
566}
567
568impl From<PosixSignal> for i32 {
569 fn from(sig: PosixSignal) -> Self {
570 sig.number
571 }
572}
573
574#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
576pub struct MechanismMeta {
577 #[serde(default, skip_serializing_if = "Option::is_none")]
579 pub errno: Option<CError>,
580 #[serde(default, skip_serializing_if = "Option::is_none")]
582 pub signal: Option<PosixSignal>,
583 #[serde(default, skip_serializing_if = "Option::is_none")]
585 pub mach_exception: Option<MachException>,
586}
587
588impl MechanismMeta {
589 fn is_empty(&self) -> bool {
590 self.errno.is_none() && self.signal.is_none() && self.mach_exception.is_none()
591 }
592}
593
594#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
596pub struct Mechanism {
597 #[serde(rename = "type")]
599 pub ty: String,
600 #[serde(default, skip_serializing_if = "Option::is_none")]
602 pub description: Option<String>,
603 #[serde(default, skip_serializing_if = "Option::is_none")]
605 pub help_link: Option<Url>,
606 #[serde(default, skip_serializing_if = "Option::is_none")]
608 pub handled: Option<bool>,
609 #[serde(default, skip_serializing_if = "Option::is_none")]
611 pub synthetic: Option<bool>,
612 #[serde(default, skip_serializing_if = "Map::is_empty")]
614 pub data: Map<String, Value>,
615 #[serde(default, skip_serializing_if = "MechanismMeta::is_empty")]
617 pub meta: MechanismMeta,
618}
619
620#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
622pub struct Exception {
623 #[serde(rename = "type")]
625 pub ty: String,
626 #[serde(skip_serializing_if = "Option::is_none")]
628 pub value: Option<String>,
629 #[serde(default, skip_serializing_if = "Option::is_none")]
631 pub module: Option<String>,
632 #[serde(default, skip_serializing_if = "Option::is_none")]
634 pub stacktrace: Option<Stacktrace>,
635 #[serde(default, skip_serializing_if = "Option::is_none")]
637 pub raw_stacktrace: Option<Stacktrace>,
638 #[serde(default, skip_serializing_if = "Option::is_none")]
640 pub thread_id: Option<ThreadId>,
641 #[serde(default, skip_serializing_if = "Option::is_none")]
643 pub mechanism: Option<Mechanism>,
644}
645
646#[derive(Debug, Error)]
648#[error("invalid level")]
649pub struct ParseLevelError;
650
651#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
653pub enum Level {
654 Debug,
656 #[default]
658 Info,
659 Warning,
661 Error,
663 Fatal,
665}
666
667impl str::FromStr for Level {
668 type Err = ParseLevelError;
669
670 fn from_str(string: &str) -> Result<Level, Self::Err> {
671 Ok(match string {
672 "debug" => Level::Debug,
673 "info" | "log" => Level::Info,
674 "warning" => Level::Warning,
675 "error" => Level::Error,
676 "fatal" => Level::Fatal,
677 _ => return Err(ParseLevelError),
678 })
679 }
680}
681
682impl fmt::Display for Level {
683 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
684 match *self {
685 Level::Debug => write!(f, "debug"),
686 Level::Info => write!(f, "info"),
687 Level::Warning => write!(f, "warning"),
688 Level::Error => write!(f, "error"),
689 Level::Fatal => write!(f, "fatal"),
690 }
691 }
692}
693
694impl Level {
695 pub fn is_debug(&self) -> bool {
697 *self == Level::Debug
698 }
699
700 pub fn is_info(&self) -> bool {
702 *self == Level::Info
703 }
704
705 pub fn is_warning(&self) -> bool {
707 *self == Level::Warning
708 }
709
710 pub fn is_error(&self) -> bool {
712 *self == Level::Error
713 }
714
715 pub fn is_fatal(&self) -> bool {
717 *self == Level::Fatal
718 }
719}
720
721impl_str_serde!(Level);
722
723mod breadcrumb {
724 use super::*;
725
726 pub fn default_type() -> String {
727 "default".to_string()
728 }
729
730 pub fn is_default_type(ty: &str) -> bool {
731 ty == "default"
732 }
733
734 pub fn default_level() -> Level {
735 Level::Info
736 }
737}
738
739#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
741pub struct Breadcrumb {
742 #[serde(default = "SystemTime::now", with = "ts_seconds_float")]
744 pub timestamp: SystemTime,
745 #[serde(
747 rename = "type",
748 default = "breadcrumb::default_type",
749 skip_serializing_if = "breadcrumb::is_default_type"
750 )]
751 pub ty: String,
752 #[serde(default, skip_serializing_if = "Option::is_none")]
754 pub category: Option<String>,
755 #[serde(
758 default = "breadcrumb::default_level",
759 skip_serializing_if = "Level::is_info"
760 )]
761 pub level: Level,
762 #[serde(default, skip_serializing_if = "Option::is_none")]
764 pub message: Option<String>,
765 #[serde(default, skip_serializing_if = "Map::is_empty")]
767 pub data: Map<String, Value>,
768}
769
770impl Default for Breadcrumb {
771 fn default() -> Breadcrumb {
772 Breadcrumb {
773 timestamp: SystemTime::now(),
774 ty: breadcrumb::default_type(),
775 category: Default::default(),
776 level: breadcrumb::default_level(),
777 message: Default::default(),
778 data: Default::default(),
779 }
780 }
781}
782
783#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
785pub enum IpAddress {
786 #[default]
788 Auto,
789 Exact(IpAddr),
791}
792
793impl PartialEq<IpAddr> for IpAddress {
794 fn eq(&self, other: &IpAddr) -> bool {
795 match *self {
796 IpAddress::Auto => false,
797 IpAddress::Exact(ref addr) => addr == other,
798 }
799 }
800}
801
802impl cmp::PartialOrd<IpAddr> for IpAddress {
803 fn partial_cmp(&self, other: &IpAddr) -> Option<cmp::Ordering> {
804 match *self {
805 IpAddress::Auto => None,
806 IpAddress::Exact(ref addr) => addr.partial_cmp(other),
807 }
808 }
809}
810
811impl fmt::Display for IpAddress {
812 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
813 match *self {
814 IpAddress::Auto => write!(f, "{{{{auto}}}}"),
815 IpAddress::Exact(ref addr) => write!(f, "{addr}"),
816 }
817 }
818}
819
820impl From<IpAddr> for IpAddress {
821 fn from(addr: IpAddr) -> IpAddress {
822 IpAddress::Exact(addr)
823 }
824}
825
826impl str::FromStr for IpAddress {
827 type Err = AddrParseError;
828
829 fn from_str(string: &str) -> Result<IpAddress, AddrParseError> {
830 match string {
831 "{{auto}}" => Ok(IpAddress::Auto),
832 other => other.parse().map(IpAddress::Exact),
833 }
834 }
835}
836
837impl_str_serde!(IpAddress);
838
839#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
841pub struct User {
842 #[serde(default, skip_serializing_if = "Option::is_none")]
844 pub id: Option<String>,
845 #[serde(default, skip_serializing_if = "Option::is_none")]
847 pub email: Option<String>,
848 #[serde(default, skip_serializing_if = "Option::is_none")]
850 pub ip_address: Option<IpAddress>,
851 #[serde(default, skip_serializing_if = "Option::is_none")]
853 pub username: Option<String>,
854 #[serde(flatten)]
856 pub other: Map<String, Value>,
857}
858
859#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
861pub struct Request {
862 #[serde(default, skip_serializing_if = "Option::is_none")]
864 pub url: Option<Url>,
865 #[serde(default, skip_serializing_if = "Option::is_none")]
867 pub method: Option<String>,
868 #[serde(default, skip_serializing_if = "Option::is_none")]
871 pub data: Option<String>,
872 #[serde(default, skip_serializing_if = "Option::is_none")]
874 pub query_string: Option<String>,
875 #[serde(default, skip_serializing_if = "Option::is_none")]
877 pub cookies: Option<String>,
878 #[serde(default, skip_serializing_if = "Map::is_empty")]
880 pub headers: Map<String, String>,
881 #[serde(default, skip_serializing_if = "Map::is_empty")]
883 pub env: Map<String, String>,
884}
885
886#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
891pub struct SystemSdkInfo {
892 pub sdk_name: String,
894 pub version_major: u32,
896 pub version_minor: u32,
898 pub version_patchlevel: u32,
900}
901
902#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
904#[serde(rename_all = "snake_case", tag = "type")]
905pub enum DebugImage {
906 Apple(AppleDebugImage),
909 Symbolic(SymbolicDebugImage),
911 Proguard(ProguardDebugImage),
913 Wasm(WasmDebugImage),
916}
917
918impl DebugImage {
919 pub fn type_name(&self) -> &str {
921 match *self {
922 DebugImage::Apple(..) => "apple",
923 DebugImage::Symbolic(..) => "symbolic",
924 DebugImage::Proguard(..) => "proguard",
925 DebugImage::Wasm(..) => "wasm",
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#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
942pub struct AppleDebugImage {
943 pub name: String,
945 pub arch: Option<String>,
947 pub cpu_type: Option<u32>,
949 pub cpu_subtype: Option<u32>,
951 pub image_addr: Addr,
953 pub image_size: u64,
955 #[serde(default, skip_serializing_if = "Addr::is_null")]
957 pub image_vmaddr: Addr,
958 pub uuid: Uuid,
960}
961
962#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
964pub struct SymbolicDebugImage {
965 pub name: String,
970 pub arch: Option<String>,
972 pub image_addr: Addr,
976 pub image_size: u64,
980 #[serde(default, skip_serializing_if = "Addr::is_null")]
988 pub image_vmaddr: Addr,
989 pub id: DebugId,
993
994 #[serde(default, skip_serializing_if = "Option::is_none")]
996 pub code_id: Option<CodeId>,
997 #[serde(default, skip_serializing_if = "Option::is_none")]
999 pub debug_file: Option<String>,
1000}
1001
1002#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1004pub struct ProguardDebugImage {
1005 pub uuid: Uuid,
1007}
1008
1009#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1011pub struct WasmDebugImage {
1012 pub name: String,
1014 pub debug_id: Uuid,
1016 #[serde(default, skip_serializing_if = "Option::is_none")]
1021 pub debug_file: Option<String>,
1022 #[serde(default, skip_serializing_if = "Option::is_none")]
1025 pub code_id: Option<String>,
1026 pub code_file: String,
1029}
1030
1031into_debug_image!(Apple, AppleDebugImage);
1032into_debug_image!(Symbolic, SymbolicDebugImage);
1033into_debug_image!(Proguard, ProguardDebugImage);
1034into_debug_image!(Wasm, WasmDebugImage);
1035
1036#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
1038pub struct DebugMeta {
1039 #[serde(default, skip_serializing_if = "Option::is_none")]
1041 pub sdk_info: Option<SystemSdkInfo>,
1042 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1044 pub images: Vec<DebugImage>,
1045}
1046
1047impl DebugMeta {
1048 pub fn is_empty(&self) -> bool {
1052 self.sdk_info.is_none() && self.images.is_empty()
1053 }
1054}
1055
1056#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1058pub struct ClientSdkInfo {
1059 pub name: String,
1061 pub version: String,
1063 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1065 pub integrations: Vec<String>,
1066 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1068 pub packages: Vec<ClientSdkPackage>,
1069}
1070
1071#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1073pub struct ClientSdkPackage {
1074 pub name: String,
1076 pub version: String,
1078}
1079
1080#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1085#[serde(rename_all = "snake_case", tag = "type")]
1086#[non_exhaustive]
1087pub enum Context {
1088 Device(Box<DeviceContext>),
1090 Os(Box<OsContext>),
1092 Runtime(Box<RuntimeContext>),
1094 App(Box<AppContext>),
1096 Browser(Box<BrowserContext>),
1098 Trace(Box<TraceContext>),
1100 Gpu(Box<GpuContext>),
1102 Otel(Box<OtelContext>),
1104 Response(Box<ResponseContext>),
1106 #[serde(rename = "unknown")]
1108 Other(Map<String, Value>),
1109}
1110
1111impl Context {
1112 pub fn type_name(&self) -> &str {
1114 match *self {
1115 Context::Device(..) => "device",
1116 Context::Os(..) => "os",
1117 Context::Runtime(..) => "runtime",
1118 Context::App(..) => "app",
1119 Context::Browser(..) => "browser",
1120 Context::Trace(..) => "trace",
1121 Context::Gpu(..) => "gpu",
1122 Context::Otel(..) => "otel",
1123 Context::Response(..) => "response",
1124 Context::Other(..) => "unknown",
1125 }
1126 }
1127}
1128
1129#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
1131#[serde(rename_all = "lowercase")]
1132pub enum Orientation {
1133 Portrait,
1135 Landscape,
1137}
1138
1139#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1141pub struct DeviceContext {
1142 #[serde(default, skip_serializing_if = "Option::is_none")]
1144 pub name: Option<String>,
1145 #[serde(default, skip_serializing_if = "Option::is_none")]
1147 pub family: Option<String>,
1148 #[serde(default, skip_serializing_if = "Option::is_none")]
1150 pub model: Option<String>,
1151 #[serde(default, skip_serializing_if = "Option::is_none")]
1153 pub model_id: Option<String>,
1154 #[serde(default, skip_serializing_if = "Option::is_none")]
1156 pub arch: Option<String>,
1157 #[serde(default, skip_serializing_if = "Option::is_none")]
1159 pub battery_level: Option<f32>,
1160 #[serde(default, skip_serializing_if = "Option::is_none")]
1162 pub orientation: Option<Orientation>,
1163 #[serde(default, skip_serializing_if = "Option::is_none")]
1165 pub simulator: Option<bool>,
1166 #[serde(default, skip_serializing_if = "Option::is_none")]
1168 pub memory_size: Option<u64>,
1169 #[serde(default, skip_serializing_if = "Option::is_none")]
1171 pub free_memory: Option<u64>,
1172 #[serde(default, skip_serializing_if = "Option::is_none")]
1174 pub usable_memory: Option<u64>,
1175 #[serde(default, skip_serializing_if = "Option::is_none")]
1177 pub storage_size: Option<u64>,
1178 #[serde(default, skip_serializing_if = "Option::is_none")]
1180 pub free_storage: Option<u64>,
1181 #[serde(default, skip_serializing_if = "Option::is_none")]
1183 pub external_storage_size: Option<u64>,
1184 #[serde(default, skip_serializing_if = "Option::is_none")]
1186 pub external_free_storage: Option<u64>,
1187 #[serde(
1189 default,
1190 skip_serializing_if = "Option::is_none",
1191 with = "ts_rfc3339_opt"
1192 )]
1193 pub boot_time: Option<SystemTime>,
1194 #[serde(default, skip_serializing_if = "Option::is_none")]
1196 pub timezone: Option<String>,
1197 #[serde(flatten)]
1199 pub other: Map<String, Value>,
1200}
1201
1202#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1204pub struct OsContext {
1205 #[serde(default, skip_serializing_if = "Option::is_none")]
1207 pub name: Option<String>,
1208 #[serde(default, skip_serializing_if = "Option::is_none")]
1210 pub version: Option<String>,
1211 #[serde(default, skip_serializing_if = "Option::is_none")]
1213 pub build: Option<String>,
1214 #[serde(default, skip_serializing_if = "Option::is_none")]
1216 pub kernel_version: Option<String>,
1217 #[serde(default, skip_serializing_if = "Option::is_none")]
1219 pub rooted: Option<bool>,
1220 #[serde(flatten)]
1222 pub other: Map<String, Value>,
1223}
1224
1225#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1227pub struct RuntimeContext {
1228 #[serde(default, skip_serializing_if = "Option::is_none")]
1230 pub name: Option<String>,
1231 #[serde(default, skip_serializing_if = "Option::is_none")]
1233 pub version: Option<String>,
1234 #[serde(flatten)]
1236 pub other: Map<String, Value>,
1237}
1238
1239#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1241pub struct AppContext {
1242 #[serde(
1244 default,
1245 skip_serializing_if = "Option::is_none",
1246 with = "ts_rfc3339_opt"
1247 )]
1248 pub app_start_time: Option<SystemTime>,
1249 #[serde(default, skip_serializing_if = "Option::is_none")]
1251 pub device_app_hash: Option<String>,
1252 #[serde(default, skip_serializing_if = "Option::is_none")]
1254 pub build_type: Option<String>,
1255 #[serde(default, skip_serializing_if = "Option::is_none")]
1257 pub app_identifier: Option<String>,
1258 #[serde(default, skip_serializing_if = "Option::is_none")]
1260 pub app_name: Option<String>,
1261 #[serde(default, skip_serializing_if = "Option::is_none")]
1263 pub app_version: Option<String>,
1264 #[serde(default, skip_serializing_if = "Option::is_none")]
1266 pub app_build: Option<String>,
1267 #[serde(flatten)]
1269 pub other: Map<String, Value>,
1270}
1271
1272#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1274pub struct BrowserContext {
1275 #[serde(default, skip_serializing_if = "Option::is_none")]
1277 pub name: Option<String>,
1278 #[serde(default, skip_serializing_if = "Option::is_none")]
1280 pub version: Option<String>,
1281 #[serde(flatten)]
1283 pub other: Map<String, Value>,
1284}
1285
1286#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1288pub struct GpuContext {
1289 pub name: String,
1291 #[serde(default, skip_serializing_if = "Option::is_none")]
1293 pub version: Option<String>,
1294 #[serde(default, skip_serializing_if = "Option::is_none")]
1296 pub driver_version: Option<String>,
1297 #[serde(default, skip_serializing_if = "Option::is_none")]
1299 pub id: Option<String>,
1300 #[serde(default, skip_serializing_if = "Option::is_none")]
1302 pub vendor_id: Option<String>,
1303 #[serde(default, skip_serializing_if = "Option::is_none")]
1305 pub vendor_name: Option<String>,
1306 #[serde(default, skip_serializing_if = "Option::is_none")]
1308 pub memory_size: Option<u32>,
1309 #[serde(default, skip_serializing_if = "Option::is_none")]
1311 pub api_type: Option<String>,
1312 #[serde(default, skip_serializing_if = "Option::is_none")]
1314 pub multi_threaded_rendering: Option<bool>,
1315 #[serde(default, skip_serializing_if = "Option::is_none")]
1317 pub npot_support: Option<bool>,
1318 #[serde(default, skip_serializing_if = "Option::is_none")]
1320 pub max_texture_size: Option<u32>,
1321 #[serde(default, skip_serializing_if = "Option::is_none")]
1324 pub graphics_shader_level: Option<String>,
1325 #[serde(default, skip_serializing_if = "Option::is_none")]
1327 pub supports_draw_call_instancing: Option<bool>,
1328 #[serde(default, skip_serializing_if = "Option::is_none")]
1330 pub supports_ray_tracing: Option<bool>,
1331 #[serde(default, skip_serializing_if = "Option::is_none")]
1333 pub supports_compute_shaders: Option<bool>,
1334 #[serde(default, skip_serializing_if = "Option::is_none")]
1336 pub supports_geometry_shaders: Option<bool>,
1337 #[serde(flatten)]
1339 pub other: Map<String, Value>,
1340}
1341
1342#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1344pub struct OtelContext {
1345 #[serde(default, skip_serializing_if = "Map::is_empty")]
1348 pub attributes: Map<String, Value>,
1349 #[serde(default, skip_serializing_if = "Map::is_empty")]
1352 pub resource: Map<String, Value>,
1353 #[serde(flatten)]
1355 pub other: Map<String, Value>,
1356}
1357
1358#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1360pub struct ResponseContext {
1361 #[serde(default, skip_serializing_if = "Option::is_none")]
1363 pub cookies: Option<String>,
1364 #[serde(default, skip_serializing_if = "Map::is_empty")]
1369 pub headers: Map<String, String>,
1370 #[serde(default, skip_serializing_if = "Option::is_none")]
1372 pub status_code: Option<u64>,
1373 #[serde(default, skip_serializing_if = "Option::is_none")]
1375 pub body_size: Option<u64>,
1376 #[serde(default, skip_serializing_if = "Option::is_none")]
1378 pub data: Option<Value>,
1379}
1380
1381#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash)]
1383#[serde(try_from = "String", into = "String")]
1384pub struct SpanId([u8; 8]);
1385
1386impl Default for SpanId {
1387 fn default() -> Self {
1388 Self(rand::random())
1389 }
1390}
1391
1392impl fmt::Display for SpanId {
1393 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1394 write!(fmt, "{}", hex::encode(self.0))
1395 }
1396}
1397
1398impl fmt::Debug for SpanId {
1399 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1400 write!(fmt, "SpanId({self})")
1401 }
1402}
1403
1404impl From<SpanId> for String {
1405 fn from(span_id: SpanId) -> Self {
1406 span_id.to_string()
1407 }
1408}
1409
1410impl str::FromStr for SpanId {
1411 type Err = hex::FromHexError;
1412
1413 fn from_str(input: &str) -> Result<Self, Self::Err> {
1414 let mut buf = [0; 8];
1415 hex::decode_to_slice(input, &mut buf)?;
1416 Ok(Self(buf))
1417 }
1418}
1419
1420impl TryFrom<String> for SpanId {
1421 type Error = hex::FromHexError;
1422
1423 fn try_from(value: String) -> Result<Self, Self::Error> {
1424 value.parse()
1425 }
1426}
1427
1428impl From<[u8; 8]> for SpanId {
1429 fn from(value: [u8; 8]) -> Self {
1430 Self(value)
1431 }
1432}
1433
1434#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash)]
1436#[serde(try_from = "String", into = "String")]
1437pub struct TraceId([u8; 16]);
1438
1439impl Default for TraceId {
1440 fn default() -> Self {
1441 Self(rand::random())
1442 }
1443}
1444
1445impl fmt::Display for TraceId {
1446 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1447 write!(fmt, "{}", hex::encode(self.0))
1448 }
1449}
1450
1451impl fmt::Debug for TraceId {
1452 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1453 write!(fmt, "TraceId({self})")
1454 }
1455}
1456
1457impl From<TraceId> for String {
1458 fn from(trace_id: TraceId) -> Self {
1459 trace_id.to_string()
1460 }
1461}
1462
1463impl str::FromStr for TraceId {
1464 type Err = hex::FromHexError;
1465
1466 fn from_str(input: &str) -> Result<Self, Self::Err> {
1467 let mut buf = [0; 16];
1468 hex::decode_to_slice(input, &mut buf)?;
1469 Ok(Self(buf))
1470 }
1471}
1472
1473impl TryFrom<String> for TraceId {
1474 type Error = hex::FromHexError;
1475
1476 fn try_from(value: String) -> Result<Self, Self::Error> {
1477 value.parse()
1478 }
1479}
1480
1481impl From<[u8; 16]> for TraceId {
1482 fn from(value: [u8; 16]) -> Self {
1483 Self(value)
1484 }
1485}
1486
1487#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1489pub struct TraceContext {
1490 #[serde(default)]
1492 pub span_id: SpanId,
1493 #[serde(default)]
1495 pub trace_id: TraceId,
1496 #[serde(default, skip_serializing_if = "Option::is_none")]
1498 pub parent_span_id: Option<SpanId>,
1499 #[serde(default, skip_serializing_if = "Option::is_none")]
1501 pub op: Option<String>,
1502 #[serde(default, skip_serializing_if = "Option::is_none")]
1504 pub description: Option<String>,
1505 #[serde(default, skip_serializing_if = "Option::is_none")]
1507 pub status: Option<SpanStatus>,
1508 #[serde(default, skip_serializing_if = "Option::is_none")]
1511 pub origin: Option<String>,
1512 #[serde(default, skip_serializing_if = "Map::is_empty")]
1514 pub data: Map<String, Value>,
1515}
1516
1517macro_rules! into_context {
1518 ($kind:ident, $ty:ty) => {
1519 impl From<$ty> for Context {
1520 fn from(data: $ty) -> Self {
1521 Context::$kind(Box::new(data))
1522 }
1523 }
1524 };
1525}
1526
1527into_context!(App, AppContext);
1528into_context!(Device, DeviceContext);
1529into_context!(Os, OsContext);
1530into_context!(Runtime, RuntimeContext);
1531into_context!(Browser, BrowserContext);
1532into_context!(Trace, TraceContext);
1533into_context!(Gpu, GpuContext);
1534into_context!(Otel, OtelContext);
1535into_context!(Response, ResponseContext);
1536
1537const INFERABLE_CONTEXTS: &[&str] = &[
1538 "device", "os", "runtime", "app", "browser", "trace", "gpu", "otel", "response",
1539];
1540
1541struct ContextsVisitor;
1542
1543impl<'de> de::Visitor<'de> for ContextsVisitor {
1544 type Value = Map<String, Context>;
1545
1546 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1547 formatter.write_str("contexts object")
1548 }
1549
1550 fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
1551 where
1552 A: de::MapAccess<'de>,
1553 {
1554 let mut map: Map<String, Context> = Map::new();
1555
1556 while let Some((key, mut value)) = access.next_entry::<String, Value>()? {
1557 let typed_value = value
1558 .as_object_mut()
1559 .map(|ctx| {
1560 if !ctx.contains_key("type") {
1561 let type_key = if INFERABLE_CONTEXTS.contains(&key.as_str()) {
1562 key.clone().into()
1563 } else {
1564 Value::String("unknown".into())
1565 };
1566 ctx.insert(String::from("type"), type_key);
1567 }
1568 ctx.to_owned()
1569 })
1570 .ok_or_else(|| de::Error::custom("expected valid `context` object"))?;
1571
1572 match serde_json::from_value(serde_json::to_value(typed_value).unwrap()) {
1573 Ok(context) => {
1574 map.insert(key, context);
1575 }
1576 Err(e) => return Err(de::Error::custom(e.to_string())),
1577 }
1578 }
1579
1580 Ok(map)
1581 }
1582}
1583
1584fn deserialize_contexts<'de, D>(deserializer: D) -> Result<Map<String, Context>, D::Error>
1585where
1586 D: Deserializer<'de>,
1587{
1588 deserializer.deserialize_map(ContextsVisitor {})
1589}
1590
1591mod event {
1592 use super::*;
1593
1594 pub fn default_id() -> Uuid {
1595 crate::random_uuid()
1596 }
1597
1598 pub fn serialize_id<S: Serializer>(uuid: &Uuid, serializer: S) -> Result<S::Ok, S::Error> {
1599 serializer.serialize_some(&uuid.as_simple().to_string())
1600 }
1601
1602 pub fn default_level() -> Level {
1603 Level::Error
1604 }
1605
1606 pub fn default_platform() -> Cow<'static, str> {
1607 Cow::Borrowed("other")
1608 }
1609
1610 pub fn is_default_platform(value: &str) -> bool {
1611 value == "other"
1612 }
1613
1614 static DEFAULT_FINGERPRINT: &[Cow<'static, str>] = &[Cow::Borrowed("{{ default }}")];
1615
1616 pub fn default_fingerprint<'a>() -> Cow<'a, [Cow<'a, str>]> {
1617 Cow::Borrowed(DEFAULT_FINGERPRINT)
1618 }
1619
1620 pub fn is_default_fingerprint(fp: &[Cow<'_, str>]) -> bool {
1621 fp.len() == 1 && ((fp)[0] == "{{ default }}" || (fp)[0] == "{{default}}")
1622 }
1623}
1624
1625#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1627pub struct Event<'a> {
1628 #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
1630 pub event_id: Uuid,
1631 #[serde(
1633 default = "event::default_level",
1634 skip_serializing_if = "Level::is_error"
1635 )]
1636 pub level: Level,
1637 #[serde(
1639 default = "event::default_fingerprint",
1640 skip_serializing_if = "event::is_default_fingerprint"
1641 )]
1642 pub fingerprint: Cow<'a, [Cow<'a, str>]>,
1643 #[serde(default, skip_serializing_if = "Option::is_none")]
1645 pub culprit: Option<String>,
1646 #[serde(default, skip_serializing_if = "Option::is_none")]
1648 pub transaction: Option<String>,
1649 #[serde(default, skip_serializing_if = "Option::is_none")]
1651 pub message: Option<String>,
1652 #[serde(default, skip_serializing_if = "Option::is_none")]
1655 pub logentry: Option<LogEntry>,
1656 #[serde(default, skip_serializing_if = "Option::is_none")]
1658 pub logger: Option<String>,
1659 #[serde(default, skip_serializing_if = "Map::is_empty")]
1661 pub modules: Map<String, String>,
1662 #[serde(
1664 default = "event::default_platform",
1665 skip_serializing_if = "event::is_default_platform"
1666 )]
1667 pub platform: Cow<'a, str>,
1668 #[serde(default = "SystemTime::now", with = "ts_seconds_float")]
1672 pub timestamp: SystemTime,
1673 #[serde(default, skip_serializing_if = "Option::is_none")]
1675 pub server_name: Option<Cow<'a, str>>,
1676 #[serde(default, skip_serializing_if = "Option::is_none")]
1678 pub release: Option<Cow<'a, str>>,
1679 #[serde(default, skip_serializing_if = "Option::is_none")]
1681 pub dist: Option<Cow<'a, str>>,
1682 #[serde(default, skip_serializing_if = "Option::is_none")]
1684 pub environment: Option<Cow<'a, str>>,
1685 #[serde(default, skip_serializing_if = "Option::is_none")]
1687 pub user: Option<User>,
1688 #[serde(default, skip_serializing_if = "Option::is_none")]
1690 pub request: Option<Request>,
1691 #[serde(
1693 default,
1694 skip_serializing_if = "Map::is_empty",
1695 deserialize_with = "deserialize_contexts"
1696 )]
1697 pub contexts: Map<String, Context>,
1698 #[serde(default, skip_serializing_if = "Values::is_empty")]
1700 pub breadcrumbs: Values<Breadcrumb>,
1701 #[serde(default, skip_serializing_if = "Values::is_empty")]
1703 pub exception: Values<Exception>,
1704 #[serde(default, skip_serializing_if = "Option::is_none")]
1706 pub stacktrace: Option<Stacktrace>,
1707 #[serde(default, skip_serializing_if = "Option::is_none")]
1709 pub template: Option<TemplateInfo>,
1710 #[serde(default, skip_serializing_if = "Values::is_empty")]
1712 pub threads: Values<Thread>,
1713 #[serde(default, skip_serializing_if = "Map::is_empty")]
1715 pub tags: Map<String, String>,
1716 #[serde(default, skip_serializing_if = "Map::is_empty")]
1718 pub extra: Map<String, Value>,
1719 #[serde(default, skip_serializing_if = "DebugMeta::is_empty")]
1721 pub debug_meta: Cow<'a, DebugMeta>,
1722 #[serde(default, skip_serializing_if = "Option::is_none")]
1724 pub sdk: Option<Cow<'a, ClientSdkInfo>>,
1725}
1726
1727impl Default for Event<'_> {
1728 fn default() -> Self {
1729 Event {
1730 event_id: event::default_id(),
1731 level: event::default_level(),
1732 fingerprint: event::default_fingerprint(),
1733 culprit: Default::default(),
1734 transaction: Default::default(),
1735 message: Default::default(),
1736 logentry: Default::default(),
1737 logger: Default::default(),
1738 modules: Default::default(),
1739 platform: event::default_platform(),
1740 timestamp: SystemTime::now(),
1741 server_name: Default::default(),
1742 release: Default::default(),
1743 dist: Default::default(),
1744 environment: Default::default(),
1745 user: Default::default(),
1746 request: Default::default(),
1747 contexts: Default::default(),
1748 breadcrumbs: Default::default(),
1749 exception: Default::default(),
1750 stacktrace: Default::default(),
1751 template: Default::default(),
1752 threads: Default::default(),
1753 tags: Default::default(),
1754 extra: Default::default(),
1755 debug_meta: Default::default(),
1756 sdk: Default::default(),
1757 }
1758 }
1759}
1760
1761impl<'a> Event<'a> {
1762 pub fn new() -> Event<'a> {
1764 Default::default()
1765 }
1766
1767 pub fn into_owned(self) -> Event<'static> {
1769 Event {
1770 event_id: self.event_id,
1771 level: self.level,
1772 fingerprint: Cow::Owned(
1773 self.fingerprint
1774 .iter()
1775 .map(|x| Cow::Owned(x.to_string()))
1776 .collect(),
1777 ),
1778 culprit: self.culprit,
1779 transaction: self.transaction,
1780 message: self.message,
1781 logentry: self.logentry,
1782 logger: self.logger,
1783 modules: self.modules,
1784 platform: Cow::Owned(self.platform.into_owned()),
1785 timestamp: self.timestamp,
1786 server_name: self.server_name.map(|x| Cow::Owned(x.into_owned())),
1787 release: self.release.map(|x| Cow::Owned(x.into_owned())),
1788 dist: self.dist.map(|x| Cow::Owned(x.into_owned())),
1789 environment: self.environment.map(|x| Cow::Owned(x.into_owned())),
1790 user: self.user,
1791 request: self.request,
1792 contexts: self.contexts,
1793 breadcrumbs: self.breadcrumbs,
1794 exception: self.exception,
1795 stacktrace: self.stacktrace,
1796 template: self.template,
1797 threads: self.threads,
1798 tags: self.tags,
1799 extra: self.extra,
1800 debug_meta: Cow::Owned(self.debug_meta.into_owned()),
1801 sdk: self.sdk.map(|x| Cow::Owned(x.into_owned())),
1802 }
1803 }
1804}
1805
1806impl fmt::Display for Event<'_> {
1807 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1808 write!(
1809 f,
1810 "Event(id: {}, ts: {})",
1811 self.event_id,
1812 crate::utils::to_rfc3339(&self.timestamp)
1813 )
1814 }
1815}
1816
1817#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1819pub struct Span {
1820 #[serde(default)]
1822 pub span_id: SpanId,
1823 #[serde(default)]
1825 pub trace_id: TraceId,
1826 #[serde(default, skip_serializing_if = "Option::is_none")]
1828 pub parent_span_id: Option<SpanId>,
1829 #[serde(default, skip_serializing_if = "Option::is_none")]
1831 pub same_process_as_parent: Option<bool>,
1832 #[serde(default, skip_serializing_if = "Option::is_none")]
1834 pub op: Option<String>,
1835 #[serde(default, skip_serializing_if = "Option::is_none")]
1838 pub description: Option<String>,
1839 #[serde(
1841 default,
1842 skip_serializing_if = "Option::is_none",
1843 with = "ts_rfc3339_opt"
1844 )]
1845 pub timestamp: Option<SystemTime>,
1846 #[serde(default = "SystemTime::now", with = "ts_seconds_float")]
1848 pub start_timestamp: SystemTime,
1849 #[serde(default, skip_serializing_if = "Option::is_none")]
1851 pub status: Option<SpanStatus>,
1852 #[serde(default, skip_serializing_if = "Map::is_empty")]
1854 pub tags: Map<String, String>,
1855 #[serde(default, skip_serializing_if = "Map::is_empty")]
1857 pub data: Map<String, Value>,
1858}
1859
1860impl Default for Span {
1861 fn default() -> Self {
1862 Span {
1863 span_id: Default::default(),
1864 trace_id: Default::default(),
1865 timestamp: Default::default(),
1866 tags: Default::default(),
1867 start_timestamp: SystemTime::now(),
1868 description: Default::default(),
1869 status: Default::default(),
1870 parent_span_id: Default::default(),
1871 same_process_as_parent: Default::default(),
1872 op: Default::default(),
1873 data: Default::default(),
1874 }
1875 }
1876}
1877
1878impl Span {
1879 pub fn new() -> Span {
1881 Default::default()
1882 }
1883
1884 pub fn finish_with_timestamp(&mut self, timestamp: SystemTime) {
1886 self.timestamp = Some(timestamp);
1887 }
1888
1889 pub fn finish(&mut self) {
1891 self.timestamp = Some(SystemTime::now());
1892 }
1893}
1894
1895impl fmt::Display for Span {
1896 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1897 write!(
1898 f,
1899 "Span(id: {}, ts: {})",
1900 self.span_id,
1901 crate::utils::to_rfc3339(&self.start_timestamp)
1902 )
1903 }
1904}
1905
1906#[derive(Debug, Error)]
1908#[error("invalid status")]
1909pub struct ParseStatusError;
1910
1911#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)]
1913#[non_exhaustive]
1914pub enum SpanStatus {
1915 #[serde(rename = "ok")]
1917 Ok,
1918 #[serde(rename = "deadline_exceeded")]
1920 DeadlineExceeded,
1921 #[serde(rename = "unauthenticated")]
1923 Unauthenticated,
1924 #[serde(rename = "permission_denied")]
1926 PermissionDenied,
1927 #[serde(rename = "not_found")]
1929 NotFound,
1930 #[serde(rename = "resource_exhausted")]
1932 ResourceExhausted,
1933 #[serde(rename = "invalid_argument")]
1935 InvalidArgument,
1936 #[serde(rename = "unimplemented")]
1938 Unimplemented,
1939 #[serde(rename = "unavailable")]
1941 Unavailable,
1942 #[serde(rename = "internal_error")]
1944 InternalError,
1945 #[serde(rename = "unknown_error")]
1947 UnknownError,
1948 #[serde(rename = "cancelled")]
1950 Cancelled,
1951 #[serde(rename = "already_exists")]
1953 AlreadyExists,
1954 #[serde(rename = "failed_precondition")]
1956 FailedPrecondition,
1957 #[serde(rename = "aborted")]
1959 Aborted,
1960 #[serde(rename = "out_of_range")]
1962 OutOfRange,
1963 #[serde(rename = "data_loss")]
1965 DataLoss,
1966}
1967
1968impl str::FromStr for SpanStatus {
1969 type Err = ParseStatusError;
1970
1971 fn from_str(s: &str) -> Result<SpanStatus, Self::Err> {
1972 Ok(match s {
1973 "ok" => SpanStatus::Ok,
1974 "deadline_exceeded" => SpanStatus::DeadlineExceeded,
1975 "unauthenticated" => SpanStatus::Unauthenticated,
1976 "permission_denied" => SpanStatus::PermissionDenied,
1977 "not_found" => SpanStatus::NotFound,
1978 "resource_exhausted" => SpanStatus::ResourceExhausted,
1979 "invalid_argument" => SpanStatus::InvalidArgument,
1980 "unimplemented" => SpanStatus::Unimplemented,
1981 "unavailable" => SpanStatus::Unavailable,
1982 "internal_error" => SpanStatus::InternalError,
1983 "unknown_error" => SpanStatus::UnknownError,
1984 "cancelled" => SpanStatus::Cancelled,
1985 "already_exists" => SpanStatus::AlreadyExists,
1986 "failed_precondition" => SpanStatus::FailedPrecondition,
1987 "aborted" => SpanStatus::Aborted,
1988 "out_of_range" => SpanStatus::OutOfRange,
1989 "data_loss" => SpanStatus::DataLoss,
1990 _ => return Err(ParseStatusError),
1991 })
1992 }
1993}
1994
1995impl fmt::Display for SpanStatus {
1996 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1997 match self {
1998 SpanStatus::Ok => write!(f, "ok"),
1999 SpanStatus::DeadlineExceeded => write!(f, "deadline_exceeded"),
2000 SpanStatus::Unauthenticated => write!(f, "unauthenticated"),
2001 SpanStatus::PermissionDenied => write!(f, "permission_denied"),
2002 SpanStatus::NotFound => write!(f, "not_found"),
2003 SpanStatus::ResourceExhausted => write!(f, "resource_exhausted"),
2004 SpanStatus::InvalidArgument => write!(f, "invalid_argument"),
2005 SpanStatus::Unimplemented => write!(f, "unimplemented"),
2006 SpanStatus::Unavailable => write!(f, "unavailable"),
2007 SpanStatus::InternalError => write!(f, "internal_error"),
2008 SpanStatus::UnknownError => write!(f, "unknown_error"),
2009 SpanStatus::Cancelled => write!(f, "cancelled"),
2010 SpanStatus::AlreadyExists => write!(f, "already_exists"),
2011 SpanStatus::FailedPrecondition => write!(f, "failed_precondition"),
2012 SpanStatus::Aborted => write!(f, "aborted"),
2013 SpanStatus::OutOfRange => write!(f, "out_of_range"),
2014 SpanStatus::DataLoss => write!(f, "data_loss"),
2015 }
2016 }
2017}
2018
2019#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
2021pub struct Transaction<'a> {
2022 #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
2024 pub event_id: Uuid,
2025 #[serde(
2027 rename = "transaction",
2028 default,
2029 skip_serializing_if = "Option::is_none"
2030 )]
2031 pub name: Option<String>,
2032 #[serde(default, skip_serializing_if = "Option::is_none")]
2034 pub release: Option<Cow<'a, str>>,
2035 #[serde(default, skip_serializing_if = "Option::is_none")]
2037 pub environment: Option<Cow<'a, str>>,
2038 #[serde(default, skip_serializing_if = "Option::is_none")]
2040 pub user: Option<User>,
2041 #[serde(default, skip_serializing_if = "Map::is_empty")]
2043 pub tags: Map<String, String>,
2044 #[serde(default, skip_serializing_if = "Map::is_empty")]
2046 pub extra: Map<String, Value>,
2047 #[serde(default, skip_serializing_if = "Option::is_none")]
2049 pub sdk: Option<Cow<'a, ClientSdkInfo>>,
2050 #[serde(
2052 default = "event::default_platform",
2053 skip_serializing_if = "event::is_default_platform"
2054 )]
2055 pub platform: Cow<'a, str>,
2056 #[serde(
2058 default,
2059 skip_serializing_if = "Option::is_none",
2060 with = "ts_rfc3339_opt"
2061 )]
2062 pub timestamp: Option<SystemTime>,
2063 #[serde(default = "SystemTime::now", with = "ts_seconds_float")]
2065 pub start_timestamp: SystemTime,
2066 pub spans: Vec<Span>,
2068 #[serde(
2070 default,
2071 skip_serializing_if = "Map::is_empty",
2072 deserialize_with = "deserialize_contexts"
2073 )]
2074 pub contexts: Map<String, Context>,
2075 #[serde(default, skip_serializing_if = "Option::is_none")]
2077 pub request: Option<Request>,
2078 #[serde(default, skip_serializing_if = "Option::is_none")]
2080 pub server_name: Option<Cow<'a, str>>,
2081}
2082
2083impl Default for Transaction<'_> {
2084 fn default() -> Self {
2085 Transaction {
2086 event_id: event::default_id(),
2087 name: Default::default(),
2088 user: Default::default(),
2089 tags: Default::default(),
2090 extra: Default::default(),
2091 release: Default::default(),
2092 environment: Default::default(),
2093 sdk: Default::default(),
2094 platform: event::default_platform(),
2095 timestamp: Default::default(),
2096 start_timestamp: SystemTime::now(),
2097 spans: Default::default(),
2098 contexts: Default::default(),
2099 request: Default::default(),
2100 server_name: Default::default(),
2101 }
2102 }
2103}
2104
2105impl<'a> Transaction<'a> {
2106 pub fn new() -> Transaction<'a> {
2108 Default::default()
2109 }
2110
2111 pub fn into_owned(self) -> Transaction<'static> {
2113 Transaction {
2114 event_id: self.event_id,
2115 name: self.name,
2116 user: self.user,
2117 tags: self.tags,
2118 extra: self.extra,
2119 release: self.release.map(|x| Cow::Owned(x.into_owned())),
2120 environment: self.environment.map(|x| Cow::Owned(x.into_owned())),
2121 sdk: self.sdk.map(|x| Cow::Owned(x.into_owned())),
2122 platform: Cow::Owned(self.platform.into_owned()),
2123 timestamp: self.timestamp,
2124 start_timestamp: self.start_timestamp,
2125 spans: self.spans,
2126 contexts: self.contexts,
2127 request: self.request,
2128 server_name: self.server_name.map(|x| Cow::Owned(x.into_owned())),
2129 }
2130 }
2131
2132 pub fn finish(&mut self) {
2134 self.timestamp = Some(SystemTime::now());
2135 }
2136
2137 pub fn finish_with_timestamp(&mut self, timestamp: SystemTime) {
2139 self.timestamp = Some(timestamp);
2140 }
2141}
2142
2143impl fmt::Display for Transaction<'_> {
2144 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2145 write!(
2146 f,
2147 "Transaction(id: {}, ts: {})",
2148 self.event_id,
2149 crate::utils::to_rfc3339(&self.start_timestamp)
2150 )
2151 }
2152}
2153
2154#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
2156pub struct Log {
2157 pub level: LogLevel,
2159 pub body: String,
2161 #[serde(default, skip_serializing_if = "Option::is_none")]
2163 pub trace_id: Option<TraceId>,
2164 #[serde(with = "ts_seconds_float")]
2166 pub timestamp: SystemTime,
2167 #[serde(default, skip_serializing_if = "Option::is_none")]
2169 pub severity_number: Option<LogSeverityNumber>,
2170 #[serde(default, skip_serializing_if = "Map::is_empty")]
2172 pub attributes: Map<String, LogAttribute>,
2173}
2174
2175#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
2178#[serde(rename_all = "lowercase")]
2179pub enum LogLevel {
2180 Trace,
2182 Debug,
2184 Info,
2186 Warn,
2188 Error,
2190 Fatal,
2192}
2193
2194#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
2197pub struct LogSeverityNumber(u8);
2198
2199impl LogSeverityNumber {
2200 pub const MIN: u8 = 1;
2202 pub const MAX: u8 = 24;
2204}
2205
2206impl TryFrom<u8> for LogSeverityNumber {
2207 type Error = String;
2208
2209 fn try_from(value: u8) -> Result<Self, Self::Error> {
2210 if (LogSeverityNumber::MIN..=LogSeverityNumber::MAX).contains(&value) {
2211 Ok(Self(value))
2212 } else {
2213 Err(format!(
2214 "Log severity number must be between {} and {}",
2215 LogSeverityNumber::MIN,
2216 LogSeverityNumber::MAX
2217 ))
2218 }
2219 }
2220}
2221
2222#[derive(Clone, Debug, PartialEq)]
2224pub struct LogAttribute(pub Value);
2225
2226impl<T> From<T> for LogAttribute
2227where
2228 Value: From<T>,
2229{
2230 fn from(value: T) -> Self {
2231 Self(Value::from(value))
2232 }
2233}
2234
2235impl Serialize for LogAttribute {
2236 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2237 where
2238 S: serde::Serializer,
2239 {
2240 use serde::ser::SerializeStruct;
2241 let mut state = serializer.serialize_struct("LogAttribute", 2)?;
2242
2243 match &self.0 {
2244 Value::String(s) => {
2245 state.serialize_field("value", s.as_str())?;
2246 state.serialize_field("type", "string")?;
2247 }
2248 Value::Number(n) => {
2249 if let Some(i) = n.as_i64() {
2250 state.serialize_field("value", &i)?;
2251 state.serialize_field("type", "integer")?;
2252 } else if let Some(u) = n.as_u64() {
2253 state.serialize_field("value", &u.to_string())?;
2255 state.serialize_field("type", "string")?;
2256 } else if let Some(f) = n.as_f64() {
2257 state.serialize_field("value", &f)?;
2258 state.serialize_field("type", "double")?;
2259 } else {
2260 state.serialize_field("value", &n.to_string())?;
2262 state.serialize_field("type", "string")?;
2263 }
2264 }
2265 Value::Bool(b) => {
2266 state.serialize_field("value", &b)?;
2267 state.serialize_field("type", "boolean")?;
2268 }
2269 _ => {
2271 state.serialize_field("value", &self.0.to_string())?;
2272 state.serialize_field("type", "string")?;
2273 }
2274 }
2275
2276 state.end()
2277 }
2278}
2279
2280impl<'de> Deserialize<'de> for LogAttribute {
2281 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2282 where
2283 D: serde::Deserializer<'de>,
2284 {
2285 use serde::de::{self, MapAccess, Visitor};
2286 use std::fmt;
2287
2288 struct LogAttributeVisitor;
2289
2290 impl<'de> Visitor<'de> for LogAttributeVisitor {
2291 type Value = LogAttribute;
2292
2293 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2294 formatter.write_str("a LogAttribute with value and type fields")
2295 }
2296
2297 fn visit_map<V>(self, mut map: V) -> Result<LogAttribute, V::Error>
2298 where
2299 V: MapAccess<'de>,
2300 {
2301 let mut value: Option<serde_json::Value> = None;
2302 let mut type_str: Option<String> = None;
2303
2304 while let Some(key) = map.next_key::<String>()? {
2305 match key.as_str() {
2306 "value" => {
2307 if value.is_some() {
2308 return Err(de::Error::duplicate_field("value"));
2309 }
2310 value = Some(map.next_value()?);
2311 }
2312 "type" => {
2313 if type_str.is_some() {
2314 return Err(de::Error::duplicate_field("type"));
2315 }
2316 type_str = Some(map.next_value()?);
2317 }
2318 _ => {
2319 let _: serde_json::Value = map.next_value()?;
2321 }
2322 }
2323 }
2324
2325 let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
2326 let type_str = type_str.ok_or_else(|| de::Error::missing_field("type"))?;
2327
2328 match type_str.as_str() {
2329 "string" => {
2330 if !value.is_string() {
2331 return Err(de::Error::custom(
2332 "type is 'string' but value is not a string",
2333 ));
2334 }
2335 }
2336 "integer" => {
2337 if !value.is_i64() {
2338 return Err(de::Error::custom(
2339 "type is 'integer' but value is not an integer",
2340 ));
2341 }
2342 }
2343 "double" => {
2344 if !value.is_f64() {
2345 return Err(de::Error::custom(
2346 "type is 'double' but value is not a double",
2347 ));
2348 }
2349 }
2350 "boolean" => {
2351 if !value.is_boolean() {
2352 return Err(de::Error::custom(
2353 "type is 'boolean' but value is not a boolean",
2354 ));
2355 }
2356 }
2357 _ => {
2358 return Err(de::Error::custom(format!(
2359 "expected type to be 'string' | 'integer' | 'double' | 'boolean', found {type_str}"
2360 )))
2361 }
2362 }
2363
2364 Ok(LogAttribute(value))
2365 }
2366 }
2367
2368 deserializer.deserialize_map(LogAttributeVisitor)
2369 }
2370}
2371
2372#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
2374#[serde(rename_all = "lowercase")]
2375pub enum MetricType {
2376 Counter,
2378 Gauge,
2380 Distribution,
2382}
2383
2384#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
2388pub struct Metric {
2389 pub r#type: MetricType,
2391 pub name: Cow<'static, str>,
2393 pub value: f64,
2395 #[serde(with = "ts_seconds_float")]
2397 pub timestamp: SystemTime,
2398 pub trace_id: TraceId,
2400 #[serde(default, skip_serializing_if = "Option::is_none")]
2402 pub span_id: Option<SpanId>,
2403 #[serde(default, skip_serializing_if = "Option::is_none")]
2405 pub unit: Option<Unit>,
2406 #[serde(default, skip_serializing_if = "Map::is_empty")]
2408 pub attributes: Map<Cow<'static, str>, LogAttribute>,
2409}
2410
2411#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
2413pub struct OrganizationId(u64);
2414
2415impl From<u64> for OrganizationId {
2416 fn from(value: u64) -> Self {
2417 Self(value)
2418 }
2419}
2420
2421impl std::str::FromStr for OrganizationId {
2422 type Err = std::num::ParseIntError;
2423
2424 fn from_str(s: &str) -> Result<Self, Self::Err> {
2425 s.parse().map(Self)
2426 }
2427}
2428
2429impl std::fmt::Display for OrganizationId {
2430 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2431 write!(f, "{}", self.0)
2432 }
2433}
2434
2435#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
2437pub struct SampleRand(f64);
2438
2439#[derive(Debug, Error)]
2441pub enum InvalidSampleRandError {
2442 #[error("failed to parse f64: {0}")]
2444 InvalidFloat(#[from] std::num::ParseFloatError),
2445
2446 #[error("sample rand value out of admissible interval [0.0, 1.0)")]
2449 OutOfRange,
2450}
2451
2452impl TryFrom<f64> for SampleRand {
2453 type Error = InvalidSampleRandError;
2454
2455 fn try_from(value: f64) -> Result<Self, Self::Error> {
2456 if !(0.0..1.0).contains(&value) {
2457 return Err(InvalidSampleRandError::OutOfRange);
2458 }
2459 Ok(Self(value))
2460 }
2461}
2462
2463impl std::str::FromStr for SampleRand {
2464 type Err = InvalidSampleRandError;
2465
2466 fn from_str(s: &str) -> Result<Self, Self::Err> {
2467 let x: f64 = s.parse().map_err(InvalidSampleRandError::InvalidFloat)?;
2468 Self::try_from(x)
2469 }
2470}
2471
2472impl std::fmt::Display for SampleRand {
2473 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2474 if self.0 >= 0.9999995 {
2478 write!(f, "0.999999")
2479 } else {
2480 write!(f, "{:.6}", self.0)
2481 }
2482 }
2483}
2484
2485#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
2493pub struct DynamicSamplingContext {
2494 #[serde(default, skip_serializing_if = "Option::is_none")]
2497 trace_id: Option<TraceId>,
2498 #[serde(default, skip_serializing_if = "Option::is_none")]
2499 public_key: Option<String>,
2500 #[serde(
2501 default,
2502 skip_serializing_if = "Option::is_none",
2503 with = "display_from_str_opt"
2504 )]
2505 sample_rate: Option<f32>,
2506 #[serde(
2508 default,
2509 skip_serializing_if = "Option::is_none",
2510 with = "display_from_str_opt"
2511 )]
2512 sample_rand: Option<SampleRand>,
2513 #[serde(
2514 default,
2515 skip_serializing_if = "Option::is_none",
2516 with = "display_from_str_opt"
2517 )]
2518 sampled: Option<bool>,
2519 #[serde(default, skip_serializing_if = "Option::is_none")]
2520 release: Option<String>,
2521 #[serde(default, skip_serializing_if = "Option::is_none")]
2522 environment: Option<String>,
2523 #[serde(default, skip_serializing_if = "Option::is_none")]
2524 transaction: Option<String>,
2525 #[serde(
2526 default,
2527 skip_serializing_if = "Option::is_none",
2528 with = "display_from_str_opt"
2529 )]
2530 org_id: Option<OrganizationId>,
2531}
2532
2533impl DynamicSamplingContext {
2534 pub fn new() -> Self {
2536 Default::default()
2537 }
2538
2539 #[must_use]
2541 pub fn with_trace_id(mut self, trace_id: TraceId) -> Self {
2542 self.trace_id = Some(trace_id);
2543 self
2544 }
2545
2546 #[must_use]
2548 pub fn with_public_key(mut self, public_key: String) -> Self {
2549 self.public_key = Some(public_key);
2550 self
2551 }
2552
2553 #[must_use]
2555 pub fn with_sample_rate(mut self, sample_rate: f32) -> Self {
2556 self.sample_rate = Some(sample_rate);
2557 self
2558 }
2559
2560 #[must_use]
2562 pub fn with_sample_rand(mut self, sample_rand: SampleRand) -> Self {
2563 self.sample_rand = Some(sample_rand);
2564 self
2565 }
2566
2567 #[must_use]
2569 pub fn with_sampled(mut self, sampled: bool) -> Self {
2570 self.sampled = Some(sampled);
2571 self
2572 }
2573
2574 #[must_use]
2576 pub fn with_release(mut self, release: String) -> Self {
2577 self.release = Some(release);
2578 self
2579 }
2580
2581 #[must_use]
2583 pub fn with_environment(mut self, environment: String) -> Self {
2584 self.environment = Some(environment);
2585 self
2586 }
2587
2588 #[must_use]
2590 pub fn with_transaction(mut self, transaction: String) -> Self {
2591 self.transaction = Some(transaction);
2592 self
2593 }
2594
2595 #[must_use]
2597 pub fn with_org_id(mut self, org_id: OrganizationId) -> Self {
2598 self.org_id = Some(org_id);
2599 self
2600 }
2601}