promhttp (Go): Per-request dynamic label values

199 views
Skip to first unread message

João

unread,
Jul 17, 2021, 10:55:01 AM7/17/21
to Prometheus Users
Hi,

I've been using github.com/prometheus/client_golang/prometheus/promhttp to export API metrics and now I'd like to extend these with per-request dynamic label values.

For example, let's imagine that for each incoming HTTP request, I want to add and fill a `user_group` label with value `admin` or `guest` depending on a few validations that happen at run time while processing the request. Now let's imagine the API has received 2 requests so far, one from an admin and another from a guest.

Instead of something like this:

myapp_http_requests_total{code="200",method="get"} 2

I want this:

myapp_http_requests_total{code="200",method="get",user_group="admin"} 1
myapp_http_requests_total{code="200",method="get",user_group="guest"} 1

Right now I don't see any way of achieving this. I know we can add const labels, but I don't see a way to inject and fill labels depending on the HTTP request context. The only option I see is cloning the promhttp package code and modify it to add these new labels and fill them at run time by reading their value from the HTTP request context (such as here).

I wonder if anyone is aware of a better solution?

Bjoern Rabenstein

unread,
Jul 20, 2021, 7:15:51 AM7/20/21
to João, Prometheus Users
On 17.07.21 07:55, João wrote:
>
> I've been using github.com/prometheus/client_golang/prometheus/promhttp
> <https://pkg.go.dev/github.com/prometheus/client_golang/prometheus/promhttp> to
> export API metrics and now I'd like to extend these with per-request
> dynamic label values.
>
> For example, let's imagine that for each incoming HTTP request, I want to
> add and fill a `user_group` label with value `admin` or `guest` depending
> on a few validations that happen at run time while processing the request.
> Now let's imagine the API has received 2 requests so far, one from an admin
> and another from a guest.
>
> Instead of something like this:
>
> myapp_http_requests_total{code="200",method="get"} 2
>
> I want this:
>
> myapp_http_requests_total{code="200",method="get",user_group="admin"} 1
> myapp_http_requests_total{code="200",method="get",user_group="guest"} 1
>
> Right now I don't see any way of achieving this. I know we can add const
> labels, but I don't see a way to inject and fill labels depending on the
> HTTP request context. The only option I see is cloning the promhttp package
> code and modify it to add these new labels and fill them at run time by
> reading their value from the HTTP request context (such as here
> <https://github.com/prometheus/client_golang/blob/8184d76b3b0bd3b01ed903690431ccb6826bf3e0/prometheus/promhttp/instrument_server.go#L102>
> ).
>
> I wonder if anyone is aware of a better solution?

The middlewares in
github.com/prometheus/client_golang/prometheus/promhttp are really
just quite thin convenience wrappers around the instrumentation
primitives in github.com/prometheus/client_golang/prometheus. They are
meant to make the common case very easy. If they had many nobs to
tweak for special cases, it would defeat their purpose of
convenience. If you want to do anything special, just use the
instrumentation primitives directly. It's quite easy, and loads of
tutorials on the internet. (Shameless plug: Watch
https://www.youtube.com/watch?v=HkEZ1LJ7kzQ , instrumenting an HTTP
handler is explained beginning at 10m15s .)


--
Björn Rabenstein
[PGP-ID] 0x851C3DA17D748D03
[email] bjo...@rabenste.in
Reply all
Reply to author
Forward
0 new messages