Custom serde for prometheus

Hello,

I don't want to use prometheus crate(https://crates.io/crates/prometheus) to generate metrics, rather I want custom serde to this job.
I have a structure which contains counters

pub static STATS: Lazy<Arc<Stats>> = Lazy::new(|| Arc::new(Stats::default()));

#[derive(Default, Serialize, Debug)]
pub struct ServiceA{
    authentication_requests: AtomicU64,
}
impl ServiceA {
    pub fn increment_authentication_requests(&self) {
        self.authentication_requests.fetch_add(1, Ordering::SeqCst);
    }
pub struct Stats{
    servicea: ServiceA,
}
impl Stats {
    pub fn increment_servicea_authentication_requests() {
        GLOBAL_STATS.servicea.increment_authentication_requests();
    }

fn main() {
    Stats::increment_authentication_requests();
    Stats::increment_authentication_requests();

    let str = GlobalStatsPrometheus::metrics();
    println!("{}", str);
}

///////////Expected output//////////////
# cargo run
# HELP authentication_requests Stats Authentication Requests
# TYPE authentication_requests counter
authentication_requests 2

How can I generate same output as generated by prometheus crate(i.e. Output string).

Why not using prometheus crate?

  1. My microservice is getting heavy by already using lot of crates.
  2. Collection metrics is an occasional call.
  3. All statistics are begin available in structure, its just a wrapper to pull and create string, I believe its doable using serde.

Any help!!

You should more clear if you want some answer:

  • should this work for one counter or many?
  • how does serde fit in here?
  • the code you posted contains a bunch of typos.
  • can you explain the expected output?

With what you posted you could do something like this, but I doubt it will be actually useful Rust Playground

1 Like

Hey Thanks for response.

I want to generate this string using serde.

# HELP authentication_requests Stats Authentication Requests
# TYPE authentication_requests counter
authentication_requests 2

# HELP <variable_name> <custom string>
# TYPE <variable_name> <custom_string>
<variable_name> value

ie serde should pick up variable name by itself, create prometheus metrics as above and return. And struct has 100's of variables, serde should do same for all variables and return concatenated string. Is it possible anyhow?

Using macro_rules

pub const HELP: &str = "# HELP ";
pub const TYPE: &str = "# TYPE ";
pub const COUNTER: &str = "counter";
pub const NEWLINE: &str = "\n";

macro_rules! m_text {
    ($type:expr, $name:expr, $desc:expr, $n:expr) => {
        $type.to_string() + $name + $desc + $n
    };
    ($type:expr, $val:expr, $n:expr) => {
        $type.to_string() + $val + $n
    };
}
pub fn test() -> String {
        let ar = "api_request ";
        let cgs = "CommonGlobalStats API Requests";
        out.push_str(&m_text!(HELP, &ar, &cgs, NEWLINE));
        out.push_str(&m_text!(TYPE, &ar, COUNTER, NEWLINE));
        out.push_str(&m_text!(
            &ar,
            &GLOBAL_STATS.servicea.authentication_requests.load(Ordering::SeqCst),
            NEWLINE
        ));
}

But I wanted to do it using serde.

I still don't see how serde would help for this use case. It's a serialization library, but you seem to want to format some values rather than serializing them. Also, it doesn't support those <custom_string>.

I think you're better off writing a declarative macro with macro_rules that takes care to generate the struct and the code for printing it.

If you do want to stick with Serde, you should read through their documentation on implementing a custom data format. However, at the end of the day, you'll still have to use string formatting to actually implement it.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.