3 releases

0.1.5 Aug 5, 2023
0.1.4 Aug 5, 2023
0.1.3 Aug 4, 2023

#994 in Algorithms

MIT license

44KB
752 lines

promerge

Promerge provides minimalistic and easy to use API to parse and manipulate Prometheus metrics. A simple usecase could be collecting metrics from several servers and combining and exposing them as single metrics endpoint, adding namespace and custom (Key,Value) pairs to each Prometheus exposition line.

Example:

use promerge::promerge::Context;

fn main() {
    // example from: https://prometheus.io/docs/instrumenting/exposition_formats/
    let metrics = r#"# HELP http_requests_total The total number of HTTP requests.
# TYPE http_requests_total counter
http_requests_total{method="post",code="200"} 1027 1395066363000
http_requests_total{method="post",code="400"}    3 1395066363000

# Escaping in label values:
msdos_file_access_time_seconds{path="C:\\DIR\\FILE.TXT",error="Cannot find file:\n\"FILE.TXT\""} 1.458255915e9

# Minimalistic line:
metric_without_timestamp_and_labels 12.47

# A weird metric from before the epoch:
something_weird{problem="division by zero"} +Inf -3982045

# A histogram, which has a pretty complex representation in the text format:
# HELP http_request_duration_seconds A histogram of the request duration.
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.05"} 24054
http_request_duration_seconds_bucket{le="0.1"} 33444
http_request_duration_seconds_bucket{le="0.2"} 100392
http_request_duration_seconds_bucket{le="0.5"} 129389
http_request_duration_seconds_bucket{le="1"} 133988
http_request_duration_seconds_bucket{le="+Inf"} 144320
http_request_duration_seconds_sum 53423
http_request_duration_seconds_count 144320

# Finally a summary, which has a complex representation, too:
# HELP rpc_duration_seconds A summary of the RPC duration in seconds.
# TYPE rpc_duration_seconds summary
rpc_duration_seconds{quantile="0.01"} 3102
rpc_duration_seconds{quantile="0.05"} 3272
rpc_duration_seconds{quantile="0.5"} 4773
rpc_duration_seconds{quantile="0.9"} 9001
rpc_duration_seconds{quantile="0.99"} 76656
rpc_duration_seconds_sum 1.7560473e+07
rpc_duration_seconds_count 2693"#;

    // add new (k,v) pairs into Prometheus metric exposition
    let pairs = [("custom_key".into(), "custom_value".into())];
    // add a prefix to metrics
    let mut metrics = Context::with_prefix_and_pairs(&metrics, "some_prefix_", &pairs);
	
    // parse and evaluate
    {
	let ctx = &mut metrics;
	match ctx.run() {
	    Ok(output) => {
		println!("first run: {}", output);
	    },
	    Err(err) => {
		eprintln!("{}", err);
	    }
	};
    }
	
    // append new metrics with difference prefix
    {
        let block = r#"# New minimalistic line:
new_metric_without_timestamp_and_labels 24.81"#;	
	let ctx = &mut metrics;
	match ctx.combine_with_prefix(block, "second_prefix_") {
	    Ok(output) => {
		println!("second run: {}", output);
	    },
	    Err(err) => {
		eprintln!("{}", err);
	    }
	};
    }

    /* Final Output ->
    
    # HELP some_prefix_http_requests_total The total number of HTTP requests.
    # TYPE some_prefix_http_requests_total counter
    some_prefix_http_requests_total{method="post",code="200",custom_key="custom_value"} 1027 1395066363000
    some_prefix_http_requests_total{method="post",code="400",custom_key="custom_value"} 3 1395066363000

    # Escaping in label values:
    some_prefix_msdos_file_access_time_seconds{path="C:\\DIR\\FILE.TXT",error="Cannot find file:\n\"FILE.TXT\"",custom_key="custom_value"} 1.458255915e9

    # Minimalistic line:
    some_prefix_metric_without_timestamp_and_labels{custom_key="custom_value"} 12.47

    # A weird metric from before the epoch:
    some_prefix_something_weird{problem="division by zero",custom_key="custom_value"} +Inf -3982045

    # A histogram, which has a pretty complex representation in the text format:
    # HELP some_prefix_http_request_duration_seconds A histogram of the request duration.
    # TYPE some_prefix_http_request_duration_seconds histogram
    some_prefix_http_request_duration_seconds_bucket{le="0.05",custom_key="custom_value"} 24054
    some_prefix_http_request_duration_seconds_bucket{le="0.1",custom_key="custom_value"} 33444
    some_prefix_http_request_duration_seconds_bucket{le="0.2",custom_key="custom_value"} 100392
    some_prefix_http_request_duration_seconds_bucket{le="0.5",custom_key="custom_value"} 129389
    some_prefix_http_request_duration_seconds_bucket{le="1",custom_key="custom_value"} 133988
    some_prefix_http_request_duration_seconds_bucket{le="+Inf",custom_key="custom_value"} 144320
    some_prefix_http_request_duration_seconds_sum 53423
    some_prefix_http_request_duration_seconds_count 144320

    # Finally a summary, which has a complex representation, too:
    # HELP some_prefix_rpc_duration_seconds A summary of the RPC duration in seconds.
    # TYPE some_prefix_rpc_duration_seconds summary
    some_prefix_rpc_duration_seconds{quantile="0.01",custom_key="custom_value"} 3102
    some_prefix_rpc_duration_seconds{quantile="0.05",custom_key="custom_value"} 3272
    some_prefix_rpc_duration_seconds{quantile="0.5",custom_key="custom_value"} 4773
    some_prefix_rpc_duration_seconds{quantile="0.9",custom_key="custom_value"} 9001
    some_prefix_rpc_duration_seconds{quantile="0.99",custom_key="custom_value"} 76656
    some_prefix_rpc_duration_seconds_sum 1.7560473e+07
    some_prefix_rpc_duration_seconds_count 2693

    # New minimalistic line:
    second_prefix_new_metric_without_timestamp_and_labels 24.81
    
     */
}

Dependencies

~2.5–3.5MB
~73K SLoC