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::*;
31
32pub mod value {
34 pub use serde_json::value::{from_value, to_value, Index, Map, Number, Value};
35}
36
37pub mod map {
39 pub use std::collections::btree_map::{BTreeMap as Map, *};
40}
41
42pub mod debugid {
44 pub use debugid::{BreakpadFormat, CodeId, DebugId, ParseDebugIdError};
45}
46
47pub use self::value::Value;
49
50pub use self::map::Map;
52
53#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
60pub struct Values<T> {
61 pub values: Vec<T>,
63}
64
65impl<T> Values<T> {
66 pub fn new() -> Values<T> {
68 Values { values: Vec::new() }
69 }
70
71 pub fn is_empty(&self) -> bool {
73 self.values.is_empty()
74 }
75}
76
77impl<T> Default for Values<T> {
78 fn default() -> Self {
79 Values::new()
81 }
82}
83
84impl<T> From<Vec<T>> for Values<T> {
85 fn from(values: Vec<T>) -> Self {
86 Values { values }
87 }
88}
89
90impl<T> AsRef<[T]> for Values<T> {
91 fn as_ref(&self) -> &[T] {
92 &self.values
93 }
94}
95
96impl<T> AsMut<Vec<T>> for Values<T> {
97 fn as_mut(&mut self) -> &mut Vec<T> {
98 &mut self.values
99 }
100}
101
102impl<T> ops::Deref for Values<T> {
103 type Target = [T];
104
105 fn deref(&self) -> &Self::Target {
106 &self.values
107 }
108}
109
110impl<T> ops::DerefMut for Values<T> {
111 fn deref_mut(&mut self) -> &mut Self::Target {
112 &mut self.values
113 }
114}
115
116impl<T> FromIterator<T> for Values<T> {
117 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
118 Vec::<T>::from_iter(iter).into()
119 }
120}
121
122impl<T> Extend<T> for Values<T> {
123 fn extend<I>(&mut self, iter: I)
124 where
125 I: IntoIterator<Item = T>,
126 {
127 self.values.extend(iter)
128 }
129}
130
131impl<'a, T> IntoIterator for &'a mut Values<T> {
132 type Item = <&'a mut Vec<T> as IntoIterator>::Item;
133 type IntoIter = <&'a mut Vec<T> as IntoIterator>::IntoIter;
134
135 fn into_iter(self) -> Self::IntoIter {
136 self.values.iter_mut()
137 }
138}
139
140impl<'a, T> IntoIterator for &'a Values<T> {
141 type Item = <&'a Vec<T> as IntoIterator>::Item;
142 type IntoIter = <&'a Vec<T> as IntoIterator>::IntoIter;
143
144 fn into_iter(self) -> Self::IntoIter {
145 self.values.iter()
146 }
147}
148
149impl<T> IntoIterator for Values<T> {
150 type Item = <Vec<T> as IntoIterator>::Item;
151 type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
152
153 fn into_iter(self) -> Self::IntoIter {
154 self.values.into_iter()
155 }
156}
157
158#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
163pub struct LogEntry {
164 pub message: String,
166 #[serde(default, skip_serializing_if = "Vec::is_empty")]
168 pub params: Vec<Value>,
169}
170
171#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
173pub struct Frame {
174 #[serde(default, skip_serializing_if = "Option::is_none")]
179 pub function: Option<String>,
180 #[serde(default, skip_serializing_if = "Option::is_none")]
186 pub symbol: Option<String>,
187 #[serde(default, skip_serializing_if = "Option::is_none")]
192 pub module: Option<String>,
193 #[serde(default, skip_serializing_if = "Option::is_none")]
198 pub package: Option<String>,
199 #[serde(default, skip_serializing_if = "Option::is_none")]
201 pub filename: Option<String>,
202 #[serde(default, skip_serializing_if = "Option::is_none")]
204 pub abs_path: Option<String>,
205 #[serde(default, skip_serializing_if = "Option::is_none")]
207 pub lineno: Option<u64>,
208 #[serde(default, skip_serializing_if = "Option::is_none")]
210 pub colno: Option<u64>,
211 #[serde(default, skip_serializing_if = "Vec::is_empty")]
213 pub pre_context: Vec<String>,
214 #[serde(default, skip_serializing_if = "Option::is_none")]
216 pub context_line: Option<String>,
217 #[serde(default, skip_serializing_if = "Vec::is_empty")]
219 pub post_context: Vec<String>,
220 #[serde(default, skip_serializing_if = "Option::is_none")]
222 pub in_app: Option<bool>,
223 #[serde(default, skip_serializing_if = "Map::is_empty")]
225 pub vars: Map<String, Value>,
226 #[serde(default, skip_serializing_if = "Option::is_none")]
228 pub image_addr: Option<Addr>,
229 #[serde(default, skip_serializing_if = "Option::is_none")]
231 pub instruction_addr: Option<Addr>,
232 #[serde(default, skip_serializing_if = "Option::is_none")]
234 pub symbol_addr: Option<Addr>,
235 #[serde(default, skip_serializing_if = "Option::is_none")]
241 pub addr_mode: Option<String>,
242}
243
244#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
246pub struct TemplateInfo {
247 #[serde(default, skip_serializing_if = "Option::is_none")]
249 pub filename: Option<String>,
250 #[serde(default, skip_serializing_if = "Option::is_none")]
252 pub abs_path: Option<String>,
253 #[serde(default, skip_serializing_if = "Option::is_none")]
255 pub lineno: Option<u64>,
256 #[serde(default, skip_serializing_if = "Option::is_none")]
258 pub colno: Option<u64>,
259 #[serde(default, skip_serializing_if = "Vec::is_empty")]
261 pub pre_context: Vec<String>,
262 #[serde(default, skip_serializing_if = "Option::is_none")]
264 pub context_line: Option<String>,
265 #[serde(default, skip_serializing_if = "Vec::is_empty")]
267 pub post_context: Vec<String>,
268}
269
270#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
272pub struct Stacktrace {
273 #[serde(default)]
275 pub frames: Vec<Frame>,
276 #[serde(default, skip_serializing_if = "Option::is_none")]
278 pub frames_omitted: Option<(u64, u64)>,
279 #[serde(default, skip_serializing_if = "Map::is_empty")]
281 pub registers: Map<String, RegVal>,
282}
283
284impl Stacktrace {
285 pub fn from_frames_reversed(mut frames: Vec<Frame>) -> Option<Stacktrace> {
287 if frames.is_empty() {
288 None
289 } else {
290 frames.reverse();
291 Some(Stacktrace {
292 frames,
293 ..Default::default()
294 })
295 }
296 }
297}
298
299#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
301#[serde(untagged)]
302pub enum ThreadId {
303 Int(u64),
305 String(String),
307}
308
309impl Default for ThreadId {
310 fn default() -> ThreadId {
311 ThreadId::Int(0)
312 }
313}
314
315impl<'a> From<&'a str> for ThreadId {
316 fn from(id: &'a str) -> ThreadId {
317 ThreadId::String(id.to_string())
318 }
319}
320
321impl From<String> for ThreadId {
322 fn from(id: String) -> ThreadId {
323 ThreadId::String(id)
324 }
325}
326
327impl From<i64> for ThreadId {
328 fn from(id: i64) -> ThreadId {
329 ThreadId::Int(id as u64)
330 }
331}
332
333impl From<i32> for ThreadId {
334 fn from(id: i32) -> ThreadId {
335 ThreadId::Int(id as u64)
336 }
337}
338
339impl From<u32> for ThreadId {
340 fn from(id: u32) -> ThreadId {
341 ThreadId::Int(id as u64)
342 }
343}
344
345impl From<u16> for ThreadId {
346 fn from(id: u16) -> ThreadId {
347 ThreadId::Int(id as u64)
348 }
349}
350
351impl fmt::Display for ThreadId {
352 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
353 match *self {
354 ThreadId::Int(i) => write!(f, "{i}"),
355 ThreadId::String(ref s) => write!(f, "{s}"),
356 }
357 }
358}
359
360#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
362pub struct Addr(pub u64);
363
364impl Addr {
365 pub fn is_null(&self) -> bool {
367 self.0 == 0
368 }
369}
370
371impl_hex_serde!(Addr, u64);
372
373impl From<u64> for Addr {
374 fn from(addr: u64) -> Addr {
375 Addr(addr)
376 }
377}
378
379impl From<i32> for Addr {
380 fn from(addr: i32) -> Addr {
381 Addr(addr as u64)
382 }
383}
384
385impl From<u32> for Addr {
386 fn from(addr: u32) -> Addr {
387 Addr(addr as u64)
388 }
389}
390
391impl From<usize> for Addr {
392 fn from(addr: usize) -> Addr {
393 Addr(addr as u64)
394 }
395}
396
397impl<T> From<*const T> for Addr {
398 fn from(addr: *const T) -> Addr {
399 Addr(addr as u64)
400 }
401}
402
403impl<T> From<*mut T> for Addr {
404 fn from(addr: *mut T) -> Addr {
405 Addr(addr as u64)
406 }
407}
408
409impl From<Addr> for u64 {
410 fn from(addr: Addr) -> Self {
411 addr.0
412 }
413}
414
415fn is_false(value: &bool) -> bool {
416 !*value
417}
418
419#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
421pub struct RegVal(pub u64);
422
423impl_hex_serde!(RegVal, u64);
424
425impl From<u64> for RegVal {
426 fn from(addr: u64) -> RegVal {
427 RegVal(addr)
428 }
429}
430
431impl From<i32> for RegVal {
432 fn from(addr: i32) -> RegVal {
433 RegVal(addr as u64)
434 }
435}
436
437impl From<u32> for RegVal {
438 fn from(addr: u32) -> RegVal {
439 RegVal(addr as u64)
440 }
441}
442
443impl From<usize> for RegVal {
444 fn from(addr: usize) -> RegVal {
445 RegVal(addr as u64)
446 }
447}
448
449impl<T> From<*const T> for RegVal {
450 fn from(addr: *const T) -> RegVal {
451 RegVal(addr as u64)
452 }
453}
454
455impl<T> From<*mut T> for RegVal {
456 fn from(addr: *mut T) -> RegVal {
457 RegVal(addr as u64)
458 }
459}
460
461impl From<RegVal> for u64 {
462 fn from(reg: RegVal) -> Self {
463 reg.0
464 }
465}
466
467#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
469pub struct Thread {
470 #[serde(default, skip_serializing_if = "Option::is_none")]
472 pub id: Option<ThreadId>,
473 #[serde(default, skip_serializing_if = "Option::is_none")]
475 pub name: Option<String>,
476 #[serde(default, skip_serializing_if = "Option::is_none")]
479 pub stacktrace: Option<Stacktrace>,
480 #[serde(default, skip_serializing_if = "Option::is_none")]
482 pub raw_stacktrace: Option<Stacktrace>,
483 #[serde(default, skip_serializing_if = "is_false")]
485 pub crashed: bool,
486 #[serde(default, skip_serializing_if = "is_false")]
489 pub current: bool,
490}
491
492#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
494pub struct CError {
495 pub number: i32,
497 #[serde(default, skip_serializing_if = "Option::is_none")]
499 pub name: Option<String>,
500}
501
502impl From<i32> for CError {
503 fn from(number: i32) -> CError {
504 CError { number, name: None }
505 }
506}
507
508impl From<CError> for i32 {
509 fn from(err: CError) -> Self {
510 err.number
511 }
512}
513
514#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
516pub struct MachException {
517 pub exception: i32,
519 pub code: u64,
521 pub subcode: u64,
523 #[serde(default, skip_serializing_if = "Option::is_none")]
525 pub name: Option<String>,
526}
527
528#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
530pub struct PosixSignal {
531 pub number: i32,
533 #[serde(default, skip_serializing_if = "Option::is_none")]
535 pub code: Option<i32>,
536 #[serde(default, skip_serializing_if = "Option::is_none")]
538 pub name: Option<String>,
539 #[serde(default, skip_serializing_if = "Option::is_none")]
541 pub code_name: Option<String>,
542}
543
544impl From<i32> for PosixSignal {
545 fn from(number: i32) -> PosixSignal {
546 PosixSignal {
547 number,
548 code: None,
549 name: None,
550 code_name: None,
551 }
552 }
553}
554
555impl From<(i32, i32)> for PosixSignal {
556 fn from(tuple: (i32, i32)) -> PosixSignal {
557 let (number, code) = tuple;
558 PosixSignal {
559 number,
560 code: Some(code),
561 name: None,
562 code_name: None,
563 }
564 }
565}
566
567impl From<PosixSignal> for i32 {
568 fn from(sig: PosixSignal) -> Self {
569 sig.number
570 }
571}
572
573#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
575pub struct MechanismMeta {
576 #[serde(default, skip_serializing_if = "Option::is_none")]
578 pub errno: Option<CError>,
579 #[serde(default, skip_serializing_if = "Option::is_none")]
581 pub signal: Option<PosixSignal>,
582 #[serde(default, skip_serializing_if = "Option::is_none")]
584 pub mach_exception: Option<MachException>,
585}
586
587impl MechanismMeta {
588 fn is_empty(&self) -> bool {
589 self.errno.is_none() && self.signal.is_none() && self.mach_exception.is_none()
590 }
591}
592
593#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
595pub struct Mechanism {
596 #[serde(rename = "type")]
598 pub ty: String,
599 #[serde(default, skip_serializing_if = "Option::is_none")]
601 pub description: Option<String>,
602 #[serde(default, skip_serializing_if = "Option::is_none")]
604 pub help_link: Option<Url>,
605 #[serde(default, skip_serializing_if = "Option::is_none")]
607 pub handled: Option<bool>,
608 #[serde(default, skip_serializing_if = "Option::is_none")]
610 pub synthetic: Option<bool>,
611 #[serde(default, skip_serializing_if = "Map::is_empty")]
613 pub data: Map<String, Value>,
614 #[serde(default, skip_serializing_if = "MechanismMeta::is_empty")]
616 pub meta: MechanismMeta,
617}
618
619#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
621pub struct Exception {
622 #[serde(rename = "type")]
624 pub ty: String,
625 #[serde(skip_serializing_if = "Option::is_none")]
627 pub value: Option<String>,
628 #[serde(default, skip_serializing_if = "Option::is_none")]
630 pub module: Option<String>,
631 #[serde(default, skip_serializing_if = "Option::is_none")]
633 pub stacktrace: Option<Stacktrace>,
634 #[serde(default, skip_serializing_if = "Option::is_none")]
636 pub raw_stacktrace: Option<Stacktrace>,
637 #[serde(default, skip_serializing_if = "Option::is_none")]
639 pub thread_id: Option<ThreadId>,
640 #[serde(default, skip_serializing_if = "Option::is_none")]
642 pub mechanism: Option<Mechanism>,
643}
644
645#[derive(Debug, Error)]
647#[error("invalid level")]
648pub struct ParseLevelError;
649
650#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
652pub enum Level {
653 Debug,
655 #[default]
657 Info,
658 Warning,
660 Error,
662 Fatal,
664}
665
666impl str::FromStr for Level {
667 type Err = ParseLevelError;
668
669 fn from_str(string: &str) -> Result<Level, Self::Err> {
670 Ok(match string {
671 "debug" => Level::Debug,
672 "info" | "log" => Level::Info,
673 "warning" => Level::Warning,
674 "error" => Level::Error,
675 "fatal" => Level::Fatal,
676 _ => return Err(ParseLevelError),
677 })
678 }
679}
680
681impl fmt::Display for Level {
682 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
683 match *self {
684 Level::Debug => write!(f, "debug"),
685 Level::Info => write!(f, "info"),
686 Level::Warning => write!(f, "warning"),
687 Level::Error => write!(f, "error"),
688 Level::Fatal => write!(f, "fatal"),
689 }
690 }
691}
692
693impl Level {
694 pub fn is_debug(&self) -> bool {
696 *self == Level::Debug
697 }
698
699 pub fn is_info(&self) -> bool {
701 *self == Level::Info
702 }
703
704 pub fn is_warning(&self) -> bool {
706 *self == Level::Warning
707 }
708
709 pub fn is_error(&self) -> bool {
711 *self == Level::Error
712 }
713
714 pub fn is_fatal(&self) -> bool {
716 *self == Level::Fatal
717 }
718}
719
720impl_str_serde!(Level);
721
722mod breadcrumb {
723 use super::*;
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#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
740pub struct Breadcrumb {
741 #[serde(default = "SystemTime::now", with = "ts_seconds_float")]
743 pub timestamp: SystemTime,
744 #[serde(
746 rename = "type",
747 default = "breadcrumb::default_type",
748 skip_serializing_if = "breadcrumb::is_default_type"
749 )]
750 pub ty: String,
751 #[serde(default, skip_serializing_if = "Option::is_none")]
753 pub category: Option<String>,
754 #[serde(
757 default = "breadcrumb::default_level",
758 skip_serializing_if = "Level::is_info"
759 )]
760 pub level: Level,
761 #[serde(default, skip_serializing_if = "Option::is_none")]
763 pub message: Option<String>,
764 #[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: SystemTime::now(),
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#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash, Default)]
784pub enum IpAddress {
785 #[default]
787 Auto,
788 Exact(IpAddr),
790}
791
792impl PartialEq<IpAddr> for IpAddress {
793 fn eq(&self, other: &IpAddr) -> bool {
794 match *self {
795 IpAddress::Auto => false,
796 IpAddress::Exact(ref addr) => addr == other,
797 }
798 }
799}
800
801impl cmp::PartialOrd<IpAddr> for IpAddress {
802 fn partial_cmp(&self, other: &IpAddr) -> Option<cmp::Ordering> {
803 match *self {
804 IpAddress::Auto => None,
805 IpAddress::Exact(ref addr) => addr.partial_cmp(other),
806 }
807 }
808}
809
810impl fmt::Display for IpAddress {
811 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
812 match *self {
813 IpAddress::Auto => write!(f, "{{{{auto}}}}"),
814 IpAddress::Exact(ref addr) => write!(f, "{addr}"),
815 }
816 }
817}
818
819impl From<IpAddr> for IpAddress {
820 fn from(addr: IpAddr) -> IpAddress {
821 IpAddress::Exact(addr)
822 }
823}
824
825impl str::FromStr for IpAddress {
826 type Err = AddrParseError;
827
828 fn from_str(string: &str) -> Result<IpAddress, AddrParseError> {
829 match string {
830 "{{auto}}" => Ok(IpAddress::Auto),
831 other => other.parse().map(IpAddress::Exact),
832 }
833 }
834}
835
836impl_str_serde!(IpAddress);
837
838#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
840pub struct User {
841 #[serde(default, skip_serializing_if = "Option::is_none")]
843 pub id: Option<String>,
844 #[serde(default, skip_serializing_if = "Option::is_none")]
846 pub email: Option<String>,
847 #[serde(default, skip_serializing_if = "Option::is_none")]
849 pub ip_address: Option<IpAddress>,
850 #[serde(default, skip_serializing_if = "Option::is_none")]
852 pub username: Option<String>,
853 #[serde(flatten)]
855 pub other: Map<String, Value>,
856}
857
858#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
860pub struct Request {
861 #[serde(default, skip_serializing_if = "Option::is_none")]
863 pub url: Option<Url>,
864 #[serde(default, skip_serializing_if = "Option::is_none")]
866 pub method: Option<String>,
867 #[serde(default, skip_serializing_if = "Option::is_none")]
870 pub data: Option<String>,
871 #[serde(default, skip_serializing_if = "Option::is_none")]
873 pub query_string: Option<String>,
874 #[serde(default, skip_serializing_if = "Option::is_none")]
876 pub cookies: Option<String>,
877 #[serde(default, skip_serializing_if = "Map::is_empty")]
879 pub headers: Map<String, String>,
880 #[serde(default, skip_serializing_if = "Map::is_empty")]
882 pub env: Map<String, String>,
883}
884
885#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
890pub struct SystemSdkInfo {
891 pub sdk_name: String,
893 pub version_major: u32,
895 pub version_minor: u32,
897 pub version_patchlevel: u32,
899}
900
901#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
903#[serde(rename_all = "snake_case", tag = "type")]
904pub enum DebugImage {
905 Apple(AppleDebugImage),
908 Symbolic(SymbolicDebugImage),
910 Proguard(ProguardDebugImage),
912 Wasm(WasmDebugImage),
915}
916
917impl DebugImage {
918 pub fn type_name(&self) -> &str {
920 match *self {
921 DebugImage::Apple(..) => "apple",
922 DebugImage::Symbolic(..) => "symbolic",
923 DebugImage::Proguard(..) => "proguard",
924 DebugImage::Wasm(..) => "wasm",
925 }
926 }
927}
928
929macro_rules! into_debug_image {
930 ($kind:ident, $ty:ty) => {
931 impl From<$ty> for DebugImage {
932 fn from(data: $ty) -> DebugImage {
933 DebugImage::$kind(data)
934 }
935 }
936 };
937}
938
939#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
941pub struct AppleDebugImage {
942 pub name: String,
944 pub arch: Option<String>,
946 pub cpu_type: Option<u32>,
948 pub cpu_subtype: Option<u32>,
950 pub image_addr: Addr,
952 pub image_size: u64,
954 #[serde(default, skip_serializing_if = "Addr::is_null")]
956 pub image_vmaddr: Addr,
957 pub uuid: Uuid,
959}
960
961#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
963pub struct SymbolicDebugImage {
964 pub name: String,
969 pub arch: Option<String>,
971 pub image_addr: Addr,
975 pub image_size: u64,
979 #[serde(default, skip_serializing_if = "Addr::is_null")]
987 pub image_vmaddr: Addr,
988 pub id: DebugId,
992
993 #[serde(default, skip_serializing_if = "Option::is_none")]
995 pub code_id: Option<CodeId>,
996 #[serde(default, skip_serializing_if = "Option::is_none")]
998 pub debug_file: Option<String>,
999}
1000
1001#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1003pub struct ProguardDebugImage {
1004 pub uuid: Uuid,
1006}
1007
1008#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1010pub struct WasmDebugImage {
1011 pub name: String,
1013 pub debug_id: Uuid,
1015 #[serde(default, skip_serializing_if = "Option::is_none")]
1020 pub debug_file: Option<String>,
1021 #[serde(default, skip_serializing_if = "Option::is_none")]
1024 pub code_id: Option<String>,
1025 pub code_file: String,
1028}
1029
1030into_debug_image!(Apple, AppleDebugImage);
1031into_debug_image!(Symbolic, SymbolicDebugImage);
1032into_debug_image!(Proguard, ProguardDebugImage);
1033into_debug_image!(Wasm, WasmDebugImage);
1034
1035#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
1037pub struct DebugMeta {
1038 #[serde(default, skip_serializing_if = "Option::is_none")]
1040 pub sdk_info: Option<SystemSdkInfo>,
1041 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1043 pub images: Vec<DebugImage>,
1044}
1045
1046impl DebugMeta {
1047 pub fn is_empty(&self) -> bool {
1051 self.sdk_info.is_none() && self.images.is_empty()
1052 }
1053}
1054
1055#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1057pub struct ClientSdkInfo {
1058 pub name: String,
1060 pub version: String,
1062 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1064 pub integrations: Vec<String>,
1065 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1067 pub packages: Vec<ClientSdkPackage>,
1068}
1069
1070#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1072pub struct ClientSdkPackage {
1073 pub name: String,
1075 pub version: String,
1077}
1078
1079#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1084#[serde(rename_all = "snake_case", tag = "type")]
1085#[non_exhaustive]
1086pub enum Context {
1087 Device(Box<DeviceContext>),
1089 Os(Box<OsContext>),
1091 Runtime(Box<RuntimeContext>),
1093 App(Box<AppContext>),
1095 Browser(Box<BrowserContext>),
1097 Trace(Box<TraceContext>),
1099 Gpu(Box<GpuContext>),
1101 Otel(Box<OtelContext>),
1103 Response(Box<ResponseContext>),
1105 #[serde(rename = "unknown")]
1107 Other(Map<String, Value>),
1108}
1109
1110impl Context {
1111 pub fn type_name(&self) -> &str {
1113 match *self {
1114 Context::Device(..) => "device",
1115 Context::Os(..) => "os",
1116 Context::Runtime(..) => "runtime",
1117 Context::App(..) => "app",
1118 Context::Browser(..) => "browser",
1119 Context::Trace(..) => "trace",
1120 Context::Gpu(..) => "gpu",
1121 Context::Otel(..) => "otel",
1122 Context::Response(..) => "response",
1123 Context::Other(..) => "unknown",
1124 }
1125 }
1126}
1127
1128#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
1130#[serde(rename_all = "lowercase")]
1131pub enum Orientation {
1132 Portrait,
1134 Landscape,
1136}
1137
1138#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1140pub struct DeviceContext {
1141 #[serde(default, skip_serializing_if = "Option::is_none")]
1143 pub name: Option<String>,
1144 #[serde(default, skip_serializing_if = "Option::is_none")]
1146 pub family: Option<String>,
1147 #[serde(default, skip_serializing_if = "Option::is_none")]
1149 pub model: Option<String>,
1150 #[serde(default, skip_serializing_if = "Option::is_none")]
1152 pub model_id: Option<String>,
1153 #[serde(default, skip_serializing_if = "Option::is_none")]
1155 pub arch: Option<String>,
1156 #[serde(default, skip_serializing_if = "Option::is_none")]
1158 pub battery_level: Option<f32>,
1159 #[serde(default, skip_serializing_if = "Option::is_none")]
1161 pub orientation: Option<Orientation>,
1162 #[serde(default, skip_serializing_if = "Option::is_none")]
1164 pub simulator: Option<bool>,
1165 #[serde(default, skip_serializing_if = "Option::is_none")]
1167 pub memory_size: Option<u64>,
1168 #[serde(default, skip_serializing_if = "Option::is_none")]
1170 pub free_memory: Option<u64>,
1171 #[serde(default, skip_serializing_if = "Option::is_none")]
1173 pub usable_memory: Option<u64>,
1174 #[serde(default, skip_serializing_if = "Option::is_none")]
1176 pub storage_size: Option<u64>,
1177 #[serde(default, skip_serializing_if = "Option::is_none")]
1179 pub free_storage: Option<u64>,
1180 #[serde(default, skip_serializing_if = "Option::is_none")]
1182 pub external_storage_size: Option<u64>,
1183 #[serde(default, skip_serializing_if = "Option::is_none")]
1185 pub external_free_storage: Option<u64>,
1186 #[serde(
1188 default,
1189 skip_serializing_if = "Option::is_none",
1190 with = "ts_rfc3339_opt"
1191 )]
1192 pub boot_time: Option<SystemTime>,
1193 #[serde(default, skip_serializing_if = "Option::is_none")]
1195 pub timezone: Option<String>,
1196 #[serde(flatten)]
1198 pub other: Map<String, Value>,
1199}
1200
1201#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1203pub struct OsContext {
1204 #[serde(default, skip_serializing_if = "Option::is_none")]
1206 pub name: Option<String>,
1207 #[serde(default, skip_serializing_if = "Option::is_none")]
1209 pub version: Option<String>,
1210 #[serde(default, skip_serializing_if = "Option::is_none")]
1212 pub build: Option<String>,
1213 #[serde(default, skip_serializing_if = "Option::is_none")]
1215 pub kernel_version: Option<String>,
1216 #[serde(default, skip_serializing_if = "Option::is_none")]
1218 pub rooted: Option<bool>,
1219 #[serde(flatten)]
1221 pub other: Map<String, Value>,
1222}
1223
1224#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1226pub struct RuntimeContext {
1227 #[serde(default, skip_serializing_if = "Option::is_none")]
1229 pub name: Option<String>,
1230 #[serde(default, skip_serializing_if = "Option::is_none")]
1232 pub version: Option<String>,
1233 #[serde(flatten)]
1235 pub other: Map<String, Value>,
1236}
1237
1238#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1240pub struct AppContext {
1241 #[serde(
1243 default,
1244 skip_serializing_if = "Option::is_none",
1245 with = "ts_rfc3339_opt"
1246 )]
1247 pub app_start_time: Option<SystemTime>,
1248 #[serde(default, skip_serializing_if = "Option::is_none")]
1250 pub device_app_hash: Option<String>,
1251 #[serde(default, skip_serializing_if = "Option::is_none")]
1253 pub build_type: Option<String>,
1254 #[serde(default, skip_serializing_if = "Option::is_none")]
1256 pub app_identifier: Option<String>,
1257 #[serde(default, skip_serializing_if = "Option::is_none")]
1259 pub app_name: Option<String>,
1260 #[serde(default, skip_serializing_if = "Option::is_none")]
1262 pub app_version: Option<String>,
1263 #[serde(default, skip_serializing_if = "Option::is_none")]
1265 pub app_build: Option<String>,
1266 #[serde(flatten)]
1268 pub other: Map<String, Value>,
1269}
1270
1271#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1273pub struct BrowserContext {
1274 #[serde(default, skip_serializing_if = "Option::is_none")]
1276 pub name: Option<String>,
1277 #[serde(default, skip_serializing_if = "Option::is_none")]
1279 pub version: Option<String>,
1280 #[serde(flatten)]
1282 pub other: Map<String, Value>,
1283}
1284
1285#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1287pub struct GpuContext {
1288 pub name: String,
1290 #[serde(default, skip_serializing_if = "Option::is_none")]
1292 pub version: Option<String>,
1293 #[serde(default, skip_serializing_if = "Option::is_none")]
1295 pub driver_version: Option<String>,
1296 #[serde(default, skip_serializing_if = "Option::is_none")]
1298 pub id: Option<String>,
1299 #[serde(default, skip_serializing_if = "Option::is_none")]
1301 pub vendor_id: Option<String>,
1302 #[serde(default, skip_serializing_if = "Option::is_none")]
1304 pub vendor_name: Option<String>,
1305 #[serde(default, skip_serializing_if = "Option::is_none")]
1307 pub memory_size: Option<u32>,
1308 #[serde(default, skip_serializing_if = "Option::is_none")]
1310 pub api_type: Option<String>,
1311 #[serde(default, skip_serializing_if = "Option::is_none")]
1313 pub multi_threaded_rendering: Option<bool>,
1314 #[serde(default, skip_serializing_if = "Option::is_none")]
1316 pub npot_support: Option<bool>,
1317 #[serde(default, skip_serializing_if = "Option::is_none")]
1319 pub max_texture_size: Option<u32>,
1320 #[serde(default, skip_serializing_if = "Option::is_none")]
1323 pub graphics_shader_level: Option<String>,
1324 #[serde(default, skip_serializing_if = "Option::is_none")]
1326 pub supports_draw_call_instancing: Option<bool>,
1327 #[serde(default, skip_serializing_if = "Option::is_none")]
1329 pub supports_ray_tracing: Option<bool>,
1330 #[serde(default, skip_serializing_if = "Option::is_none")]
1332 pub supports_compute_shaders: Option<bool>,
1333 #[serde(default, skip_serializing_if = "Option::is_none")]
1335 pub supports_geometry_shaders: Option<bool>,
1336 #[serde(flatten)]
1338 pub other: Map<String, Value>,
1339}
1340
1341#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1343pub struct OtelContext {
1344 #[serde(default, skip_serializing_if = "Map::is_empty")]
1347 pub attributes: Map<String, Value>,
1348 #[serde(default, skip_serializing_if = "Map::is_empty")]
1351 pub resource: Map<String, Value>,
1352 #[serde(flatten)]
1354 pub other: Map<String, Value>,
1355}
1356
1357#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1359pub struct ResponseContext {
1360 #[serde(default, skip_serializing_if = "Option::is_none")]
1362 pub cookies: Option<String>,
1363 #[serde(default, skip_serializing_if = "Map::is_empty")]
1368 pub headers: Map<String, String>,
1369 #[serde(default, skip_serializing_if = "Option::is_none")]
1371 pub status_code: Option<u64>,
1372 #[serde(default, skip_serializing_if = "Option::is_none")]
1374 pub body_size: Option<u64>,
1375 #[serde(default, skip_serializing_if = "Option::is_none")]
1377 pub data: Option<Value>,
1378}
1379
1380#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash)]
1382#[serde(try_from = "String", into = "String")]
1383pub struct SpanId([u8; 8]);
1384
1385impl Default for SpanId {
1386 fn default() -> Self {
1387 Self(rand::random())
1388 }
1389}
1390
1391impl fmt::Display for SpanId {
1392 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1393 write!(fmt, "{}", hex::encode(self.0))
1394 }
1395}
1396
1397impl fmt::Debug for SpanId {
1398 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1399 write!(fmt, "SpanId({self})")
1400 }
1401}
1402
1403impl From<SpanId> for String {
1404 fn from(span_id: SpanId) -> Self {
1405 span_id.to_string()
1406 }
1407}
1408
1409impl str::FromStr for SpanId {
1410 type Err = hex::FromHexError;
1411
1412 fn from_str(input: &str) -> Result<Self, Self::Err> {
1413 let mut buf = [0; 8];
1414 hex::decode_to_slice(input, &mut buf)?;
1415 Ok(Self(buf))
1416 }
1417}
1418
1419impl TryFrom<String> for SpanId {
1420 type Error = hex::FromHexError;
1421
1422 fn try_from(value: String) -> Result<Self, Self::Error> {
1423 value.parse()
1424 }
1425}
1426
1427impl From<[u8; 8]> for SpanId {
1428 fn from(value: [u8; 8]) -> Self {
1429 Self(value)
1430 }
1431}
1432
1433#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash)]
1435#[serde(try_from = "String", into = "String")]
1436pub struct TraceId([u8; 16]);
1437
1438impl Default for TraceId {
1439 fn default() -> Self {
1440 Self(rand::random())
1441 }
1442}
1443
1444impl fmt::Display for TraceId {
1445 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1446 write!(fmt, "{}", hex::encode(self.0))
1447 }
1448}
1449
1450impl fmt::Debug for TraceId {
1451 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1452 write!(fmt, "TraceId({self})")
1453 }
1454}
1455
1456impl From<TraceId> for String {
1457 fn from(trace_id: TraceId) -> Self {
1458 trace_id.to_string()
1459 }
1460}
1461
1462impl str::FromStr for TraceId {
1463 type Err = hex::FromHexError;
1464
1465 fn from_str(input: &str) -> Result<Self, Self::Err> {
1466 let mut buf = [0; 16];
1467 hex::decode_to_slice(input, &mut buf)?;
1468 Ok(Self(buf))
1469 }
1470}
1471
1472impl TryFrom<String> for TraceId {
1473 type Error = hex::FromHexError;
1474
1475 fn try_from(value: String) -> Result<Self, Self::Error> {
1476 value.parse()
1477 }
1478}
1479
1480impl From<[u8; 16]> for TraceId {
1481 fn from(value: [u8; 16]) -> Self {
1482 Self(value)
1483 }
1484}
1485
1486#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
1488pub struct TraceContext {
1489 #[serde(default)]
1491 pub span_id: SpanId,
1492 #[serde(default)]
1494 pub trace_id: TraceId,
1495 #[serde(default, skip_serializing_if = "Option::is_none")]
1497 pub parent_span_id: Option<SpanId>,
1498 #[serde(default, skip_serializing_if = "Option::is_none")]
1500 pub op: Option<String>,
1501 #[serde(default, skip_serializing_if = "Option::is_none")]
1503 pub description: Option<String>,
1504 #[serde(default, skip_serializing_if = "Option::is_none")]
1506 pub status: Option<SpanStatus>,
1507 #[serde(default, skip_serializing_if = "Option::is_none")]
1510 pub origin: Option<String>,
1511 #[serde(default, skip_serializing_if = "Map::is_empty")]
1513 pub data: Map<String, Value>,
1514}
1515
1516macro_rules! into_context {
1517 ($kind:ident, $ty:ty) => {
1518 impl From<$ty> for Context {
1519 fn from(data: $ty) -> Self {
1520 Context::$kind(Box::new(data))
1521 }
1522 }
1523 };
1524}
1525
1526into_context!(App, AppContext);
1527into_context!(Device, DeviceContext);
1528into_context!(Os, OsContext);
1529into_context!(Runtime, RuntimeContext);
1530into_context!(Browser, BrowserContext);
1531into_context!(Trace, TraceContext);
1532into_context!(Gpu, GpuContext);
1533into_context!(Otel, OtelContext);
1534into_context!(Response, ResponseContext);
1535
1536const INFERABLE_CONTEXTS: &[&str] = &[
1537 "device", "os", "runtime", "app", "browser", "trace", "gpu", "otel", "response",
1538];
1539
1540struct ContextsVisitor;
1541
1542impl<'de> de::Visitor<'de> for ContextsVisitor {
1543 type Value = Map<String, Context>;
1544
1545 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1546 formatter.write_str("contexts object")
1547 }
1548
1549 fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
1550 where
1551 A: de::MapAccess<'de>,
1552 {
1553 let mut map: Map<String, Context> = Map::new();
1554
1555 while let Some((key, mut value)) = access.next_entry::<String, Value>()? {
1556 let typed_value = value
1557 .as_object_mut()
1558 .map(|ctx| {
1559 if !ctx.contains_key("type") {
1560 let type_key = if INFERABLE_CONTEXTS.contains(&key.as_str()) {
1561 key.clone().into()
1562 } else {
1563 Value::String("unknown".into())
1564 };
1565 ctx.insert(String::from("type"), type_key);
1566 }
1567 ctx.to_owned()
1568 })
1569 .ok_or_else(|| de::Error::custom("expected valid `context` object"))?;
1570
1571 match serde_json::from_value(serde_json::to_value(typed_value).unwrap()) {
1572 Ok(context) => {
1573 map.insert(key, context);
1574 }
1575 Err(e) => return Err(de::Error::custom(e.to_string())),
1576 }
1577 }
1578
1579 Ok(map)
1580 }
1581}
1582
1583fn deserialize_contexts<'de, D>(deserializer: D) -> Result<Map<String, Context>, D::Error>
1584where
1585 D: Deserializer<'de>,
1586{
1587 deserializer.deserialize_map(ContextsVisitor {})
1588}
1589
1590mod event {
1591 use super::*;
1592
1593 pub fn default_id() -> Uuid {
1594 crate::random_uuid()
1595 }
1596
1597 pub fn serialize_id<S: Serializer>(uuid: &Uuid, serializer: S) -> Result<S::Ok, S::Error> {
1598 serializer.serialize_some(&uuid.as_simple().to_string())
1599 }
1600
1601 pub fn default_level() -> Level {
1602 Level::Error
1603 }
1604
1605 pub fn default_platform() -> Cow<'static, str> {
1606 Cow::Borrowed("other")
1607 }
1608
1609 pub fn is_default_platform(value: &str) -> bool {
1610 value == "other"
1611 }
1612
1613 static DEFAULT_FINGERPRINT: &[Cow<'static, str>] = &[Cow::Borrowed("{{ default }}")];
1614
1615 pub fn default_fingerprint<'a>() -> Cow<'a, [Cow<'a, str>]> {
1616 Cow::Borrowed(DEFAULT_FINGERPRINT)
1617 }
1618
1619 pub fn is_default_fingerprint(fp: &[Cow<'_, str>]) -> bool {
1620 fp.len() == 1 && ((fp)[0] == "{{ default }}" || (fp)[0] == "{{default}}")
1621 }
1622}
1623
1624#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1626pub struct Event<'a> {
1627 #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
1629 pub event_id: Uuid,
1630 #[serde(
1632 default = "event::default_level",
1633 skip_serializing_if = "Level::is_error"
1634 )]
1635 pub level: Level,
1636 #[serde(
1638 default = "event::default_fingerprint",
1639 skip_serializing_if = "event::is_default_fingerprint"
1640 )]
1641 pub fingerprint: Cow<'a, [Cow<'a, str>]>,
1642 #[serde(default, skip_serializing_if = "Option::is_none")]
1644 pub culprit: Option<String>,
1645 #[serde(default, skip_serializing_if = "Option::is_none")]
1647 pub transaction: Option<String>,
1648 #[serde(default, skip_serializing_if = "Option::is_none")]
1650 pub message: Option<String>,
1651 #[serde(default, skip_serializing_if = "Option::is_none")]
1654 pub logentry: Option<LogEntry>,
1655 #[serde(default, skip_serializing_if = "Option::is_none")]
1657 pub logger: Option<String>,
1658 #[serde(default, skip_serializing_if = "Map::is_empty")]
1660 pub modules: Map<String, String>,
1661 #[serde(
1663 default = "event::default_platform",
1664 skip_serializing_if = "event::is_default_platform"
1665 )]
1666 pub platform: Cow<'a, str>,
1667 #[serde(default = "SystemTime::now", with = "ts_seconds_float")]
1671 pub timestamp: SystemTime,
1672 #[serde(default, skip_serializing_if = "Option::is_none")]
1674 pub server_name: Option<Cow<'a, str>>,
1675 #[serde(default, skip_serializing_if = "Option::is_none")]
1677 pub release: Option<Cow<'a, str>>,
1678 #[serde(default, skip_serializing_if = "Option::is_none")]
1680 pub dist: Option<Cow<'a, str>>,
1681 #[serde(default, skip_serializing_if = "Option::is_none")]
1683 pub environment: Option<Cow<'a, str>>,
1684 #[serde(default, skip_serializing_if = "Option::is_none")]
1686 pub user: Option<User>,
1687 #[serde(default, skip_serializing_if = "Option::is_none")]
1689 pub request: Option<Request>,
1690 #[serde(
1692 default,
1693 skip_serializing_if = "Map::is_empty",
1694 deserialize_with = "deserialize_contexts"
1695 )]
1696 pub contexts: Map<String, Context>,
1697 #[serde(default, skip_serializing_if = "Values::is_empty")]
1699 pub breadcrumbs: Values<Breadcrumb>,
1700 #[serde(default, skip_serializing_if = "Values::is_empty")]
1702 pub exception: Values<Exception>,
1703 #[serde(default, skip_serializing_if = "Option::is_none")]
1705 pub stacktrace: Option<Stacktrace>,
1706 #[serde(default, skip_serializing_if = "Option::is_none")]
1708 pub template: Option<TemplateInfo>,
1709 #[serde(default, skip_serializing_if = "Values::is_empty")]
1711 pub threads: Values<Thread>,
1712 #[serde(default, skip_serializing_if = "Map::is_empty")]
1714 pub tags: Map<String, String>,
1715 #[serde(default, skip_serializing_if = "Map::is_empty")]
1717 pub extra: Map<String, Value>,
1718 #[serde(default, skip_serializing_if = "DebugMeta::is_empty")]
1720 pub debug_meta: Cow<'a, DebugMeta>,
1721 #[serde(default, skip_serializing_if = "Option::is_none")]
1723 pub sdk: Option<Cow<'a, ClientSdkInfo>>,
1724}
1725
1726impl Default for Event<'_> {
1727 fn default() -> Self {
1728 Event {
1729 event_id: event::default_id(),
1730 level: event::default_level(),
1731 fingerprint: event::default_fingerprint(),
1732 culprit: Default::default(),
1733 transaction: Default::default(),
1734 message: Default::default(),
1735 logentry: Default::default(),
1736 logger: Default::default(),
1737 modules: Default::default(),
1738 platform: event::default_platform(),
1739 timestamp: SystemTime::now(),
1740 server_name: Default::default(),
1741 release: Default::default(),
1742 dist: Default::default(),
1743 environment: Default::default(),
1744 user: Default::default(),
1745 request: Default::default(),
1746 contexts: Default::default(),
1747 breadcrumbs: Default::default(),
1748 exception: Default::default(),
1749 stacktrace: Default::default(),
1750 template: Default::default(),
1751 threads: Default::default(),
1752 tags: Default::default(),
1753 extra: Default::default(),
1754 debug_meta: Default::default(),
1755 sdk: Default::default(),
1756 }
1757 }
1758}
1759
1760impl<'a> Event<'a> {
1761 pub fn new() -> Event<'a> {
1763 Default::default()
1764 }
1765
1766 pub fn into_owned(self) -> Event<'static> {
1768 Event {
1769 event_id: self.event_id,
1770 level: self.level,
1771 fingerprint: Cow::Owned(
1772 self.fingerprint
1773 .iter()
1774 .map(|x| Cow::Owned(x.to_string()))
1775 .collect(),
1776 ),
1777 culprit: self.culprit,
1778 transaction: self.transaction,
1779 message: self.message,
1780 logentry: self.logentry,
1781 logger: self.logger,
1782 modules: self.modules,
1783 platform: Cow::Owned(self.platform.into_owned()),
1784 timestamp: self.timestamp,
1785 server_name: self.server_name.map(|x| Cow::Owned(x.into_owned())),
1786 release: self.release.map(|x| Cow::Owned(x.into_owned())),
1787 dist: self.dist.map(|x| Cow::Owned(x.into_owned())),
1788 environment: self.environment.map(|x| Cow::Owned(x.into_owned())),
1789 user: self.user,
1790 request: self.request,
1791 contexts: self.contexts,
1792 breadcrumbs: self.breadcrumbs,
1793 exception: self.exception,
1794 stacktrace: self.stacktrace,
1795 template: self.template,
1796 threads: self.threads,
1797 tags: self.tags,
1798 extra: self.extra,
1799 debug_meta: Cow::Owned(self.debug_meta.into_owned()),
1800 sdk: self.sdk.map(|x| Cow::Owned(x.into_owned())),
1801 }
1802 }
1803}
1804
1805impl fmt::Display for Event<'_> {
1806 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1807 write!(
1808 f,
1809 "Event(id: {}, ts: {})",
1810 self.event_id,
1811 crate::utils::to_rfc3339(&self.timestamp)
1812 )
1813 }
1814}
1815
1816#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
1818pub struct Span {
1819 #[serde(default)]
1821 pub span_id: SpanId,
1822 #[serde(default)]
1824 pub trace_id: TraceId,
1825 #[serde(default, skip_serializing_if = "Option::is_none")]
1827 pub parent_span_id: Option<SpanId>,
1828 #[serde(default, skip_serializing_if = "Option::is_none")]
1830 pub same_process_as_parent: Option<bool>,
1831 #[serde(default, skip_serializing_if = "Option::is_none")]
1833 pub op: Option<String>,
1834 #[serde(default, skip_serializing_if = "Option::is_none")]
1837 pub description: Option<String>,
1838 #[serde(
1840 default,
1841 skip_serializing_if = "Option::is_none",
1842 with = "ts_rfc3339_opt"
1843 )]
1844 pub timestamp: Option<SystemTime>,
1845 #[serde(default = "SystemTime::now", with = "ts_seconds_float")]
1847 pub start_timestamp: SystemTime,
1848 #[serde(default, skip_serializing_if = "Option::is_none")]
1850 pub status: Option<SpanStatus>,
1851 #[serde(default, skip_serializing_if = "Map::is_empty")]
1853 pub tags: Map<String, String>,
1854 #[serde(default, skip_serializing_if = "Map::is_empty")]
1856 pub data: Map<String, Value>,
1857}
1858
1859impl Default for Span {
1860 fn default() -> Self {
1861 Span {
1862 span_id: Default::default(),
1863 trace_id: Default::default(),
1864 timestamp: Default::default(),
1865 tags: Default::default(),
1866 start_timestamp: SystemTime::now(),
1867 description: Default::default(),
1868 status: Default::default(),
1869 parent_span_id: Default::default(),
1870 same_process_as_parent: Default::default(),
1871 op: Default::default(),
1872 data: Default::default(),
1873 }
1874 }
1875}
1876
1877impl Span {
1878 pub fn new() -> Span {
1880 Default::default()
1881 }
1882
1883 pub fn finish_with_timestamp(&mut self, timestamp: SystemTime) {
1885 self.timestamp = Some(timestamp);
1886 }
1887
1888 pub fn finish(&mut self) {
1890 self.timestamp = Some(SystemTime::now());
1891 }
1892}
1893
1894impl fmt::Display for Span {
1895 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1896 write!(
1897 f,
1898 "Span(id: {}, ts: {})",
1899 self.span_id,
1900 crate::utils::to_rfc3339(&self.start_timestamp)
1901 )
1902 }
1903}
1904
1905#[derive(Debug, Error)]
1907#[error("invalid status")]
1908pub struct ParseStatusError;
1909
1910#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, Hash)]
1912#[non_exhaustive]
1913pub enum SpanStatus {
1914 #[serde(rename = "ok")]
1916 Ok,
1917 #[serde(rename = "deadline_exceeded")]
1919 DeadlineExceeded,
1920 #[serde(rename = "unauthenticated")]
1922 Unauthenticated,
1923 #[serde(rename = "permission_denied")]
1925 PermissionDenied,
1926 #[serde(rename = "not_found")]
1928 NotFound,
1929 #[serde(rename = "resource_exhausted")]
1931 ResourceExhausted,
1932 #[serde(rename = "invalid_argument")]
1934 InvalidArgument,
1935 #[serde(rename = "unimplemented")]
1937 Unimplemented,
1938 #[serde(rename = "unavailable")]
1940 Unavailable,
1941 #[serde(rename = "internal_error")]
1943 InternalError,
1944 #[serde(rename = "unknown_error")]
1946 UnknownError,
1947 #[serde(rename = "cancelled")]
1949 Cancelled,
1950 #[serde(rename = "already_exists")]
1952 AlreadyExists,
1953 #[serde(rename = "failed_precondition")]
1955 FailedPrecondition,
1956 #[serde(rename = "aborted")]
1958 Aborted,
1959 #[serde(rename = "out_of_range")]
1961 OutOfRange,
1962 #[serde(rename = "data_loss")]
1964 DataLoss,
1965}
1966
1967impl str::FromStr for SpanStatus {
1968 type Err = ParseStatusError;
1969
1970 fn from_str(s: &str) -> Result<SpanStatus, Self::Err> {
1971 Ok(match s {
1972 "ok" => SpanStatus::Ok,
1973 "deadline_exceeded" => SpanStatus::DeadlineExceeded,
1974 "unauthenticated" => SpanStatus::Unauthenticated,
1975 "permission_denied" => SpanStatus::PermissionDenied,
1976 "not_found" => SpanStatus::NotFound,
1977 "resource_exhausted" => SpanStatus::ResourceExhausted,
1978 "invalid_argument" => SpanStatus::InvalidArgument,
1979 "unimplemented" => SpanStatus::Unimplemented,
1980 "unavailable" => SpanStatus::Unavailable,
1981 "internal_error" => SpanStatus::InternalError,
1982 "unknown_error" => SpanStatus::UnknownError,
1983 "cancelled" => SpanStatus::Cancelled,
1984 "already_exists" => SpanStatus::AlreadyExists,
1985 "failed_precondition" => SpanStatus::FailedPrecondition,
1986 "aborted" => SpanStatus::Aborted,
1987 "out_of_range" => SpanStatus::OutOfRange,
1988 "data_loss" => SpanStatus::DataLoss,
1989 _ => return Err(ParseStatusError),
1990 })
1991 }
1992}
1993
1994impl fmt::Display for SpanStatus {
1995 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1996 match self {
1997 SpanStatus::Ok => write!(f, "ok"),
1998 SpanStatus::DeadlineExceeded => write!(f, "deadline_exceeded"),
1999 SpanStatus::Unauthenticated => write!(f, "unauthenticated"),
2000 SpanStatus::PermissionDenied => write!(f, "permission_denied"),
2001 SpanStatus::NotFound => write!(f, "not_found"),
2002 SpanStatus::ResourceExhausted => write!(f, "resource_exhausted"),
2003 SpanStatus::InvalidArgument => write!(f, "invalid_argument"),
2004 SpanStatus::Unimplemented => write!(f, "unimplemented"),
2005 SpanStatus::Unavailable => write!(f, "unavailable"),
2006 SpanStatus::InternalError => write!(f, "internal_error"),
2007 SpanStatus::UnknownError => write!(f, "unknown_error"),
2008 SpanStatus::Cancelled => write!(f, "cancelled"),
2009 SpanStatus::AlreadyExists => write!(f, "already_exists"),
2010 SpanStatus::FailedPrecondition => write!(f, "failed_precondition"),
2011 SpanStatus::Aborted => write!(f, "aborted"),
2012 SpanStatus::OutOfRange => write!(f, "out_of_range"),
2013 SpanStatus::DataLoss => write!(f, "data_loss"),
2014 }
2015 }
2016}
2017
2018#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
2020pub struct Transaction<'a> {
2021 #[serde(default = "event::default_id", serialize_with = "event::serialize_id")]
2023 pub event_id: Uuid,
2024 #[serde(
2026 rename = "transaction",
2027 default,
2028 skip_serializing_if = "Option::is_none"
2029 )]
2030 pub name: Option<String>,
2031 #[serde(default, skip_serializing_if = "Option::is_none")]
2033 pub release: Option<Cow<'a, str>>,
2034 #[serde(default, skip_serializing_if = "Option::is_none")]
2036 pub environment: Option<Cow<'a, str>>,
2037 #[serde(default, skip_serializing_if = "Option::is_none")]
2039 pub user: Option<User>,
2040 #[serde(default, skip_serializing_if = "Map::is_empty")]
2042 pub tags: Map<String, String>,
2043 #[serde(default, skip_serializing_if = "Map::is_empty")]
2045 pub extra: Map<String, Value>,
2046 #[serde(default, skip_serializing_if = "Option::is_none")]
2048 pub sdk: Option<Cow<'a, ClientSdkInfo>>,
2049 #[serde(
2051 default = "event::default_platform",
2052 skip_serializing_if = "event::is_default_platform"
2053 )]
2054 pub platform: Cow<'a, str>,
2055 #[serde(
2057 default,
2058 skip_serializing_if = "Option::is_none",
2059 with = "ts_rfc3339_opt"
2060 )]
2061 pub timestamp: Option<SystemTime>,
2062 #[serde(default = "SystemTime::now", with = "ts_seconds_float")]
2064 pub start_timestamp: SystemTime,
2065 pub spans: Vec<Span>,
2067 #[serde(
2069 default,
2070 skip_serializing_if = "Map::is_empty",
2071 deserialize_with = "deserialize_contexts"
2072 )]
2073 pub contexts: Map<String, Context>,
2074 #[serde(default, skip_serializing_if = "Option::is_none")]
2076 pub request: Option<Request>,
2077 #[serde(default, skip_serializing_if = "Option::is_none")]
2079 pub server_name: Option<Cow<'a, str>>,
2080}
2081
2082impl Default for Transaction<'_> {
2083 fn default() -> Self {
2084 Transaction {
2085 event_id: event::default_id(),
2086 name: Default::default(),
2087 user: Default::default(),
2088 tags: Default::default(),
2089 extra: Default::default(),
2090 release: Default::default(),
2091 environment: Default::default(),
2092 sdk: Default::default(),
2093 platform: event::default_platform(),
2094 timestamp: Default::default(),
2095 start_timestamp: SystemTime::now(),
2096 spans: Default::default(),
2097 contexts: Default::default(),
2098 request: Default::default(),
2099 server_name: Default::default(),
2100 }
2101 }
2102}
2103
2104impl<'a> Transaction<'a> {
2105 pub fn new() -> Transaction<'a> {
2107 Default::default()
2108 }
2109
2110 pub fn into_owned(self) -> Transaction<'static> {
2112 Transaction {
2113 event_id: self.event_id,
2114 name: self.name,
2115 user: self.user,
2116 tags: self.tags,
2117 extra: self.extra,
2118 release: self.release.map(|x| Cow::Owned(x.into_owned())),
2119 environment: self.environment.map(|x| Cow::Owned(x.into_owned())),
2120 sdk: self.sdk.map(|x| Cow::Owned(x.into_owned())),
2121 platform: Cow::Owned(self.platform.into_owned()),
2122 timestamp: self.timestamp,
2123 start_timestamp: self.start_timestamp,
2124 spans: self.spans,
2125 contexts: self.contexts,
2126 request: self.request,
2127 server_name: self.server_name.map(|x| Cow::Owned(x.into_owned())),
2128 }
2129 }
2130
2131 pub fn finish(&mut self) {
2133 self.timestamp = Some(SystemTime::now());
2134 }
2135
2136 pub fn finish_with_timestamp(&mut self, timestamp: SystemTime) {
2138 self.timestamp = Some(timestamp);
2139 }
2140}
2141
2142impl fmt::Display for Transaction<'_> {
2143 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2144 write!(
2145 f,
2146 "Transaction(id: {}, ts: {})",
2147 self.event_id,
2148 crate::utils::to_rfc3339(&self.start_timestamp)
2149 )
2150 }
2151}
2152
2153#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
2155pub struct Log {
2156 pub level: LogLevel,
2158 pub body: String,
2160 #[serde(default, skip_serializing_if = "Option::is_none")]
2162 pub trace_id: Option<TraceId>,
2163 #[serde(with = "ts_seconds_float")]
2165 pub timestamp: SystemTime,
2166 #[serde(default, skip_serializing_if = "Option::is_none")]
2168 pub severity_number: Option<LogSeverityNumber>,
2169 #[serde(default, skip_serializing_if = "Map::is_empty")]
2171 pub attributes: Map<String, LogAttribute>,
2172}
2173
2174#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
2177#[serde(rename_all = "lowercase")]
2178pub enum LogLevel {
2179 Trace,
2181 Debug,
2183 Info,
2185 Warn,
2187 Error,
2189 Fatal,
2191}
2192
2193#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
2196pub struct LogSeverityNumber(u8);
2197
2198impl LogSeverityNumber {
2199 pub const MIN: u8 = 1;
2201 pub const MAX: u8 = 24;
2203}
2204
2205impl TryFrom<u8> for LogSeverityNumber {
2206 type Error = String;
2207
2208 fn try_from(value: u8) -> Result<Self, Self::Error> {
2209 if (LogSeverityNumber::MIN..=LogSeverityNumber::MAX).contains(&value) {
2210 Ok(Self(value))
2211 } else {
2212 Err(format!(
2213 "Log severity number must be between {} and {}",
2214 LogSeverityNumber::MIN,
2215 LogSeverityNumber::MAX
2216 ))
2217 }
2218 }
2219}
2220
2221#[derive(Clone, Debug, PartialEq)]
2223pub struct LogAttribute(pub Value);
2224
2225impl<T> From<T> for LogAttribute
2226where
2227 Value: From<T>,
2228{
2229 fn from(value: T) -> Self {
2230 Self(Value::from(value))
2231 }
2232}
2233
2234impl Serialize for LogAttribute {
2235 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2236 where
2237 S: serde::Serializer,
2238 {
2239 use serde::ser::SerializeStruct;
2240 let mut state = serializer.serialize_struct("LogAttribute", 2)?;
2241
2242 match &self.0 {
2243 Value::String(s) => {
2244 state.serialize_field("value", s.as_str())?;
2245 state.serialize_field("type", "string")?;
2246 }
2247 Value::Number(n) => {
2248 if let Some(i) = n.as_i64() {
2249 state.serialize_field("value", &i)?;
2250 state.serialize_field("type", "integer")?;
2251 } else if let Some(u) = n.as_u64() {
2252 state.serialize_field("value", &u.to_string())?;
2254 state.serialize_field("type", "string")?;
2255 } else if let Some(f) = n.as_f64() {
2256 state.serialize_field("value", &f)?;
2257 state.serialize_field("type", "double")?;
2258 } else {
2259 state.serialize_field("value", &n.to_string())?;
2261 state.serialize_field("type", "string")?;
2262 }
2263 }
2264 Value::Bool(b) => {
2265 state.serialize_field("value", &b)?;
2266 state.serialize_field("type", "boolean")?;
2267 }
2268 _ => {
2270 state.serialize_field("value", &self.0.to_string())?;
2271 state.serialize_field("type", "string")?;
2272 }
2273 }
2274
2275 state.end()
2276 }
2277}
2278
2279impl<'de> Deserialize<'de> for LogAttribute {
2280 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2281 where
2282 D: serde::Deserializer<'de>,
2283 {
2284 use serde::de::{self, MapAccess, Visitor};
2285 use std::fmt;
2286
2287 struct LogAttributeVisitor;
2288
2289 impl<'de> Visitor<'de> for LogAttributeVisitor {
2290 type Value = LogAttribute;
2291
2292 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2293 formatter.write_str("a LogAttribute with value and type fields")
2294 }
2295
2296 fn visit_map<V>(self, mut map: V) -> Result<LogAttribute, V::Error>
2297 where
2298 V: MapAccess<'de>,
2299 {
2300 let mut value: Option<serde_json::Value> = None;
2301 let mut type_str: Option<String> = None;
2302
2303 while let Some(key) = map.next_key::<String>()? {
2304 match key.as_str() {
2305 "value" => {
2306 if value.is_some() {
2307 return Err(de::Error::duplicate_field("value"));
2308 }
2309 value = Some(map.next_value()?);
2310 }
2311 "type" => {
2312 if type_str.is_some() {
2313 return Err(de::Error::duplicate_field("type"));
2314 }
2315 type_str = Some(map.next_value()?);
2316 }
2317 _ => {
2318 let _: serde_json::Value = map.next_value()?;
2320 }
2321 }
2322 }
2323
2324 let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
2325 let type_str = type_str.ok_or_else(|| de::Error::missing_field("type"))?;
2326
2327 match type_str.as_str() {
2328 "string" => {
2329 if !value.is_string() {
2330 return Err(de::Error::custom(
2331 "type is 'string' but value is not a string",
2332 ));
2333 }
2334 }
2335 "integer" => {
2336 if !value.is_i64() {
2337 return Err(de::Error::custom(
2338 "type is 'integer' but value is not an integer",
2339 ));
2340 }
2341 }
2342 "double" => {
2343 if !value.is_f64() {
2344 return Err(de::Error::custom(
2345 "type is 'double' but value is not a double",
2346 ));
2347 }
2348 }
2349 "boolean" => {
2350 if !value.is_boolean() {
2351 return Err(de::Error::custom(
2352 "type is 'boolean' but value is not a boolean",
2353 ));
2354 }
2355 }
2356 _ => {
2357 return Err(de::Error::custom(format!(
2358 "expected type to be 'string' | 'integer' | 'double' | 'boolean', found {type_str}"
2359 )))
2360 }
2361 }
2362
2363 Ok(LogAttribute(value))
2364 }
2365 }
2366
2367 deserializer.deserialize_map(LogAttributeVisitor)
2368 }
2369}
2370
2371#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
2373pub struct OrganizationId(u64);
2374
2375impl From<u64> for OrganizationId {
2376 fn from(value: u64) -> Self {
2377 Self(value)
2378 }
2379}
2380
2381impl std::str::FromStr for OrganizationId {
2382 type Err = std::num::ParseIntError;
2383
2384 fn from_str(s: &str) -> Result<Self, Self::Err> {
2385 s.parse().map(Self)
2386 }
2387}
2388
2389impl std::fmt::Display for OrganizationId {
2390 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2391 write!(f, "{}", self.0)
2392 }
2393}
2394
2395#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
2397pub struct SampleRand(f64);
2398
2399#[derive(Debug, Error)]
2401pub enum InvalidSampleRandError {
2402 #[error("failed to parse f64: {0}")]
2404 InvalidFloat(#[from] std::num::ParseFloatError),
2405
2406 #[error("sample rand value out of admissible interval [0.0, 1.0)")]
2409 OutOfRange,
2410}
2411
2412impl TryFrom<f64> for SampleRand {
2413 type Error = InvalidSampleRandError;
2414
2415 fn try_from(value: f64) -> Result<Self, Self::Error> {
2416 if !(0.0..1.0).contains(&value) {
2417 return Err(InvalidSampleRandError::OutOfRange);
2418 }
2419 Ok(Self(value))
2420 }
2421}
2422
2423impl std::str::FromStr for SampleRand {
2424 type Err = InvalidSampleRandError;
2425
2426 fn from_str(s: &str) -> Result<Self, Self::Err> {
2427 let x: f64 = s.parse().map_err(InvalidSampleRandError::InvalidFloat)?;
2428 Self::try_from(x)
2429 }
2430}
2431
2432impl std::fmt::Display for SampleRand {
2433 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2434 if self.0 >= 0.9999995 {
2438 write!(f, "0.999999")
2439 } else {
2440 write!(f, "{:.6}", self.0)
2441 }
2442 }
2443}
2444
2445#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
2453pub struct DynamicSamplingContext {
2454 #[serde(default, skip_serializing_if = "Option::is_none")]
2457 trace_id: Option<TraceId>,
2458 #[serde(default, skip_serializing_if = "Option::is_none")]
2459 public_key: Option<String>,
2460 #[serde(
2461 default,
2462 skip_serializing_if = "Option::is_none",
2463 with = "display_from_str_opt"
2464 )]
2465 sample_rate: Option<f32>,
2466 #[serde(
2468 default,
2469 skip_serializing_if = "Option::is_none",
2470 with = "display_from_str_opt"
2471 )]
2472 sample_rand: Option<SampleRand>,
2473 #[serde(
2474 default,
2475 skip_serializing_if = "Option::is_none",
2476 with = "display_from_str_opt"
2477 )]
2478 sampled: Option<bool>,
2479 #[serde(default, skip_serializing_if = "Option::is_none")]
2480 release: Option<String>,
2481 #[serde(default, skip_serializing_if = "Option::is_none")]
2482 environment: Option<String>,
2483 #[serde(default, skip_serializing_if = "Option::is_none")]
2484 transaction: Option<String>,
2485 #[serde(
2486 default,
2487 skip_serializing_if = "Option::is_none",
2488 with = "display_from_str_opt"
2489 )]
2490 org_id: Option<OrganizationId>,
2491}
2492
2493impl DynamicSamplingContext {
2494 pub fn new() -> Self {
2496 Default::default()
2497 }
2498
2499 #[must_use]
2501 pub fn with_trace_id(mut self, trace_id: TraceId) -> Self {
2502 self.trace_id = Some(trace_id);
2503 self
2504 }
2505
2506 #[must_use]
2508 pub fn with_public_key(mut self, public_key: String) -> Self {
2509 self.public_key = Some(public_key);
2510 self
2511 }
2512
2513 #[must_use]
2515 pub fn with_sample_rate(mut self, sample_rate: f32) -> Self {
2516 self.sample_rate = Some(sample_rate);
2517 self
2518 }
2519
2520 #[must_use]
2522 pub fn with_sample_rand(mut self, sample_rand: SampleRand) -> Self {
2523 self.sample_rand = Some(sample_rand);
2524 self
2525 }
2526
2527 #[must_use]
2529 pub fn with_sampled(mut self, sampled: bool) -> Self {
2530 self.sampled = Some(sampled);
2531 self
2532 }
2533
2534 #[must_use]
2536 pub fn with_release(mut self, release: String) -> Self {
2537 self.release = Some(release);
2538 self
2539 }
2540
2541 #[must_use]
2543 pub fn with_environment(mut self, environment: String) -> Self {
2544 self.environment = Some(environment);
2545 self
2546 }
2547
2548 #[must_use]
2550 pub fn with_transaction(mut self, transaction: String) -> Self {
2551 self.transaction = Some(transaction);
2552 self
2553 }
2554
2555 #[must_use]
2557 pub fn with_org_id(mut self, org_id: OrganizationId) -> Self {
2558 self.org_id = Some(org_id);
2559 self
2560 }
2561}