Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: virtual metrics #64

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

Conversation

aspiwack
Copy link

This is a draft for an idea to generalise the metrics API, before I commit to making it clean and documenting it and such, I would like the maintainers' opinion on the general principle.

The idea is to provide what I've been calling “virtual metrics” (for lack of a better name, though I think it's not bad a name). The idea is to be able to create metrics which are not backed by their usual IORef but can be sampled from a preexisting store (or store-like thing). Existing examples of such metrics would be the GHC runtime metrics, or the proc metrics, though I didn't change their implementation (I don't think I should plan to either). A situation that I've had and motivated this PR was that I wanted to return a measure that was computed by a database query.

With the current API, I have basically two options: either I define the metric myself using the concrete Metric type, which is a tad low-level and error prone; or I make a standard metric, and some background thread periodically forwards my metric to the IORef, with all the baggage that it entails.

With the virtual metric API (this draft only implement gauge, since it's the one that makes the more sense, but other metrics may very well benefit from the same treatment) we make a metric simply by providing the IO action that will measure the value when the metric is sampled.


A key ingredient which makes this idea actually useful is that it is easy to define the regular metrics as virtual metrics. To that effect I extended the Metric API a little with

  • A function metricIO :: IO (Metric a) -> Metric a (I don't like the name though)
  • A Functor instance, which lets me, for instance, replace VirtualGauge by the appropriage Gauge where creating a new standard gauge.
  • An Applicative instance, which I don't actually need in this particular PR, but we might as well: it lets us group metrics under a single Metric Foo, like is done in the GHC runtime metrics and the proc metrics. It was very cheap to write, and since I was making the Metric API more composable, I thought I might as well. It's part of making it easier to define ones own custom metric packages on top of prometheus-client.

Does this look like a reasonable plan? Any recommendations? requests?

@ocharles
Copy link
Collaborator

ocharles commented Nov 23, 2021

I haven't studied your PR in detail, but I am sympathetic to

define the metric myself using the concrete Metric type, which is a tad low-level and error prone

Using Metric is really fiddly, and requires users to duplicate code from prometheus-client.

Does this look like a reasonable plan? Any recommendations? requests?

It might be a good idea to explore what I think is alternative solution to the problem, which is to make Metric itself more ergonomic. Right now, it talks about SampleGroups, which ultimately is a Sample Text LabelPairs ByteString. Maybe there's a better API here that doesn't require users to manually construct ByteStrings, but instead work at a higher-level.

@aspiwack
Copy link
Author

I must confess that I don't see precisely what you have in mind. I confess to not having given much thought to what my ideal Prometheus library would look like. I would be quite happy to have this conversation though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants