This reworks/rewrites the way that metric registration and tracking is
handled across all of statsd_exporter. The goal here is to reduce
memory and cpu usage, but also to reduce complexity by unifying metric
registration with the ttl tracking for expiration.
Some high level notes:
* Previously metric names and labels were being hashed three times for
every event accepted: in the container code, the save label set code and
again in the prometheus client libraries. This unifies the first two
and caches the results of `GetMetricWith` to avoid the third.
* This optimizes the label hashing to reduce cpu overhead and memory
allocations. The label hashing code previously showed up high on all
profiling done for both CPU and memory allocations
Using the BenchmarkExporterListener benchmark, the improvement looks
like this.
Before:
cpu: 11,341,797 ns/op
memory allocated: 1,731,119 B/op
memory allocations: 58,028 allocs/op
After:
cpu: 7,084,651 ns/op
memory allocated: 906,556 B/op
memory allocations: 42,026 allocs/op
Signed-off-by: Clayton O'Neill <claytono@github.com>
Previously we were sorting labels in every container to build a map key,
but also when generating the hash key by calling the `LabelsToSignature`
method. This moves the sorting to be done early in the event processing
then passes the sorted label array around.
Signed-off-by: Clayton O'Neill <claytono@github.com>
This converts the byte buffer to a string by casting and parses the
string by looping over it instead of calling Split.
This usage of unsafe is taken from the strings.Builder package here:
cb5c82bc3d/src/strings/builder.go (L47)
Signed-off-by: Clayton O'Neill <claytono@github.com>
This converts escapeMetricName to use strings.Builder instead of
allocating a byte array, filling it and then converting it to a string.
This also optimizes for the case where the metricName is already valid,
and in that case, it just returns the original string.
This reduces memory allocations from 2 per call to 1 per call in the
case when the string does need to be escaped, and reduces it to zero
memory allocations when the string is already valid.
Signed-off-by: Clayton O'Neill <claytono@github.com>
While it doesn't report it as a metric, when collecting, the registry
considers the base metric name to below to the histogram that's
registered. This means that we need to prevent other metrics from
registering anything under this name, in addition to checking for the
bucket, sum and count suffixes.
Signed-off-by: Clayton O'Neill <claytono@github.com>
This adds sanity checking before registering a metric to ensure that the
metric isn't already registered under an existing name. This prevents
the exporter from getting into a state where it has accepted and
registered conflicting metrics, and then cannot report the metrics it
has collected.
Signed-off-by: Clayton O'Neill <claytono@github.com>
This adds the ability to accept Datadog's distribution type and treat it
like a histogram/summary.
Signed-off-by: Clayton O'Neill <claytono@github.com>
This improves performance per call in the a-z case from around 5533
ns/op to 3169ns/op. It also drops allocations per call from 57 to 31
in the a-z case.
Signed-off-by: Clayton O'Neill <claytono@github.com>
- use MetricVec family instead of Metric
- dynamic label values instead of ConstLabels
- use dto.Metric to gain histrogram value in exporter_test
- remove hash calculations
Signed-off-by: Ivan Mikheykin <ivan.mikheykin@flant.com>
It's idiomatic in go to keep code indentation due to nested loops to a
minimum. Decoupling the events handling function into its own function
makes it easier to read the code and test the behavior in isolation of
the channel handling. It's now also easily possible to process events
in parallel without having to touch actual business code.
Signed-off-by: Tobias Schmidt <tobidt@gmail.com>
* Quantile values for a Summary are now configurable.
* The default quantiles (DefObjectives) in the prometheus Go client library is
deprecated. This commit removes the reliance on it.
Signed-off-by: Harry Bagdi <harrybagdi@gmail.com>