Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DogStatsD extended aggregation support #558

Merged
merged 7 commits into from
Aug 18, 2024
40 changes: 33 additions & 7 deletions pkg/line/line.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,18 +217,44 @@ func (p *Parser) LineToEvents(line string, sampleErrors prometheus.CounterVec, s

labels := map[string]string{}
metric := p.parseNameAndTags(elements[0], labels, tagErrors, logger)

var samples []string
if strings.Contains(elements[1], "|#") {
usingDogStatsDTags := strings.Contains(elements[1], "|#")
if usingDogStatsDTags && len(labels) > 0 {
// using DogStatsD tags

// don't allow mixed tagging styles
if len(labels) > 0 {
sampleErrors.WithLabelValues("mixed_tagging_styles").Inc()
level.Debug(logger).Log("msg", "Bad line (multiple tagging styles) from StatsD", "line", line)
return events
sampleErrors.WithLabelValues("mixed_tagging_styles").Inc()
level.Debug(logger).Log("msg", "Bad line (multiple tagging styles) from StatsD", "line", line)
return events
}

var samples []string
lineParts := strings.SplitN(elements[1], "|", 3)
if strings.Contains(lineParts[0], ":") {
// handle DogStatsD extended aggregation
isValidAggType := false
switch lineParts[1] {
Copy link

@m-barthelemy m-barthelemy Aug 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After updating to 0.27.1, this line is triggering a panic: runtime error: index out of range [1] with length 1 for us.

case
"ms", // timer
"h", // histogram
"d": // distribution
isValidAggType = true
}

if isValidAggType {
aggValues := strings.Split(lineParts[0], ":")
aggLines := make([]string, len(aggValues))
_, aggLineSuffix, _ := strings.Cut(elements[1], "|")

for i, aggValue := range aggValues {
aggLines[i] = strings.Join([]string{aggValue, aggLineSuffix}, "|")
}
samples = aggLines
Comment on lines +244 to +251
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll accept this as is, but this amount of string manipulation is making me nervous – both for the potential to mess up a line, and because of the amount of intermediate strings we're leaving for the garbage collector to deal with.

I would prefer if we could delay dealing with the multiple samples in a line until line 280, when we turn the value into a float. There, we could turn the single value float64 into a values []float64, looping over the : separated values to parse them in turn. We should be able to do this without allocating any additional strings. Then, further down on line 331, where we're emitting 1/samplingFactor events, we could also loop over that.

That being said, I've left this PR hanging for too long, so I'll take working over perfect. If anyone runs into actual issues from the current approach, or feels otherwise motivated, maybe this comment can help guide them 😃

} else {
sampleErrors.WithLabelValues("invalid_extended_aggregate_type").Inc()
level.Debug(logger).Log("msg", "Bad line (invalid extended aggregate type) from StatsD", "line", line)
return events
}
} else if usingDogStatsDTags {
// disable multi-metrics
samples = elements[1:]
} else {
Expand Down
Loading