Skip to content

Enhancement proposals for rust-prometheus #392

Open
@mxinden

Description

@mxinden

During the last 10 month, helping to maintain this library, I had several ideas how to enhance rust-prometheus. I prototyped my ideas, starting from scratch end of last year, somewhat accidentally ending up with a full-featured client library - rust-open-metrics-client. Below I want to describe the differences between rust-prometheus and rust-open-metrics-client.

I am posting this here first off to collect feedback. In case people like some of my ideas, we could port them to rust-prometheus.

  • Strongly typed label sets: While rust-prometheus treats both label keys and values as strings, rust-open-metrics-client allows any Rust type to act as a label set. More concretely with rust-open-metrics-client one can use both (String, String) as a label set, as well as a defined custom type. Example:

    #[derive(Clone, Hash, PartialEq, Eq, Encode)]
    struct Labels {
      method: Method,
      path: String,
    };
    
    #[derive(Clone, Hash, PartialEq, Eq, Encode)]
    enum Method {
      GET,
      PUT,
    };
    
    let http_requests = Family::<Labels, Counter<AtomicU64>>::default();
    
    http_requests.get_or_create(
        &Labels { method: Method::GET, path: "/metrics".to_string() }
    ).inc();

    Using a custom type instead of some string type gives the user all of the safety benefits the Rust type system provides. In addition, using simple enums instead of a string allows various optimizations, as the former can potentially be stack allocated.

  • Reduced allocations in hot-path: There are two performance critical paths when instrumenting applications, metric tracking and metric encoding. I think rust-prometheus can improve in the latter case. I.e. the Collector trait forces string allocations of the metric type, help,name, ... on each collect call. rust-open-metrics-client instead uses the visitor pattern, requiring no allocations when collecting, instead, directly writing the encoded metrics out to the provided I/O resource. This leads to a large performance improvement of ~40% (see benchmarks).

  • Smaller scoped metric metadata: In rust-prometheus metric metadata (name, help, type) is both carried by the metric reference passed to business logic as well as the metric reference owned by the metric registry. rust-open-meitrcs-client tracks metric metadata in the registry only. The metric reference owned by the business logic e.g. compiles down to a plain AtomicXXX for a counter.

  • Access to underlying atomics: rust-open-metrics-client allows advanced users to access the underlying atomic. Useful e.g. for Tracking peak/max value #358.

  • Open Metrics Compliance: rust-open-metrics-client is compatible with the Open Metrics specification. Given that the Open Metrics format is backwardds-compatible with the Prometheus format, rust-open-metrics-client is compatible with both the Open Metrics format as well as the Prometheus format.

You can find the code of rust-open-metrics-client here. In addition I hope I did a reasonable job documenting the crate.

Curious what you think and whether you would like to see any of the features of rust-open-metrics-client to be ported to rust-prometheus.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions