Skip to content

Commit

Permalink
[exporter/datadog]: improve mappings for span kind dd span type (#3368)
Browse files Browse the repository at this point in the history
* [exporter/datadog]: improve mappings for span kind dd span type

* [exporter/datadog]: pr feedback for span type heuristics
  • Loading branch information
ericmustin committed May 12, 2021
1 parent f4fbf5f commit 3ea9f85
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 14 deletions.
39 changes: 29 additions & 10 deletions exporter/datadogexporter/translate_traces.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,13 @@ const (
currentILNameTag string = "otel.library.name"
errorCode int32 = 1
okCode int32 = 0
httpKind string = "http"
webKind string = "web"
customKind string = "custom"
kindDb string = "db"
kindHTTP string = "http"
kindWeb string = "web"
kindCustom string = "custom"
kindCache string = "cache"
kindMemcached string = "memcached"
kindRedis string = "redis"
grpcPath string = "grpc.path"
eventsTag string = "events"
eventNameTag string = "name"
Expand Down Expand Up @@ -282,7 +286,7 @@ func spanToDatadogSpan(s pdata.Span,
Duration: duration,
Metrics: map[string]float64{},
Meta: make(map[string]string, len(tags)),
Type: spanKindToDatadogType(s.Kind()),
Type: inferDatadogType(s.Kind(), tags),
Error: isSpanError,
}

Expand Down Expand Up @@ -376,16 +380,31 @@ func buildDatadogContainerTags(spanTags map[string]string) string {
return strings.TrimSuffix(b.String(), ",")
}

// TODO: some clients send SPAN_KIND_UNSPECIFIED for valid kinds
// we also need a more formal mapping for cache and db types
func spanKindToDatadogType(kind pdata.SpanKind) string {
// inferDatadogTypes returns a string for the datadog type based on metadata
// in the otel span. DB semantic conventions state that what datadog
// would mark as a db or cache span type, otel marks as a CLIENT span kind, but
// has a required attribute 'db.system'. This is the only required attribute for
// db or cache spans, so we can reliably use it as a heuristic for infering the
// difference between client, db, and cache span types. The only "cache" spans
// in datadog currently are redis and memcached, so those are the only two db.system
// attribute values we have to check to determine whether it's a db or cache span
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/database.md#semantic-conventions-for-database-client-calls
func inferDatadogType(kind pdata.SpanKind, datadogTags map[string]string) string {
switch kind {
case pdata.SpanKindCLIENT:
return httpKind
if dbSysOtlp, ok := datadogTags[conventions.AttributeDBSystem]; ok {
if dbSysOtlp == kindRedis || dbSysOtlp == kindMemcached {
return kindCache
}

return kindDb
}

return kindHTTP
case pdata.SpanKindSERVER:
return webKind
return kindWeb
default:
return customKind
return kindCustom
}
}

Expand Down
26 changes: 22 additions & 4 deletions exporter/datadogexporter/translate_traces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1058,14 +1058,32 @@ func TestSpanNameNormalization(t *testing.T) {

// ensure that the datadog span type gets mapped from span kind
func TestSpanTypeTranslation(t *testing.T) {
spanTypeClient := spanKindToDatadogType(pdata.SpanKindCLIENT)
spanTypeServer := spanKindToDatadogType(pdata.SpanKindSERVER)
spanTypeCustom := spanKindToDatadogType(pdata.SpanKindUNSPECIFIED)
spanTypeClient := inferDatadogType(pdata.SpanKindCLIENT, map[string]string{})
spanTypeServer := inferDatadogType(pdata.SpanKindSERVER, map[string]string{})
spanTypeCustom := inferDatadogType(pdata.SpanKindUNSPECIFIED, map[string]string{})

ddTagsDb := map[string]string{
"db.system": "postgresql",
}

ddTagsCache := map[string]string{
"db.system": "redis",
}

ddTagsCacheAlt := map[string]string{
"db.system": "memcached",
}

spanTypeDb := inferDatadogType(pdata.SpanKindCLIENT, ddTagsDb)
spanTypeCache := inferDatadogType(pdata.SpanKindCLIENT, ddTagsCache)
spanTypeCacheAlt := inferDatadogType(pdata.SpanKindCLIENT, ddTagsCacheAlt)

assert.Equal(t, "http", spanTypeClient)
assert.Equal(t, "web", spanTypeServer)
assert.Equal(t, "custom", spanTypeCustom)

assert.Equal(t, "db", spanTypeDb)
assert.Equal(t, "cache", spanTypeCache)
assert.Equal(t, "cache", spanTypeCacheAlt)
}

// ensure that the IL Tags extraction handles nil case
Expand Down

0 comments on commit 3ea9f85

Please sign in to comment.