fuel_indexer_macro_utils/
lib.rs1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use proc_macro_error::proc_macro_error;
5use quote::quote;
6use syn::{parse_macro_input, ItemFn};
7
8fn process_with_prometheus_metrics(input: TokenStream) -> TokenStream {
9 let ast = parse_macro_input!(input as ItemFn);
10 let fn_name = &ast.sig.ident;
11 let label = fn_name.to_string();
12 let fn_inputs = &ast.sig.inputs;
13 let fn_output = &ast.sig.output;
14 let fn_vis = &ast.vis;
15 let block = &ast.block;
16
17 let (asyncness, awaitness) = if ast.sig.asyncness.is_none() {
18 (quote! {}, quote! {})
19 } else {
20 (quote! {async}, quote! {.await})
21 };
22
23 let input_idents = fn_inputs
24 .iter()
25 .map(|input| match input {
26 syn::FnArg::Typed(typed) => typed.pat.clone(),
27 syn::FnArg::Receiver(_) => panic!("`self` arguments are not supported"),
28 })
29 .collect::<Vec<_>>();
30
31 let gen = quote! {
32 #fn_vis #asyncness fn #fn_name(#fn_inputs) #fn_output {
33 let result = {
34 let start_time = Instant::now();
35 #asyncness fn inner(#fn_inputs) #fn_output #block
36 let res = inner(#(#input_idents),*)#awaitness;
37
38 METRICS
39 .db
40 .postgres
41 .record(#label, start_time.elapsed().as_millis() as f64);
42 res
43 };
44 result
45 }
46 };
47
48 gen.into()
49}
50
51#[proc_macro_error]
52#[proc_macro_attribute]
53pub fn metrics(_attrs: TokenStream, input: TokenStream) -> TokenStream {
54 process_with_prometheus_metrics(input)
55}