Here is an example profile with samples using sampling rate, where you can see it takes more than 21% of total memory used:

dogClient, err := statsd.New(
opts.statsdServer,
statsd.WithoutTelemetry(),
statsd.WithNamespace("flood_statsd"),
statsd.WithTags([]string{"pod_name:" + os.Getenv("POD_NAME")}),
statsd.WithoutClientSideAggregation(),
)
if err != nil {
level.Error(logger).Log("msg", "Error creating dogClient client", "err", err)
os.Exit(1)
}
samplesSent := 0
start := time.Now()
for {
randomInt := rand.Int63n(opts.cardinalityLimit)
err := dogClient.Count("sample_counter", 1, []string{"mybad_label:co_" + strconv.FormatInt(randomInt, 10)}, 0.01)
if err != nil {
level.Error(logger).Log("msg", "Error sending metric", "err", err)
}
_ = dogClient.Distribution("synthetic", float64(randomInt), []string{"mybad_label:co" + strconv.FormatInt(randomInt, 10)}, 0.001)
_ = dogClient.Timing(
"some_timing",
time.Duration(rand.Intn(3000))*time.Millisecond,
[]string{"cardinality:" + strconv.FormatInt(randomInt, 10)},
0.01,
)
_ = dogClient.Gauge("some_gauge", float64(randomInt), []string{"mybad_label:co" + strconv.FormatInt(randomInt, 10)}, 0.01)
_ = dogClient.Distribution("heavily_sampled_distribution", float64(randomInt), []string{"mybad_label:co" + strconv.FormatInt(randomInt, 10)}, 0.001)
// control the rate of the synthetic metrics
samplesSent += 4
if samplesSent >= int(opts.samplesPerSec) {
elapsed := time.Since(start)
if elapsed < time.Second {
level.Info(logger).Log("msg", "Sleeping for", "duration", time.Second-elapsed)
time.Sleep(time.Second - elapsed)
}
level.Info(logger).Log("msg", "Sending", "samples", samplesSent, "elapsed", elapsed)
samplesSent = 0
start = time.Now()
}
}
Description
The current implementation of the
LineToEventsmethod inpkg/line/line.goreturns multiple events, which results in a lot of allocations in the statsd-exporter. We propose changing this method to return a single event instead.On the same refactoring step, we should introduce a "exploder" or "sampling" layer (or helper method on the event) which will keep the same behavior as we have now.
This is a breaking change on purpose which will force client projects using this repository as a library, to adapt to the new method signature.
Here is an example profile with samples using sampling rate, where you can see it takes more than 21% of total memory used:

Goals
CountorSamplingRateto another layer of the exporter.Proposed Solution
LineToEventsmethod to return a single event.CountorSamplingRatein the event structure.CountorSamplingRate.Repro script