extern crate proc_macro; use quote::quote; use proc_macro::TokenStream; use syn::*; use syn::parse::{Parse, ParseStream}; #[derive(Debug)] struct MetricDefinition { vis: Visibility, name: Ident, values: Vec, } impl Parse for MetricDefinition { fn parse(input: ParseStream) -> Result { let vis = input.parse::()?; input.parse::()?; let name = input.parse::()?; let content; braced!(content in input); let values = content .parse_terminated::<_, Token![,]>(Ident::parse)? .into_iter() .collect(); Ok(Self { vis, name, values }) } } #[proc_macro] pub fn make_metrics(input: TokenStream) -> TokenStream { let data = parse_macro_input!(input as MetricDefinition); let vis = &data.vis; let name = &data.name; let values = &data.values; let values_str = data.values.iter().map(|ident| LitStr::new( &ident.to_string(), ident.span(), )); let expanded = quote! { #vis struct #name { #(#values: Counter,)* } impl #name { pub fn new() -> Self { Self { #(#values: COUNTER.with_label_values(&[#values_str]),)* } } } }; TokenStream::from(expanded) }