- Statsd allows users to provide a metric with the same name but
differing types (counter, gauge, timer)
- The exporter allows this by letting users specify a
"match_metric_type" in the mapping config
- However the mapper cache does not look at the metric type so it would
return a MetricMapperCacheResult for the type of the first metric with
that name that the exporter saw
- Add MetricType to the signature for the cache and format the metric
name with the type to provide unique keys for a metric with the same
name but differing type
Signed-off-by: Andy Paine <andy.paine@digital.cabinet-office.gov.uk>
At high traffic levels, the locking around sending on channels can cause
a large amount of blocking and CPU usage. These adds an event queue
mechanism so that events are queued for short period of time, and
flushed in batches to the main exporter goroutine periodically.
The default is is to flush every 1000 events, or every 200ms, whichever
happens first.
Signed-off-by: Clayton O'Neill <claytono@github.com>
This was attempting to clean up any vectors that no longer have metrics
associated with them. Unfortunately this isn't really possible because
the prometheus client registry allows the second registration of the
same metric, and then throws an error when gathering the metrics.
Another options would be to unregister the metric with the client
library, but that's not implemented for unchecked collectors.
Unfortunately this means that if we have a lot of metrics with differing
label sets appearing and disappearing, that we'll leak some amount of
memory for vectors that are never used again, but this is the way the
old metric tracking code worked also.
Signed-off-by: Clayton O'Neill <claytono@github.com>
This adds two tests.
The first test is to validate that two successive counter events will
increment a counter. This is more about ensuring we can look up the
same metric twice in a row than checking increment functionality.
The second test verifies that the hashLabels function returns different
results when labels are changed.
Signed-off-by: Clayton O'Neill <claytono@github.com>
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>
I never finished releasing 0.10.0 because the build was broken, but I
don't want to re-use that tag.
Signed-off-by: Matthias Rampke <mr@soundcloud.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>