@@ -7,45 +7,133 @@ use chrono::{DateTime, Utc};
7
7
use url_serde;
8
8
use url:: Url ;
9
9
use serde:: de:: { Deserialize , Deserializer , Error as DeError } ;
10
- use serde:: ser:: { Error as SerError , SerializeMap , Serializer } ;
10
+ use serde:: ser:: { Error as SerError , Serialize , SerializeMap , Serializer } ;
11
11
use serde_json:: { from_value, to_value, Value } ;
12
12
13
13
/// Represents a log entry message.
14
+ ///
15
+ /// A log message is similar to the `message` attribute on the event itself but
16
+ /// can additionally hold optional parameters.
14
17
#[ derive( Serialize , Deserialize , Default , Clone , Debug , PartialEq ) ]
15
18
pub struct LogEntry {
19
+ /// The log message with parameters replaced by `%s`
16
20
pub message : String ,
17
- #[ serde( skip_serializing_if = "Vec::is_empty" ) ] pub params : Vec < Value > ,
21
+ /// Positional parameters to be inserted into the log entry.
22
+ #[ serde( skip_serializing_if = "Vec::is_empty" ) ]
23
+ pub params : Vec < Value > ,
18
24
}
19
25
20
26
/// Represents a frame.
21
27
#[ derive( Serialize , Deserialize , Default , Clone , Debug , PartialEq ) ]
22
28
pub struct Frame {
23
- pub filename : String ,
29
+ /// The name of the function is known.
30
+ ///
31
+ /// Note that this might include the name of a class as well if that makes
32
+ /// sense for the language.
33
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
34
+ pub function : Option < String > ,
35
+ /// The potentially mangled name of the symbol as it appears in an executable.
36
+ ///
37
+ /// This is different from a function name by generally being the mangled
38
+ /// name that appears natively in the binary. This is relevant for languages
39
+ /// like Swift, C++ or Rust.
40
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
41
+ pub symbol : Option < String > ,
42
+ /// The name of the module the frame is contained in.
43
+ ///
44
+ /// Note that this might also include a class name if that is something the
45
+ /// language natively considers to be part of the stack (for instance in Java).
46
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
47
+ pub module : Option < String > ,
48
+ /// The name of the package that contains the frame.
49
+ ///
50
+ /// For instance this can be a dylib for native languages, the name of the jar
51
+ /// or .NET assembly.
52
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
53
+ pub package : Option < String > ,
54
+ /// Location information about where the error originated.
55
+ #[ serde( flatten) ]
56
+ pub location : FileLocation ,
57
+ /// Embedded sourcecode in the frame.
58
+ #[ serde( flatten) ]
59
+ pub source : EmbeddedSources ,
60
+ /// In-app indicator.
61
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
62
+ pub in_app : Option < bool > ,
63
+ /// Optional local variables.
64
+ #[ serde( skip_serializing_if = "HashMap::is_empty" ) ]
65
+ pub vars : HashMap < String , Value > ,
66
+ /// Optional instruction information for native languages.
67
+ #[ serde( flatten) ]
68
+ pub instruction_info : InstructionInfo ,
69
+ }
70
+
71
+ /// Represents location information.
72
+ #[ derive( Serialize , Deserialize , Debug , Default , Clone , PartialEq ) ]
73
+ pub struct FileLocation {
74
+ /// The filename (basename only).
75
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
76
+ pub filename : Option < String > ,
77
+ /// If known the absolute path.
78
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
24
79
pub abs_path : Option < String > ,
25
- pub function : String ,
26
- pub lineno : Option < u32 > ,
27
- pub context_line : Option < String > ,
28
- pub pre_context : Option < Vec < String > > ,
29
- pub post_context : Option < Vec < String > > ,
80
+ /// The line number if known.
81
+ #[ serde( rename = "lineno" , skip_serializing_if = "Option::is_none" ) ]
82
+ pub line : Option < u64 > ,
83
+ /// The column number if known.
84
+ #[ serde( rename = "colno" , skip_serializing_if = "Option::is_none" ) ]
85
+ pub column : Option < u64 > ,
86
+ }
87
+
88
+ /// Represents instruction information.
89
+ #[ derive( Serialize , Deserialize , Debug , Default , Clone , PartialEq ) ]
90
+ pub struct InstructionInfo {
91
+ /// If known the location of the image.
92
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
93
+ pub image_addr : Option < u64 > ,
94
+ /// If known the location of the instruction.
95
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
96
+ pub instruction_addr : Option < u64 > ,
97
+ /// If known the location of symbol.
98
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
99
+ pub symbol_addr : Option < u64 > ,
100
+ }
101
+
102
+ /// Represents contextual information in a frame.
103
+ #[ derive( Serialize , Deserialize , Debug , Default , Clone , PartialEq ) ]
104
+ pub struct EmbeddedSources {
105
+ /// The sources of the lines leading up to the current line.
106
+ #[ serde( rename = "pre_context" ) ]
107
+ pub pre_lines : Option < Vec < String > > ,
108
+ /// The current line as source.
109
+ #[ serde( rename = "context_line" ) ]
110
+ pub current_line : Option < String > ,
111
+ /// The sources of the lines after the current line.
112
+ #[ serde( rename = "post_context" ) ]
113
+ pub post_lines : Option < Vec < String > > ,
30
114
}
31
115
32
116
/// Represents a stacktrace.
33
117
#[ derive( Serialize , Deserialize , Debug , Default , Clone , PartialEq ) ]
34
118
pub struct Stacktrace {
119
+ /// The list of frames in the stacktrace.
35
120
pub frames : Vec < Frame > ,
36
- }
37
-
38
- /// Represents a list of exceptions.
39
- #[ derive( Serialize , Deserialize , Default , Clone , Debug , PartialEq ) ]
40
- pub struct Exception {
41
- pub values : Vec < SingleException > ,
121
+ /// Optionally a segment of frames removed (`start`, `end`)
122
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
123
+ pub frames_omitted : Option < ( u64 , u64 ) > ,
42
124
}
43
125
44
126
/// Represents a single exception
45
127
#[ derive( Serialize , Deserialize , Debug , Default , Clone , PartialEq ) ]
46
- pub struct SingleException {
47
- #[ serde( rename = "type" ) ] pub ty : String ,
48
- pub value : String ,
128
+ pub struct Exception {
129
+ /// The type of the exception
130
+ #[ serde( rename = "type" ) ]
131
+ pub ty : String ,
132
+ /// The optional value of the exception
133
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
134
+ pub value : Option < String > ,
135
+ /// Optionally the stacktrace.
136
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
49
137
pub stacktrace : Option < Stacktrace > ,
50
138
}
51
139
@@ -163,7 +251,9 @@ pub struct Event {
163
251
deserialize_with = "deserialize_context" ) ]
164
252
pub contexts : HashMap < String , Context > ,
165
253
#[ serde( skip_serializing_if = "Vec::is_empty" ) ] pub breadcrumbs : Vec < Breadcrumb > ,
166
- #[ serde( skip_serializing_if = "Option::is_none" ) ] pub exception : Option < Exception > ,
254
+ #[ serde( skip_serializing_if = "Vec::is_empty" , serialize_with = "serialize_exceptions" ,
255
+ deserialize_with = "deserialize_exceptions" , rename = "exception" ) ]
256
+ pub exceptions : Vec < Exception > ,
167
257
#[ serde( skip_serializing_if = "HashMap::is_empty" ) ] pub tags : HashMap < String , String > ,
168
258
#[ serde( skip_serializing_if = "HashMap::is_empty" ) ] pub extra : HashMap < String , Value > ,
169
259
#[ serde( flatten) ] pub other : HashMap < String , Value > ,
@@ -329,3 +419,32 @@ where
329
419
330
420
map. end ( )
331
421
}
422
+
423
+ fn deserialize_exceptions < ' de , D > ( deserializer : D ) -> Result < Vec < Exception > , D :: Error >
424
+ where
425
+ D : Deserializer < ' de > ,
426
+ {
427
+ #[ derive( Deserialize ) ]
428
+ #[ serde( untagged) ]
429
+ enum Repr {
430
+ Qualified { values : Vec < Exception > } ,
431
+ Unqualified ( Vec < Exception > ) ,
432
+ Single ( Exception ) ,
433
+ }
434
+ Repr :: deserialize ( deserializer) . map ( |x| match x {
435
+ Repr :: Qualified { values } => values,
436
+ Repr :: Unqualified ( values) => values,
437
+ Repr :: Single ( exc) => vec ! [ exc] ,
438
+ } )
439
+ }
440
+
441
+ fn serialize_exceptions < S > ( value : & Vec < Exception > , serializer : S ) -> Result < S :: Ok , S :: Error >
442
+ where
443
+ S : Serializer ,
444
+ {
445
+ #[ derive( Serialize ) ]
446
+ struct Helper < ' a > {
447
+ values : & ' a [ Exception ] ,
448
+ }
449
+ Helper { values : & value } . serialize ( serializer)
450
+ }
0 commit comments