@@ -30,7 +30,7 @@ impl From<SendError<WriteItem>> for NotifyError {
3030
3131/// Tracing information for OpenTelemetry. This struct is used to store
3232/// information about the current request that can be used for tracing.
33- #[ derive( Debug ) ]
33+ #[ derive( Debug , Clone ) ]
3434#[ non_exhaustive]
3535pub struct TracingInfo {
3636 /// The OpenTelemetry service name.
@@ -43,16 +43,6 @@ pub struct TracingInfo {
4343 span : OnceLock < tracing:: Span > ,
4444}
4545
46- impl Clone for TracingInfo {
47- fn clone ( & self ) -> Self {
48- Self {
49- service : self . service ,
50- context : self . context . clone ( ) ,
51- span : OnceLock :: new ( ) ,
52- }
53- }
54- }
55-
5646impl TracingInfo {
5747 /// Create a new tracing info with the given service name and no context.
5848 #[ allow( dead_code) ] // used in some features
@@ -76,6 +66,43 @@ impl TracingInfo {
7666 }
7767 }
7868
69+ fn make_span < S > (
70+ & self ,
71+ router : & Router < S > ,
72+ with_notifications : bool ,
73+ parent : Option < & tracing:: Span > ,
74+ ) -> tracing:: Span
75+ where
76+ S : Clone + Send + Sync + ' static ,
77+ {
78+ let span = info_span ! (
79+ parent: parent. and_then( |p| p. id( ) ) ,
80+ "AjjRequest" ,
81+ "otel.kind" = "server" ,
82+ "rpc.system" = "jsonrpc" ,
83+ "rpc.jsonrpc.version" = "2.0" ,
84+ "rpc.service" = router. service_name( ) ,
85+ notifications_enabled = with_notifications,
86+ "trace_id" = :: tracing:: field:: Empty ,
87+ "otel.name" = :: tracing:: field:: Empty ,
88+ "otel.status_code" = :: tracing:: field:: Empty ,
89+ "rpc.jsonrpc.request_id" = :: tracing:: field:: Empty ,
90+ "rpc.jsonrpc.error_code" = :: tracing:: field:: Empty ,
91+ "rpc.jsonrpc.error_message" = :: tracing:: field:: Empty ,
92+ "rpc.method" = :: tracing:: field:: Empty ,
93+ params = :: tracing:: field:: Empty ,
94+ ) ;
95+ if let Some ( context) = & self . context {
96+ let _ = span. set_parent ( context. clone ( ) ) ;
97+
98+ span. record (
99+ "trace_id" ,
100+ context. span ( ) . span_context ( ) . trace_id ( ) . to_string ( ) ,
101+ ) ;
102+ }
103+ span
104+ }
105+
79106 /// Create a request span for a handler invocation.
80107 fn init_request_span < S > (
81108 & self ,
@@ -89,35 +116,23 @@ impl TracingInfo {
89116 // This span is populated with as much detail as possible, and then
90117 // given to the Request. It will be populated with request-specific
91118 // details (e.g. method) during request setup.
92- self . span . get_or_init ( || {
93- let span = info_span ! (
94- parent: parent. and_then( |p| p. id( ) ) ,
95- "AjjRequest" ,
96- "otel.kind" = "server" ,
97- "rpc.system" = "jsonrpc" ,
98- "rpc.jsonrpc.version" = "2.0" ,
99- "rpc.service" = router. service_name( ) ,
100- notifications_enabled = with_notifications,
101- "trace_id" = :: tracing:: field:: Empty ,
102- "otel.name" = :: tracing:: field:: Empty ,
103- "otel.status_code" = :: tracing:: field:: Empty ,
104- "rpc.jsonrpc.request_id" = :: tracing:: field:: Empty ,
105- "rpc.jsonrpc.error_code" = :: tracing:: field:: Empty ,
106- "rpc.jsonrpc.error_message" = :: tracing:: field:: Empty ,
107- "rpc.method" = :: tracing:: field:: Empty ,
108- params = :: tracing:: field:: Empty ,
109- ) ;
110- if let Some ( context) = & self . context {
111- let _ = span. set_parent ( context. clone ( ) ) ;
112-
113- span. record (
114- "trace_id" ,
115- context. span ( ) . span_context ( ) . trace_id ( ) . to_string ( ) ,
116- ) ;
117- }
119+ self . span
120+ . get_or_init ( || self . make_span ( router, with_notifications, parent) )
121+ }
118122
119- span
120- } )
123+ /// Create a child tracing info for a new handler context.
124+ pub fn child < S : Clone + Send + Sync + ' static > (
125+ & self ,
126+ router : & Router < S > ,
127+ with_notifications : bool ,
128+ parent : Option < & tracing:: Span > ,
129+ ) -> Self {
130+ let span = self . make_span ( router, with_notifications, parent) ;
131+ Self {
132+ service : self . service ,
133+ context : self . context . clone ( ) ,
134+ span : OnceLock :: from ( span) ,
135+ }
121136 }
122137
123138 /// Get a reference to the tracing span for this request.
@@ -186,6 +201,24 @@ impl HandlerCtx {
186201 }
187202 }
188203
204+ /// Create a child handler context for a new handler invocation.
205+ ///
206+ /// This is used when handling batch requests, to give each handler
207+ /// its own context.
208+ pub fn child_ctx < S : Clone + Send + Sync + ' static > (
209+ & self ,
210+ router : & Router < S > ,
211+ parent : Option < & tracing:: Span > ,
212+ ) -> Self {
213+ Self {
214+ notifications : self . notifications . clone ( ) ,
215+ tasks : self . tasks . clone ( ) ,
216+ tracing : self
217+ . tracing
218+ . child ( router, self . notifications_enabled ( ) , parent) ,
219+ }
220+ }
221+
189222 /// Get a reference to the tracing information for this handler context.
190223 pub const fn tracing_info ( & self ) -> & TracingInfo {
191224 & self . tracing
0 commit comments