victoria_client 0.1.0

Client library for Victoria Metrics DB
Documentation
use std::{collections::HashMap, fmt::Display, sync::{mpsc::Sender, Arc}};

use anyhow::{bail, Error};
use aphomie_db_client::{AphomieDbClient, MetadataTrendDataJoinDb};
use chrono::{DateTime, Utc};

type Result<T> = core::result::Result<T, Error>;

async fn get_trend_data(
    db_client: Arc<AphomieDbClient>,
    sender: Sender<MetadataTrendDataJoinDb>,
) -> Result<()> {
    let take_count = 1_000;
    let mut count: i64 = 0;

    loop {
        let result = db_client
            .get_metadata_join_trend_data_offset_limit(count, take_count)
            .await;

        if let Err(e) = result {
            bail!("{e}");
        }

        let trends = result.unwrap();
        let read: i64 = trends.len().try_into().unwrap();
        count += read;

        for t in trends {
            if let Err(e) = sender.send(t) {
                bail!("{e}");
            }
        }

        if read == 0 {
            break;
        }
    }

    Ok(())
}

struct PromEntry<T>
where
    T: Display,
{
    name: String,
    labels: HashMap<String, String>,
    value: T,
    stamp: DateTime<Utc>,
}

impl TryFrom<MetadataTrendDataJoinDb> for PromEntry<f64>
{
    type Error = anyhow::Error;

    fn try_from(value: MetadataTrendDataJoinDb) -> std::result::Result<Self, Self::Error> {
        if value.value.is_none() {
            bail!("value was null");
        }

        let mut s: Vec<&str> = value.source.split('/').collect();
        let name = s.pop().unwrap().to_string();
        let location = s.join("/");
        let labels = HashMap::from([("location".to_string(), location)]);
        let stamp = value.timestamp;
        let value = value.value.unwrap();

        Ok(PromEntry {
            name,
            labels,
            stamp,
            value
        })
    }

}

impl<T> PromEntry<T>
where
    T: Display,
{
    pub fn to_query(&self) -> String {
        //my_metric{label1="value1",label2="value2"} 123.45 20202000100

        let parsed_labels: Vec<String> = self
            .labels
            .iter()
            .map(|(k, v)| format!("{}=\"{}\"", k, v))
            .collect();
        let labels_string = parsed_labels.join(",");
        let name = self.name.clone();
        let value = self.value.to_string();
        // They use ms since epoch, not seconds
        let stamp = (self.stamp.timestamp() * 1000).to_string();

        format!("{name}{{{labels_string}}} {value} {stamp}")
    }
}