Skip to content

Commit

Permalink
chore(origindetection): implement LocalData struct for DogStatsD
Browse files Browse the repository at this point in the history
Signed-off-by: Wassim DHIF <[email protected]>
  • Loading branch information
wdhif committed Jan 9, 2025
1 parent cc7d330 commit f7f1973
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 182 deletions.
2 changes: 1 addition & 1 deletion comp/core/tagger/impl/tagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ func (t *TaggerWrapper) EnrichTags(tb tagset.TagsAccumulator, originInfo taggert
// Accumulate tags for pod UID
if originInfo.ExternalData.PodUID != "" {
if err := t.AccumulateTagsFor(types.NewEntityID(types.KubernetesPodUID, originInfo.ExternalData.PodUID), cardinality, tb); err != nil {
t.log.Tracef("Cannot get tags for entity %s: %s", originInfo.ContainerID, err)
t.log.Tracef("Cannot get tags for entity %s: %s", originInfo.ExternalData.PodUID, err)
}
}

Expand Down
45 changes: 45 additions & 0 deletions comp/core/tagger/origindetection/origindetection.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ const (
// ProductOriginAPM is the ProductOrigin for APM.
ProductOriginAPM ProductOrigin = iota

// Local Data Prefixes
// These prefixes are used to build the Local Data list.

// LocalDataContainerIDPrefix is the prefix used for the Container ID sent in the Local Data list.
LocalDataContainerIDPrefix = "ci-"
// LocalDataInodePrefix is the prefix used for the Inode sent in the Local Data list.
LocalDataInodePrefix = "in-"

// External Data Prefixes
// These prefixes are used to build the External Data Environment Variable.

Expand Down Expand Up @@ -63,13 +71,49 @@ type ExternalData struct {
// GenerateContainerIDFromExternalData generates a container ID from the external data.
type GenerateContainerIDFromExternalData func(externalData ExternalData) (string, error)

// ParseLocalData parses the local data string into a LocalData struct.
func ParseLocalData(rawLocalData string) (LocalData, error) {
if rawLocalData == "" {
return LocalData{}, nil
}

var localData LocalData
var parsingError error

if strings.Contains(rawLocalData, ",") {
// The Local Data can contain a list.
items := strings.Split(rawLocalData, ",")
for _, item := range items {
if strings.HasPrefix(item, LocalDataContainerIDPrefix) {
localData.ContainerID = item[len(LocalDataContainerIDPrefix):]
} else if strings.HasPrefix(item, LocalDataInodePrefix) {
localData.Inode, parsingError = strconv.ParseUint(item[len(LocalDataInodePrefix):], 10, 64)
}
}
} else {
// The Local Data can contain a single value.
if strings.HasPrefix(rawLocalData, LocalDataContainerIDPrefix) {
localData.ContainerID = rawLocalData[len(LocalDataContainerIDPrefix):]
} else if strings.HasPrefix(rawLocalData, LocalDataInodePrefix) {
localData.Inode, parsingError = strconv.ParseUint(rawLocalData[len(LocalDataInodePrefix):], 10, 64)
} else {
// Container ID with old format: <container-id>
localData.ContainerID = rawLocalData
}
}

return localData, parsingError
}

// ParseExternalData parses the external data string into an ExternalData struct.
func ParseExternalData(externalEnv string) (ExternalData, error) {
if externalEnv == "" {
return ExternalData{}, nil
}

var externalData ExternalData
var parsingError error

for _, item := range strings.Split(externalEnv, ",") {
switch {
case strings.HasPrefix(item, ExternalDataInitPrefix):
Expand All @@ -80,5 +124,6 @@ func ParseExternalData(externalEnv string) (ExternalData, error) {
externalData.PodUID = item[len(ExternalDataPodUIDPrefix):]
}
}

return externalData, parsingError
}
59 changes: 59 additions & 0 deletions comp/core/tagger/origindetection/origindetection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,65 @@ import (
"github.com/stretchr/testify/assert"
)

func TestParseLocalData(t *testing.T) {
tests := []struct {
name string
rawLocalData string
expected LocalData
expectError bool
}{
{
name: "Empty string",
rawLocalData: "",
expected: LocalData{},
expectError: false,
},
{
name: "Single container ID",
rawLocalData: "ci-abc123",
expected: LocalData{ContainerID: "abc123"},
expectError: false,
},
{
name: "Single inode",
rawLocalData: "in-12345",
expected: LocalData{Inode: 12345},
expectError: false,
},
{
name: "Multiple values",
rawLocalData: "ci-abc123,in-12345",
expected: LocalData{ContainerID: "abc123", Inode: 12345},
expectError: false,
},
{
name: "Invalid inode",
rawLocalData: "in-invalid",
expected: LocalData{},
expectError: true,
},
{
name: "Old container format",
rawLocalData: "abc123",
expected: LocalData{ContainerID: "abc123"},
expectError: false,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result, err := ParseLocalData(tc.rawLocalData)

if tc.expectError {
assert.Error(t, err)
} else {
assert.Equal(t, tc.expected, result)
}

})
}
}

func TestParseExternalData(t *testing.T) {
tests := []struct {
name string
Expand Down
11 changes: 6 additions & 5 deletions comp/dogstatsd/server/enrich.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ type enrichConfig struct {
}

// extractTagsMetadata returns tags (client tags + host tag) and information needed to query tagger (origins, cardinality).
func extractTagsMetadata(tags []string, originFromUDS string, originFromMsg []byte, externalData origindetection.ExternalData, conf enrichConfig) ([]string, string, taggertypes.OriginInfo, metrics.MetricSource) {
func extractTagsMetadata(tags []string, originFromUDS string, localData origindetection.LocalData, externalData origindetection.ExternalData, conf enrichConfig) ([]string, string, taggertypes.OriginInfo, metrics.MetricSource) {
host := conf.defaultHostname
metricSource := metrics.MetricSourceDogstatsd
origin := taggertypes.OriginInfo{
ContainerIDFromSocket: originFromUDS,
ContainerID: string(originFromMsg),
ContainerID: localData.ContainerID,
LocalData: localData,
ExternalData: externalData,
ProductOrigin: origindetection.ProductOriginDogStatsD,
}
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.containerID, ddSample.externalData, conf)
tags, hostnameFromTags, extractedOrigin, metricSource := extractTagsMetadata(ddSample.tags, origin, ddSample.localData, ddSample.externalData, 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.containerID, event.externalData, conf)
tags, hostnameFromTags, extractedOrigin, _ := extractTagsMetadata(event.tags, origin, event.localData, event.externalData, 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.containerID, serviceCheck.externalData, conf)
tags, hostnameFromTags, extractedOrigin, _ := extractTagsMetadata(serviceCheck.tags, origin, serviceCheck.localData, serviceCheck.externalData, 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, "", []byte{}, origindetection.ExternalData{}, conf)
tags, _, _, _ = extractTagsMetadata(baseTags, "", origindetection.LocalData{}, origindetection.ExternalData{}, conf)
}
})
}
Expand Down
Loading

0 comments on commit f7f1973

Please sign in to comment.