1
1
use std:: { borrow:: Cow , collections:: HashMap , num:: NonZeroU64 , sync:: Arc } ;
2
2
3
+ use derive_more:: Display ;
3
4
use serde:: { Deserialize , Serialize } ;
4
5
use tokio:: time:: Instant ;
5
6
use tracing:: Level ;
6
7
7
8
use crate :: models:: { LogLevel , SpanKind , TraceSpan } ;
8
9
9
- #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
10
+ #[ derive( Debug , Display , Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
11
+ #[ display( fmt = "{}" , _0) ]
10
12
struct SerializableNonZeroU64 ( NonZeroU64 ) ;
11
13
12
14
impl Serialize for SerializableNonZeroU64 {
@@ -17,7 +19,7 @@ impl Serialize for SerializableNonZeroU64 {
17
19
// Serialize as string to preserve full u64 precision in JavaScript. Otherwise values
18
20
// larger than 2^53 - 1 will be parsed as floats on the client side, making it possible for
19
21
// IDs to collide.
20
- self . 0 . to_string ( ) . serialize ( serializer)
22
+ self . to_string ( ) . serialize ( serializer)
21
23
}
22
24
}
23
25
@@ -34,6 +36,35 @@ impl<'de> Deserialize<'de> for SerializableNonZeroU64 {
34
36
}
35
37
}
36
38
39
+ #[ derive( Debug , Display , Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
40
+ #[ display( fmt = "{}" , _0) ]
41
+ struct SerializableU64 ( u64 ) ;
42
+
43
+ impl Serialize for SerializableU64 {
44
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
45
+ where
46
+ S : serde:: Serializer ,
47
+ {
48
+ // Serialize as string to preserve full u64 precision in JavaScript. Otherwise values
49
+ // larger than 2^53 - 1 will be parsed as floats on the client side, making it possible for
50
+ // IDs to collide.
51
+ self . to_string ( ) . serialize ( serializer)
52
+ }
53
+ }
54
+
55
+ impl < ' de > Deserialize < ' de > for SerializableU64 {
56
+ fn deserialize < D > ( deserializer : D ) -> Result < SerializableU64 , D :: Error >
57
+ where
58
+ D : serde:: Deserializer < ' de > ,
59
+ {
60
+ let value = String :: deserialize ( deserializer) ?;
61
+ let value = value. parse ( ) . map_err ( serde:: de:: Error :: custom) ?;
62
+ Ok ( SerializableU64 ( value) )
63
+ }
64
+ }
65
+
66
+ /// A unique identifier for a span. It maps directly to [`tracing::span::Id`] assigned by
67
+ /// [`tracing_subscriber::registry::Registry`].
37
68
#[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash , Serialize ) ]
38
69
pub struct SpanId ( SerializableNonZeroU64 ) ;
39
70
@@ -49,6 +80,22 @@ impl From<tracing::span::Id> for SpanId {
49
80
}
50
81
}
51
82
83
+ /// A unique identifier for an engine trace, representing a tree of spans. These internal traces *do
84
+ /// not* correspond to OpenTelemetry traces defined by [`crate::capturing::ng::traceparent::TraceParent`].
85
+ /// One OpenTelemetry trace may contain multiple Prisma Client operations, each of them leading to
86
+ /// one or more engine requests. Since engine traces map 1:1 to requests to the engine, we call
87
+ /// these trace IDs "request IDs" to disambiguate and avoid confusion.
88
+ ///
89
+ /// We don't use IDs of the root spans themselves for this purpose because span IDs are only
90
+ /// guaranteed to be unique among the spans active at the same time. They may be reused after a
91
+ /// span is closed, so they are not historically unique. We store the collected spans and events
92
+ /// for some short time after the spans are closed until the client requests them, so we need
93
+ /// request IDs that are guaranteed to be unique for a very long period of time (although they
94
+ /// still don't necessarily have to be unique for the whole lifetime of the process).
95
+ pub struct RequestId ( SerializableU64 ) ;
96
+
97
+ impl RequestId { }
98
+
52
99
#[ derive( Debug , Clone ) ]
53
100
#[ cfg_attr( test, derive( Serialize ) ) ]
54
101
pub struct CollectedSpan {
0 commit comments