macro_rules! map_inner {
( $self_:ident, $inner:pat_param => $expr:expr) => {
#[allow(redundant_semicolons)]
{
let $inner = $self_.into_inner();
Router {
inner: Arc::new($expr),
}
}
};
}
macro_rules! tap_inner {
( $self_:ident, mut $inner:ident => { $($stmt:stmt)* } ) => {
#[allow(redundant_semicolons)]
{
let mut $inner = $self_.into_inner();
$($stmt)*
Router {
inner: Arc::new($inner),
}
}
};
}
macro_rules! panic_on_err {
($expr:expr) => {
match $expr {
Ok(x) => x,
Err(err) => panic!("{err}"),
}
};
}
#[allow(unused_macros)] macro_rules! unwrap_infallible {
($expr:expr) => {
match $expr {
Ok(x) => x,
Err(_) => unreachable!("Infallible"),
}
};
}
macro_rules! message_event {
($type:literal, counter: $counter:expr, bytes: $bytes:expr,) => {{
::tracing::info!(
"rpc.message.id" = $counter.fetch_add(1, ::std::sync::atomic::Ordering::Relaxed),
"rpc.message.type" = $type,
"rpc.message.uncompressed_size" = $bytes,
"rpc.message"
);
}};
(@received, counter: $counter:expr, bytes: $bytes:expr, ) => {
message_event!("RECEIVED", counter: $counter, bytes: $bytes,);
};
(@sent, counter: $counter:expr, bytes: $bytes:expr, ) => {
message_event!("SENT", counter: $counter, bytes: $bytes,);
};
}
macro_rules! impl_handler_call {
(@metrics, $success:expr, $id:expr, $service:expr, $method:expr) => {{
$crate::metrics::record_execution($success, $service, $method);
$crate::metrics::record_output($id.is_some(), $service, $method);
}};
(@record_span, $span:expr, $payload:expr) => {
if let Some(e) = $payload.as_error() {
use tracing_opentelemetry::OpenTelemetrySpanExt;
$span.record("rpc.jsonrpc.error_code", e.code);
$span.record("rpc.jsonrpc.error_message", e.message.as_ref());
$span.set_status(::opentelemetry::trace::Status::Error {
description: e.message.clone(),
});
}
};
(@finish $span:expr, $id:expr, $service:expr, $method:expr, $payload:expr) => {{
impl_handler_call!(@metrics, $payload.is_success(), $id, $service, $method);
impl_handler_call!(@record_span, $span, $payload);
return Response::build_response($id.as_deref(), $payload);
}};
(@unpack_params $span:expr, $id:expr, $service:expr, $method:expr, $req:expr) => {{
let Ok(params) = $req.deser_params() else {
impl_handler_call!(@finish $span, $id, $service, $method, ResponsePayload::<(), ()>::invalid_params());
};
drop($req); params
}};
(@unpack_struct_params $span:expr, $id:expr, $service:expr, $method:expr, $req:expr) => {{
let Ok(params) = $req.deser_params() else {
impl_handler_call!(@finish $span, $id, $service, $method, ResponsePayload::<(), ()>::invalid_params());
};
drop($req); params
}};
(@unpack $args:expr) => {{
let id = $args.id_owned();
let (ctx, req) = $args.into_parts();
let inst = ctx.span().clone();
let span = ctx.span().clone();
let method = req.method().to_string();
let service = ctx.service_name();
(id, ctx, inst, span, method, service, req)
}};
($args:expr, $this:ident()) => {{
let (id, ctx, inst, span, method, service, req) = impl_handler_call!(@unpack $args);
drop(ctx); drop(req);
Box::pin(
async move {
let payload: $crate::ResponsePayload<_, _> = $this().await.into();
impl_handler_call!(@finish span, id, service, &method, payload);
}
.instrument(inst),
)
}};
($args:expr, $this:ident(ctx)) => {{
let (id, ctx, inst, span, method, service, req) = impl_handler_call!(@unpack $args);
drop(req);
Box::pin(
async move {
let payload: $crate::ResponsePayload<_, _> = $this(ctx).await.into();
impl_handler_call!(@finish span, id, service, &method, payload);
}
.instrument(inst),
)
}};
($args:expr, $this:ident(params: $params_ty:ty)) => {{
let (id, ctx, inst, span, method, service, req) = impl_handler_call!(@unpack $args);
drop(ctx);
Box::pin(
async move {
let params: $params_ty = impl_handler_call!(@unpack_params span, id, service, &method, req);
let payload: $crate::ResponsePayload<_, _> = $this(params.into()).await.into();
impl_handler_call!(@finish span, id, service, &method, payload);
}
.instrument(inst),
)
}};
($args:expr, $this:ident($state:expr)) => {{
let (id, ctx, inst, span, method, service, req) = impl_handler_call!(@unpack $args);
drop(ctx); drop(req);
Box::pin(
async move {
let payload: $crate::ResponsePayload<_, _> = $this($state).await.into();
impl_handler_call!(@finish span, id, service, &method, payload);
}
.instrument(inst),
)
}};
($args:expr, $this:ident(ctx, params: $params_ty:ty)) => {{
let (id, ctx, inst, span, method, service, req) = impl_handler_call!(@unpack $args);
Box::pin(
async move {
let params: $params_ty = impl_handler_call!(@unpack_params span, id, service, &method, req);
let payload: $crate::ResponsePayload<_, _> = $this(ctx, params.into()).await.into();
impl_handler_call!(@finish span, id, service, &method, payload);
}
.instrument(inst),
)
}};
($args:expr, $this:ident(ctx, $state:expr)) => {{
let (id, ctx, inst, span, method, service, req) = impl_handler_call!(@unpack $args);
drop(req);
Box::pin(
async move {
let payload: $crate::ResponsePayload<_, _> = $this(ctx, $state).await.into();
impl_handler_call!(@finish span, id, service, &method, payload);
}
.instrument(inst),
)
}};
($args:expr, $this:ident(params: $params_ty:ty, $state:expr)) => {{
let (id, ctx, inst, span, method, service, req) = impl_handler_call!(@unpack $args);
drop(ctx);
Box::pin(
async move {
let params: $params_ty = impl_handler_call!(@unpack_params span, id, service, &method, req);
let payload: $crate::ResponsePayload<_, _> = $this(params.into(), $state).await.into();
impl_handler_call!(@finish span, id, service, &method, payload);
}
.instrument(inst),
)
}};
($args:expr, $this:ident(ctx, params: $params_ty:ty, $state:expr)) => {{
let (id, ctx, inst, span, method, service, req) = impl_handler_call!(@unpack $args);
Box::pin(
async move {
let params: $params_ty = impl_handler_call!(@unpack_params span, id, service, &method, req);
let payload: $crate::ResponsePayload<_, _> = $this(ctx, params.into(), $state).await.into();
impl_handler_call!(@finish span, id, service, &method, payload);
}
.instrument(inst),
)
}};
}