tometrics 0.1.0

Simple metrics abstraction
Documentation
    use reqwest::Client;
    use std::collections::HashMap;


    //
    // A wrapper for easily pushing metrics to a backend.
    //
    // Note: current implementation is not mean for high frequency pushing (no buffering is used)
    // @param bucket string The bucket/table/database we are pushing data into.
    // @param static_metric_name string If we only are pushing one type of value, we can optionally just set the name once
    // @param static_metric_metadata map If there are metadata that do not change for all the data we are pushing, we can set those once
    //
    pub struct InfluxDBClient {
        backend_url: String,
        bucket: String,
        req_client: Client,
    }

    impl InfluxDBClient {
        // Note: You must call init manually to setup the db.
        pub fn new(backend_url: String, bucket: String) -> Self {
            InfluxDBClient {
                backend_url: backend_url,
                bucket: bucket,
                req_client: Client::new(),
            }
        }

        pub async fn init(&self) -> bool {
            // Create the db if it does not exist
            // curl - i - XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE mydb"
            let response = self
                .req_client
                .post(self.backend_url.clone() + "/query")
                .body("q=CREATE DATABASE ".to_string() + &self.bucket)
                .send()
                .await;

            // TODO make these error propagate
            response.is_ok()
        }

            // @param the name of this metric
            // @param timestamp_ns int The timestamp associated with this metric. in nanoseconds
            // @param data Dict of key value pairs that holds the data/fields for our sample
            // @param metadata Dict of key value pairs that holds the metadata describing our sample
        pub async fn send(
            &self,
            name: String,
            timestamp_ns: usize,
            data: HashMap<String, serde_json::Value>,
            metadata: HashMap<String, serde_json::Value>,
        ) -> bool {
            // curl - i - XPOST 'http://localhost:8086/write?db=mydb' --data - binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000'"""

            let mut formatted_metadata = String::from("");
            metadata.iter().for_each(|(k, v)| {
                // since we're abusing the json lib for its nice variant-likeness, it auto wraps with quotes, we dont want that for strings, so work around it.
                let value_as_string: String = match v.is_string() {
                    true => v.as_str().unwrap().to_string(),
                    false => v.to_string(),
                };
                formatted_metadata = formatted_metadata.clone() // TODO cleaner append?
                + ","
                + k 
                + "=" 
                + &value_as_string
            }); 
            
            let mut formatted_data = String::from("");
            data.iter().for_each(|(k, v)| {
                // since we're abusing the json lib for its nice variant-likeness, it auto wraps with quotes, we dont want that for strings, so work around it.
                let value_as_string: String = match v.is_string() {
                    true => v.as_str().unwrap().to_string(),
                    false => v.to_string(),
                };
                formatted_data = formatted_data.clone() 
                + (if formatted_data.is_empty() {" "} else {","}) 
                + k 
                + "=" 
                + &value_as_string
            });

            let response = self
                .req_client
                .post(self.backend_url.clone() + "/write?db=" + &self.bucket)
                .body(
                    name
                    + &formatted_metadata
                        + " "
                        + &formatted_data
                        + " "
                        + &timestamp_ns.to_string(),
                )
                .send()
                .await;

            // TODO make these error propagate
            response.is_ok()
        }
    }