@@ -76,6 +76,179 @@ macro_rules! message_event {
7676 } ;
7777}
7878
79+ /// Implement a `Handler` call, with metrics recording and response building.
80+ macro_rules! impl_handler_call {
81+ ( @metrics, $success: expr, $id: expr, $service: expr, $method: expr) => { {
82+ // Record the metrics.
83+ $crate:: metrics:: record_execution( $success, $service, $method) ;
84+ $crate:: metrics:: record_output( $id. is_some( ) , $service, $method) ;
85+ } } ;
86+
87+ ( @record_span, $span: expr, $payload: expr) => {
88+ if let Some ( e) = $payload. as_error( ) {
89+ use tracing_opentelemetry:: OpenTelemetrySpanExt ;
90+ $span. record( "rpc.jsonrpc.error_code" , e. code) ;
91+ $span. record( "rpc.jsonrpc.error_message" , e. message. as_ref( ) ) ;
92+ $span. set_status( :: opentelemetry:: trace:: Status :: Error {
93+ description: e. message. clone( ) ,
94+ } ) ;
95+ }
96+ } ;
97+
98+ // Hit the metrics and return the payload if any.
99+ ( @finish $span: expr, $id: expr, $service: expr, $method: expr, $payload: expr) => { {
100+ impl_handler_call!( @metrics, $payload. is_success( ) , $id, $service, $method) ;
101+ impl_handler_call!( @record_span, $span, $payload) ;
102+ return Response :: build_response( $id. as_deref( ) , $payload) ;
103+ } } ;
104+
105+ ( @unpack_params $span: expr, $id: expr, $service: expr, $method: expr, $req: expr) => { {
106+ let Ok ( params) = $req. deser_params( ) else {
107+ impl_handler_call!( @finish $span, $id, $service, $method, & ResponsePayload :: <( ) , ( ) >:: invalid_params( ) ) ;
108+ } ;
109+ drop( $req) ; // no longer needed
110+ params
111+ } } ;
112+
113+ ( @unpack_struct_params $span: expr, $id: expr, $service: expr, $method: expr, $req: expr) => { {
114+ let Ok ( params) = $req. deser_params( ) else {
115+ impl_handler_call!( @finish $span, $id, $service, $method, & ResponsePayload :: <( ) , ( ) >:: invalid_params( ) ) ;
116+ } ;
117+ drop( $req) ; // no longer needed
118+ params
119+ } } ;
120+
121+ ( @unpack $args: expr) => { {
122+ let id = $args. id_owned( ) ;
123+ let ( ctx, req) = $args. into_parts( ) ;
124+ let inst = ctx. span( ) . clone( ) ;
125+ let span = ctx. span( ) . clone( ) ;
126+ let method = req. method( ) . to_string( ) ;
127+ let service = ctx. service_name( ) ;
128+
129+ ( id, ctx, inst, span, method, service, req)
130+ } } ;
131+
132+ // NO ARGS
133+ ( $args: expr, $this: ident( ) ) => { {
134+ let ( id, ctx, inst, span, method, service, req) = impl_handler_call!( @unpack $args) ;
135+ drop( ctx) ; // no longer needed
136+ drop( req) ; // no longer needed
137+
138+ Box :: pin(
139+ async move {
140+ let payload: $crate:: ResponsePayload <_, _> = $this( ) . await . into( ) ;
141+ impl_handler_call!( @finish span, id, service, & method, & payload) ;
142+ }
143+ . instrument( inst) ,
144+ )
145+ } } ;
146+
147+ // CTX only
148+ ( $args: expr, $this: ident( ctx) ) => { {
149+ let ( id, ctx, inst, span, method, service, req) = impl_handler_call!( @unpack $args) ;
150+ drop( req) ; // no longer needed
151+
152+ Box :: pin(
153+ async move {
154+ let payload: $crate:: ResponsePayload <_, _> = $this( ctx) . await . into( ) ;
155+ impl_handler_call!( @finish span, id, service, & method, & payload) ;
156+ }
157+ . instrument( inst) ,
158+ )
159+ } } ;
160+
161+
162+ // PARAMS only
163+ ( $args: expr, $this: ident( params: $params_ty: ty) ) => { {
164+ let ( id, ctx, inst, span, method, service, req) = impl_handler_call!( @unpack $args) ;
165+ drop( ctx) ; // no longer needed
166+
167+ Box :: pin(
168+ async move {
169+ let params: $params_ty = impl_handler_call!( @unpack_params span, id, service, & method, req) ;
170+ let payload: $crate:: ResponsePayload <_, _> = $this( params. into( ) ) . await . into( ) ;
171+ impl_handler_call!( @finish span, id, service, & method, & payload) ;
172+ }
173+ . instrument( inst) ,
174+ )
175+ } } ;
176+
177+
178+ // STATE only
179+ ( $args: expr, $this: ident( $state: expr) ) => { {
180+ let ( id, ctx, inst, span, method, service, req) = impl_handler_call!( @unpack $args) ;
181+ drop( ctx) ; // no longer needed
182+ drop( req) ; // no longer needed
183+
184+ Box :: pin(
185+ async move {
186+ let payload: $crate:: ResponsePayload <_, _> = $this( $state) . await . into( ) ;
187+ impl_handler_call!( @finish span, id, service, & method, & payload) ;
188+ }
189+ . instrument( inst) ,
190+ )
191+ } } ;
192+
193+
194+ // CTX and PARAMS
195+ ( $args: expr, $this: ident( ctx, params: $params_ty: ty) ) => { {
196+ let ( id, ctx, inst, span, method, service, req) = impl_handler_call!( @unpack $args) ;
197+
198+ Box :: pin(
199+ async move {
200+ let params: $params_ty = impl_handler_call!( @unpack_params span, id, service, & method, req) ;
201+ let payload: $crate:: ResponsePayload <_, _> = $this( ctx, params. into( ) ) . await . into( ) ;
202+ impl_handler_call!( @finish span, id, service, & method, & payload) ;
203+ }
204+ . instrument( inst) ,
205+ )
206+ } } ;
207+
208+ // CTX and STATE
209+ ( $args: expr, $this: ident( ctx, $state: expr) ) => { {
210+ let ( id, ctx, inst, span, method, service, req) = impl_handler_call!( @unpack $args) ;
211+ drop( req) ; // no longer needed
212+
213+ Box :: pin(
214+ async move {
215+ let payload: $crate:: ResponsePayload <_, _> = $this( ctx, $state) . await . into( ) ;
216+ impl_handler_call!( @finish span, id, service, & method, & payload) ;
217+ }
218+ . instrument( inst) ,
219+ )
220+ } } ;
221+
222+ // PARAMS and STATE
223+ ( $args: expr, $this: ident( params: $params_ty: ty, $state: expr) ) => { {
224+ let ( id, ctx, inst, span, method, service, req) = impl_handler_call!( @unpack $args) ;
225+ drop( ctx) ; // no longer needed
226+
227+ Box :: pin(
228+ async move {
229+ let params: $params_ty = impl_handler_call!( @unpack_params span, id, service, & method, req) ;
230+ let payload: $crate:: ResponsePayload <_, _> = $this( params. into( ) , $state) . await . into( ) ;
231+ impl_handler_call!( @finish span, id, service, & method, & payload) ;
232+ }
233+ . instrument( inst) ,
234+ )
235+ } } ;
236+
237+ // CTX and PARAMS and STATE
238+ ( $args: expr, $this: ident( ctx, params: $params_ty: ty, $state: expr) ) => { {
239+ let ( id, ctx, inst, span, method, service, req) = impl_handler_call!( @unpack $args) ;
240+
241+ Box :: pin(
242+ async move {
243+ let params: $params_ty = impl_handler_call!( @unpack_params span, id, service, & method, req) ;
244+ let payload: $crate:: ResponsePayload <_, _> = $this( ctx, params. into( ) , $state) . await . into( ) ;
245+ impl_handler_call!( @finish span, id, service, & method, & payload) ;
246+ }
247+ . instrument( inst) ,
248+ )
249+ } } ;
250+ }
251+
79252// Some code is this file is reproduced under the terms of the MIT license. It
80253// originates from the `axum` crate. The original source code can be found at
81254// the following URL, and the original license is included below.
0 commit comments