* Extend Counters, Summaries and Histograms with creation timestamp
Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com>
* Backport created timestamp to existing tests
Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com>
* Last touches (readability and consistency)
Changes:
* Comments for "now" are more explicit and not inlined.
* populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code.
* Test consistency and simplicity - the fewer variables the better.
* Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently.
* We don't need TestCounterXXXTimestamp - we test CT in many other places already.
* Added more involved test for counter vectors with created timestamp.
* Refactored normalization for simplicity.
* Make histogram, summaries now consistent.
* Simplified histograms CT flow and implemented proper CT on reset.
TODO for next PRs:
* NewConstSummary and NewConstHistogram - ability to specify CTs there.
Signed-off-by: bwplotka <bwplotka@gmail.com>
* Update prometheus/counter_test.go
Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com>
Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
---------
Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com>
Signed-off-by: bwplotka <bwplotka@gmail.com>
Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
Co-authored-by: bwplotka <bwplotka@gmail.com>
* Introduce MetricVecOpts and add constraints to VariableLabels
MetricVecOpts exposes options specific to MetricVec initialisation. The
first option exposed by MetricVecOpts are constraints on VariableLabels,
allowing restrictions on the possible values a label can take, to
prevent cardinality explosion when the label value comes from a
non-trusted source (as a user input or HTTP header).
Signed-off-by: Quentin Devos <4972091+Okhoshi@users.noreply.github.com>
* Add tests
Signed-off-by: Quentin Devos <4972091+Okhoshi@users.noreply.github.com>
Signed-off-by: Quentin Devos <4972091+Okhoshi@users.noreply.github.com>
* Add new Go 1.19 metrics
Signed-off-by: Kemal Akkoyun <kakkoyun@gmail.com>
* Format files with the latest formatter
Signed-off-by: Kemal Akkoyun <kakkoyun@gmail.com>
Signed-off-by: Kemal Akkoyun <kakkoyun@gmail.com>
MetricVec was already exported in early versions of this library, but
nobody really used it to implement vectors of custom Metric
implementations. Now #796 has shown up with a fairly special use case
for which I'd prefer a custom implementation of a special
"auto-sampling histogram" outside of this library. Therefore, I'd like
to reinstate support for creating vectors of custom Metric
implementations.
I played around for quite some while with the option of a separate
package providing the tools one would need to create vectors of custom
Metric implementations. However, with the current structure of the
prometheus/client_golang/prometheus package, this leads to a lot of
complications with circular dependencies. (The new package would need
the primitives from the prometheus package, while the existing metric
vectors like GaugeVec need to import the new vector package to not
duplicate the implementation. Separating vector types from the main
prometheus package is out of the question at this point because that
would be a breaking change.)
Signed-off-by: beorn7 <beorn@grafana.com>
Original discussion see
https://github.com/prometheus/client_golang/pull/362 .
Assuming that the most frequently used method of a `Gauge` is `Set`
and the most frequently used method of a `Conuter` is `Inc`, this
separates the implementation of both metric types. `Inc` and integral
`Add` of a counter is now handled in a separate `uint64`. This would
create a race in `Set`, but luckily, there is no `Set` anymore in a
counter.
All attempts to solve above race (to use the same idea for a `Gauge`)
slow down `Set`, So we just stick with the old implementation
(formerly `value`) for `Gauge`.
The idea behind it is described in detail in
https://github.com/prometheus/client_golang/issues/320 .
This commit also updates the example given in
promhttp/instrument_server_test.go , which nicely illustrates the
benefit of this change.
So far, currying could be emulated by creating different metric vec's
with different values in their ConstLabels. This was quite difficult
to grasp - which is essentially what was done in the example mentioned
above. Now that this use case can be solved without ConstLabels, we
can safely declare ConstLabels as rarely used. (Perhaps we can
deprecate them entirely one day, but I'll take a raincheck on that
when the changes of v0.10 have materialized.) This commit thus also
updates the ConstLabel doc comments in the various Opts. (It contained
fairly outdated stuff anyway.)
The "panic in case of error" code was so far in metricVec. This pulls
it up into the exported types like CounterVec. This is code
replication, but it avoids an explicit type conversion. Mostly,
however, this is preparation to make the wrapped metricVec an
interface (required for curried vec's).
This is in preparation for "curried" metric vecs, as discussed.
And it's a good thing anyway. The exported MetricVec was from a time
when I thought people would define own Metric types and then create
Vecs of it. That has never happened.
- Deprecate Untyped for direct instrumentation.
- Add a SetToCurrentTime method to Gauge
Note that adding the SetToCurrentTime method is not really following
Go's principle of lean interfaces. However, the Gauge interface is
already quite fat. (The only methods really required are Set and
Add. Everything else could be expressed in terms of those two.) So we
have already quite a few "convenience" methods traditionally, so I
think we should stay consistent here.
The alternatives would be:
- Not support SetToCurrentTime at all (it's only a SHOULD in the
guidelines).
- A top level function `SetToCurrentTime(Gauge)`.
- Just a helper `CurrentTime()` that returns the curent unix time in
seconds as a float (which is pretty verbose using the standard
library, see code in this commit). This would allow
`myGauge.Set(CurrentTime)`.
Weighing all circumstances, I believe the way in this commit is the
least evil. Issue #223 could be used to rework interfaces more
fundamentally in a breaking change if feasible.
This rewrite had may backs and forths. In my git repository, it
consists of 35 commits which I cannot group or merge into reasonable
review buckets. Gerrit breaks fundamental git semantics, so I have to
squash the 35 commits into one for the review.
I'll push this not with refs/for/master, but with refs/for/next so
that we can transition after submission in a controlled fashion.
For the review, I recommend to start with looking at godoc and in
particular the many examples. After that, continue with a line-by-line
detailed review. (The big picture is hopefully as expected after
wrapping up the discussion earlier.)
Change-Id: Ib38cc46493a5139ca29d84020650929d94cac850
The LabelsToSignature function is now used outside of the prometheus
package, too. Leaving it in the prometheuos package is misleading
design and will lead to circulat import chains soon.
Change-Id: If1ca442d4023b33b138cf79fee68e82ff2a355be
These are all simple changes we should have caught a long time ago:
1. The hashing mechanism for fingerprint label sets should have not
allocated new objects for the actual hashing---at least not
egregiously. This simplifies the hash writing by just byte-
dumping the string stream into the hasher.
2. The hashing mechanism within the scope of a metric does not care
about the value of the label keys themselves but only of the label
values. The keys can be dropped from the calculation.
3. The locking mechanism for the metrics should not block on hash
computation but rather solely on the actual mutation or critical
section reads.
4. For scalar metrics (i.e., ones with niladic label signatures), we
should rely on a preallocated map versus requesting a new one
ad hoc.
This is tested with Go 1.1, so the results may yield other values
for us elsewhere:
BEFORE
BenchmarkLabelValuesToSignatureScalar 500000000 3.97 ns/op 0 B/op 0 allocs/op
BenchmarkLabelValuesToSignatureSingle 5000000 714 ns/op 74 B/op 4 allocs/op
BenchmarkLabelValuesToSignatureDouble 1000000 1153 ns/op 107 B/op 5 allocs/op
BenchmarkLabelValuesToSignatureTriple 1000000 1588 ns/op 138 B/op 6 allocs/op
BenchmarkLabelToSignatureScalar 500000000 3.91 ns/op 0 B/op 0 allocs/op
BenchmarkLabelToSignatureSingle 2000000 874 ns/op 92 B/op 5 allocs/op
BenchmarkLabelToSignatureDouble 1000000 1528 ns/op 139 B/op 7 allocs/op
BenchmarkLabelToSignatureTriple 1000000 2172 ns/op 186 B/op 9 allocs/op
AFTER
BenchmarkLabelValuesToSignatureScalar 500000000 4.36 ns/op 0 B/op 0 allocs/op
BenchmarkLabelValuesToSignatureSingle 5000000 378 ns/op 89 B/op 4 allocs/op
BenchmarkLabelValuesToSignatureDouble 5000000 574 ns/op 142 B/op 5 allocs/op
BenchmarkLabelValuesToSignatureTriple 5000000 758 ns/op 186 B/op 6 allocs/op
BenchmarkLabelToSignatureScalar 500000000 4.06 ns/op 0 B/op 0 allocs/op
BenchmarkLabelToSignatureSingle 5000000 472 ns/op 106 B/op 5 allocs/op
BenchmarkLabelToSignatureDouble 2000000 746 ns/op 174 B/op 7 allocs/op
BenchmarkLabelToSignatureTriple 1000000 1061 ns/op 235 B/op 9 allocs/op
In effect, a single metric mutation operation's lookup overhead will
move from Before::iBenchmarkLabelToSignature to
After::BenchmarkLabelValuesToSignature. This MINIMALLY reduces
1/2 the overhead. I would be hesitant in reading the memory
allocation statistics, for this was run with the GC still on and
thusly inaccurate per Go benchmarking documentation.
Before::BenchmarkLabelValuesToSignature never existed, so it is not
of any intrinsic value in itself. That said, the cases that still
rely on LabelToSignature experience consistently a 1/2 drop in time.
Change-Id: Ifc9e69f718af65a59f5be8117473518233258159
* Drop `AsMarshallable()` from the Metric interface. Use
`json.Marshaler` and `MarshalJSON()`, and leverage JSON struct tags
where possible.
* Add `MarshalJSON()` to Registry and remove `dumpToWriter`, which
makes the registry handler much simpler.
In addition to simplifying some of the marshalling behavior, this also
has the nice side effect of cutting down the number of
`map[string]interface{}` instances.