Skip to content

Commit

Permalink
feat(dogstatsd): add cardinality common field
Browse files Browse the repository at this point in the history
Signed-off-by: Wassim DHIF <[email protected]>
  • Loading branch information
wdhif committed Jan 19, 2025
1 parent cb0d65b commit 29786f5
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 8 deletions.
11 changes: 6 additions & 5 deletions comp/dogstatsd/server/enrich.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@ type enrichConfig struct {
}

// extractTagsMetadata returns tags (client tags + host tag) and information needed to query tagger (origins, cardinality).
func extractTagsMetadata(tags []string, originFromUDS string, localData origindetection.LocalData, externalData origindetection.ExternalData, conf enrichConfig) ([]string, string, taggertypes.OriginInfo, metrics.MetricSource) {
func extractTagsMetadata(tags []string, originFromUDS string, localData origindetection.LocalData, externalData origindetection.ExternalData, cardinality string, conf enrichConfig) ([]string, string, taggertypes.OriginInfo, metrics.MetricSource) {
host := conf.defaultHostname
metricSource := metrics.MetricSourceDogstatsd
origin := taggertypes.OriginInfo{
ContainerIDFromSocket: originFromUDS,
LocalData: localData,
ExternalData: externalData,
ProductOrigin: origindetection.ProductOriginDogStatsD,
Cardinality: cardinality,
}

n := 0
Expand All @@ -55,7 +56,7 @@ func extractTagsMetadata(tags []string, originFromUDS string, localData originde
} else if strings.HasPrefix(tag, entityIDTagPrefix) {
origin.LocalData.PodUID = tag[len(entityIDTagPrefix):]
continue
} else if strings.HasPrefix(tag, CardinalityTagPrefix) {
} else if strings.HasPrefix(tag, CardinalityTagPrefix) && origin.Cardinality == "" {
origin.Cardinality = tag[len(CardinalityTagPrefix):]
continue
} else if strings.HasPrefix(tag, jmxCheckNamePrefix) {
Expand Down Expand Up @@ -112,7 +113,7 @@ func tsToFloatForSamples(ts time.Time) float64 {

func enrichMetricSample(dest []metrics.MetricSample, ddSample dogstatsdMetricSample, origin string, listenerID string, conf enrichConfig) []metrics.MetricSample {
metricName := ddSample.name
tags, hostnameFromTags, extractedOrigin, metricSource := extractTagsMetadata(ddSample.tags, origin, ddSample.localData, ddSample.externalData, conf)
tags, hostnameFromTags, extractedOrigin, metricSource := extractTagsMetadata(ddSample.tags, origin, ddSample.localData, ddSample.externalData, ddSample.cardinality, conf)

if !isExcluded(metricName, conf.metricPrefix, conf.metricPrefixBlacklist) {
metricName = conf.metricPrefix + metricName
Expand Down Expand Up @@ -192,7 +193,7 @@ func enrichEventAlertType(dogstatsdAlertType alertType) metricsevent.AlertType {
}

func enrichEvent(event dogstatsdEvent, origin string, conf enrichConfig) *metricsevent.Event {
tags, hostnameFromTags, extractedOrigin, _ := extractTagsMetadata(event.tags, origin, event.localData, event.externalData, conf)
tags, hostnameFromTags, extractedOrigin, _ := extractTagsMetadata(event.tags, origin, event.localData, event.externalData, event.cardinality, conf)

enrichedEvent := &metricsevent.Event{
Title: event.title,
Expand Down Expand Up @@ -229,7 +230,7 @@ func enrichServiceCheckStatus(status serviceCheckStatus) servicecheck.ServiceChe
}

func enrichServiceCheck(serviceCheck dogstatsdServiceCheck, origin string, conf enrichConfig) *servicecheck.ServiceCheck {
tags, hostnameFromTags, extractedOrigin, _ := extractTagsMetadata(serviceCheck.tags, origin, serviceCheck.localData, serviceCheck.externalData, conf)
tags, hostnameFromTags, extractedOrigin, _ := extractTagsMetadata(serviceCheck.tags, origin, serviceCheck.localData, serviceCheck.externalData, serviceCheck.cardinality, conf)

enrichedServiceCheck := &servicecheck.ServiceCheck{
CheckName: serviceCheck.name,
Expand Down
2 changes: 1 addition & 1 deletion comp/dogstatsd/server/enrich_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func BenchmarkExtractTagsMetadata(b *testing.B) {
sb.ResetTimer()

for n := 0; n < sb.N; n++ {
tags, _, _, _ = extractTagsMetadata(baseTags, "", origindetection.LocalData{}, origindetection.ExternalData{}, conf)
tags, _, _, _ = extractTagsMetadata(baseTags, "", origindetection.LocalData{}, origindetection.ExternalData{}, "", conf)
}
})
}
Expand Down
39 changes: 37 additions & 2 deletions comp/dogstatsd/server/enrich_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,7 @@ func TestEnrichTags(t *testing.T) {
originFromMsg []byte
localData origindetection.LocalData
externalData origindetection.ExternalData
cardinality string
conf enrichConfig
}
tests := []struct {
Expand Down Expand Up @@ -1463,12 +1464,46 @@ func TestEnrichTags(t *testing.T) {
},
wantedMetricSource: metrics.MetricSourceDogstatsd,
},
{
name: "cardinality field as none",
args: args{
cardinality: types.NoneCardinalityString,
},
wantedTags: nil,
wantedOrigin: taggertypes.OriginInfo{
Cardinality: "none",
},
wantedMetricSource: metrics.MetricSourceDogstatsd,
},
{
name: "cardinality field as high",
args: args{
cardinality: types.HighCardinalityString,
},
wantedTags: nil,
wantedOrigin: taggertypes.OriginInfo{
Cardinality: "high",
},
wantedMetricSource: metrics.MetricSourceDogstatsd,
},
{
name: "cardinality field with dd.internal.card",
args: args{
tags: []string{"env:prod", "dd.internal.card:high"},
cardinality: types.NoneCardinalityString,
},
wantedTags: []string{"env:prod", "dd.internal.card:high"},
wantedOrigin: taggertypes.OriginInfo{
Cardinality: "none",
},
wantedMetricSource: metrics.MetricSourceDogstatsd,
},
}
for _, tt := range tests {
tt.wantedOrigin.ProductOrigin = origindetection.ProductOriginDogStatsD

t.Run(tt.name, func(t *testing.T) {
tags, host, origin, metricSource := extractTagsMetadata(tt.args.tags, tt.args.originFromUDS, tt.args.localData, tt.args.externalData, tt.args.conf)
tags, host, origin, metricSource := extractTagsMetadata(tt.args.tags, tt.args.originFromUDS, tt.args.localData, tt.args.externalData, tt.args.cardinality, tt.args.conf)
assert.Equal(t, tt.wantedTags, tags)
assert.Equal(t, tt.wantedHost, host)
assert.Equal(t, tt.wantedOrigin, origin)
Expand Down Expand Up @@ -1516,7 +1551,7 @@ func TestEnrichTagsWithJMXCheckName(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tags, _, _, metricSource := extractTagsMetadata(tt.tags, "", origindetection.LocalData{}, origindetection.ExternalData{}, enrichConfig{})
tags, _, _, metricSource := extractTagsMetadata(tt.tags, "", origindetection.LocalData{}, origindetection.ExternalData{}, "", enrichConfig{})
assert.Equal(t, tt.wantedTags, tags)
assert.Equal(t, tt.wantedMetricSource, metricSource)
assert.NotContains(t, tags, tt.jmxCheckName)
Expand Down
8 changes: 8 additions & 0 deletions comp/dogstatsd/server/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ var (

// externalDataPrefix is the prefix for a common field which contains the external data for Origin Detection.
externalDataPrefix = []byte("e:")

// cardinalityPrefix is the prefix for a common field which contains the cardinality for Origin Detection.
cardinalityPrefix = []byte("card:")
)

// parser parses dogstatsd messages
Expand Down Expand Up @@ -174,6 +177,7 @@ func (p *parser) parseMetricSample(message []byte) (dogstatsdMetricSample, error
var tags []string
var localData origindetection.LocalData
var externalData origindetection.ExternalData
var cardinality string
var optionalField []byte
var timestamp time.Time
for message != nil {
Expand Down Expand Up @@ -207,6 +211,9 @@ func (p *parser) parseMetricSample(message []byte) (dogstatsdMetricSample, error
// external data
case p.dsdOriginEnabled && bytes.HasPrefix(optionalField, externalDataPrefix):
externalData = p.parseExternalData(optionalField[len(externalDataPrefix):])
// cardinality
case p.dsdOriginEnabled && bytes.HasPrefix(optionalField, cardinalityPrefix):
cardinality = string(optionalField[len(cardinalityPrefix):])
}
}

Expand All @@ -220,6 +227,7 @@ func (p *parser) parseMetricSample(message []byte) (dogstatsdMetricSample, error
tags: tags,
localData: localData,
externalData: externalData,
cardinality: cardinality,
ts: timestamp,
}, nil
}
Expand Down
4 changes: 4 additions & 0 deletions comp/dogstatsd/server/parse_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type dogstatsdEvent struct {
localData origindetection.LocalData
// externalData is used for Origin Detection
externalData origindetection.ExternalData
// cardinality is used for Origin Detection
cardinality string
}

type eventHeader struct {
Expand Down Expand Up @@ -170,6 +172,8 @@ func (p *parser) applyEventOptionalField(event dogstatsdEvent, optionalField []b
newEvent.localData = p.parseLocalData(optionalField[len(localDataPrefix):])
case p.dsdOriginEnabled && bytes.HasPrefix(optionalField, externalDataPrefix):
newEvent.externalData = p.parseExternalData(optionalField[len(externalDataPrefix):])
case p.dsdOriginEnabled && bytes.HasPrefix(optionalField, cardinalityPrefix):
newEvent.cardinality = string(optionalField[len(cardinalityPrefix):])
}
if err != nil {
return event, err
Expand Down
2 changes: 2 additions & 0 deletions comp/dogstatsd/server/parse_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ type dogstatsdMetricSample struct {
localData origindetection.LocalData
// externalData is used for Origin Detection
externalData origindetection.ExternalData
// cardinality is used for Origin Detection
cardinality string
// timestamp read in the message if any
ts time.Time
}
Expand Down
4 changes: 4 additions & 0 deletions comp/dogstatsd/server/parse_service_checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type dogstatsdServiceCheck struct {
localData origindetection.LocalData
// externalData is used for Origin Detection
externalData origindetection.ExternalData
// cardinality is used for Origin Detection
cardinality string
}

var (
Expand Down Expand Up @@ -104,6 +106,8 @@ func (p *parser) applyServiceCheckOptionalField(serviceCheck dogstatsdServiceChe
newServiceCheck.localData = p.parseLocalData(optionalField[len(localDataPrefix):])
case p.dsdOriginEnabled && bytes.HasPrefix(optionalField, externalDataPrefix):
newServiceCheck.externalData = p.parseExternalData(optionalField[len(externalDataPrefix):])
case p.dsdOriginEnabled && bytes.HasPrefix(optionalField, cardinalityPrefix):
newServiceCheck.cardinality = string(optionalField[len(cardinalityPrefix):])
}
if err != nil {
return serviceCheck, err
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Each section from every release note are combined when the
# CHANGELOG.rst is rendered. So the text needs to be worded so that
# it does not depend on any information only available in another
# section. This may mean repeating some details, but each section
# must be readable independently of the other.
#
# Each section note must be formatted as reStructuredText.
---
features:
- |
Add new `card:` common field to DogStatsD Datagram specification to allow
customer to specify the cardinality of the metric. This field is optional.

0 comments on commit 29786f5

Please sign in to comment.