On 30.03.21 17:42, Aaron Gable wrote:
> 
> Suppose I have a `CounterVec` that I call `requestsCounter`, with labels 
> `method` (whose values are only `GET` and `POST`) and `success` (whose 
> values are only `true` and `false`). Maybe I have a set of unittests which 
> implement a purposefully-broken handler, and I'd like to assert that we 
> incremented the counter for unsuccessful requests the appropriate number of 
> times, _regardless_ of whether those requests were GETs or POSTs.

In very general, I'd break this down, following the philosophy of
letting a unit test just exercise the code it is supposed to test.

With your current approach, you are almost doing and end-to-end test
by invoking the whole `Collect` and `Write` machinery. I guess that's
fine for true end-to-end tests. (See
https://pkg.go.dev/github.com/prometheus/client_golang@v1.10.0/prometheus/testutil
for utilities to write those tests.) In your case, as you said, you
want to know if "we incremented the counter for unsuccessful requests
the appropriate number of times". Ideally, you inject a CounterVec
mock that doesn't really do anything with the metrics, but just
records that the right counter child was retrieved and the appropriate
increments were performed on it. Go doesn't lend itself to this kind
of monkey-patching, and the client_golang library misses good support
for this kind of approach right now, which has to do with certain
design problems that cannot be fixed without a breaking change, see
https://github.com/prometheus/client_golang/issues/230 . But it's
still possible. In your case, your code probably would have to act on
an interface, which is designed in a way that both `CounterVec` as
well as your injected mock are implementing it.

> Unfortunately this fails, because the curried `MetricVec` still sends *all* 
> metrics to the `.Collect()` channel, even those that would be excluded by 
> the curried labels.

Yeah, that's another design problem of the library. The excuse is that
currying was introduced relatively late in the design process. In an
ideal world (and in v2 of the library), the curried CounterVec
wouldn't even have a `Collect` method.

You could also follow the "inject a mock" approach half-way and
inject a CounterVec that only contains the relevant metrics instead of
using the full CounterVec with all the other metrics plus currying.

> The only real solution that I see here is to perform the currying ourselves 
> -- rather than passing a curried `MetricVec` into the `AssertMetricEquals` 
> function, pass a set of `Labels` into it and do the filtering ourselves 
> based on the contents of `iom.Label`. This would be functionally the same 
> as the "very hacky and weird" workaround in #834.

Yes, in case you want to stick with the "let's collect the metrics and
inspect the protobuf" approach, that's probably the most
straightforward way to go.

-- 
Björn Rabenstein
[PGP-ID] 0x851C3DA17D748D03
[email] bjo...@rabenste.in

-- 
You received this message because you are subscribed to the Google Groups 
"Prometheus Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to prometheus-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/prometheus-developers/20210331203601.GU2627%40jahnn.

Reply via email to