Skip to content

Commit

Permalink
[statsdreceiver] support simple tags
Browse files Browse the repository at this point in the history
dogstatsd supports two types of tags on metrics: simple and
dimensional tags[^1]. the former is just a key, the latter is
a key and a value.

with the assumption that many users of the statsdreceiver are
enabling ingest of dogstatsd metrics, this makes the statsd
parser more optimistic, so it can handle tags w/o a value.

when this happens, we set an attribute that has a zero value.
so far as i know, this is allowed in the opentelemetry spec.
the decision of how to handle attributes w/ zero values is
best left to configuration w/in the pipeline itself, as different
users may have different opinions or approaches that work best
with their systems.

[^1]: https://www.datadoghq.com/blog/the-power-of-tagged-metrics/#whats-a-metric-tag
  • Loading branch information
diurnalist committed Nov 14, 2023
1 parent f524cf3 commit 7d9d814
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
15 changes: 11 additions & 4 deletions receiver/statsdreceiver/internal/protocol/statsd_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,18 @@ func parseMessageToMetric(line string, enableMetricType bool) (statsDMetric, err

for _, tagSet := range tagSets {
tagParts := strings.SplitN(tagSet, ":", 2)
if len(tagParts) != 2 {
return result, fmt.Errorf("invalid tag format: %s", tagParts)
}
k := tagParts[0]
v := tagParts[1]
if k == "" {
return result, fmt.Errorf("invalid tag format: %q", tagSet)
}

// support both simple tags (w/o value) and dimension tags (w/ value).
// dogstatsd notably allows simple tags.
var v string
if len(tagParts) == 2 {
v = tagParts[1]
}

kvs = append(kvs, attribute.String(k, v))
}
default:
Expand Down
18 changes: 15 additions & 3 deletions receiver/statsdreceiver/internal/protocol/statsd_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ func Test_ParseMessageToMetric(t *testing.T) {
},
{
name: "invalid tag format",
input: "test.metric:42|c|#key1",
err: errors.New("invalid tag format: [key1]"),
input: "test.metric:42|c|#:val1",
err: errors.New("invalid tag format: \":val1\""),
},
{
name: "unrecognized message part",
Expand Down Expand Up @@ -90,7 +90,7 @@ func Test_ParseMessageToMetric(t *testing.T) {
err: errors.New("unsupported metric type: unhandled_type"),
},
{
name: "counter metric with sample rate and tag",
name: "counter metric with sample rate and (dimensional) tag",
input: "test.metric:42|c|@0.1|#key:value",
wantMetric: testStatsDMetric(
"test.metric",
Expand All @@ -101,6 +101,18 @@ func Test_ParseMessageToMetric(t *testing.T) {
[]string{"key"},
[]string{"value"}),
},
{
name: "counter metric with sample rate and (simple) tag",
input: "test.metric:42|c|@0.1|#key",
wantMetric: testStatsDMetric(
"test.metric",
42,
false,
"c",
0.1,
[]string{"key"},
[]string{""}),
},
{
name: "counter metric with sample rate(not divisible) and tag",
input: "test.metric:42|c|@0.8|#key:value",
Expand Down

0 comments on commit 7d9d814

Please sign in to comment.