plugin/trace - Use compatible tag name for datadog (#4408)

Traces are currently working properly with datadog with the exception of having the ability to facet the tags

![image](https://user-images.githubusercontent.com/5513509/105051238-dddbbd00-5a6e-11eb-8fb2-071b3b1fa8cc.png)

In order to get valuable graph in dashboard the tag on the metrics need to be faceted by datadog.
This PR update the tags with facetable path.
While keeping backward compatibility with existing path for zipkin.

Graph like:
![image](https://user-images.githubusercontent.com/5513509/93375960-339e1f80-f859-11ea-81f0-a1074c375630.png)
![image](https://user-images.githubusercontent.com/5513509/93375997-4153a500-f859-11ea-9f8d-63d45217c681.png)
![image](https://user-images.githubusercontent.com/5513509/93376064-5597a200-f859-11ea-823a-6768f59e3497.png)
![image](https://user-images.githubusercontent.com/5513509/93376405-d6ef3480-f859-11ea-8d6f-58dda247cc86.png)
![image](https://user-images.githubusercontent.com/5513509/93376518-069e3c80-f85a-11ea-9a7e-0426a3817439.png)

Signed-off-by: bob <bob.bouteillier@datadoghq.com>
This commit is contained in:
Bob
2021-01-28 16:38:24 +01:00
committed by GitHub
parent fc5c172109
commit d8d2c16905
2 changed files with 51 additions and 21 deletions

View File

@@ -25,14 +25,34 @@ import (
)
const (
tagName = "coredns.io/name"
tagType = "coredns.io/type"
tagRcode = "coredns.io/rcode"
tagProto = "coredns.io/proto"
tagRemote = "coredns.io/remote"
defaultTopLevelSpanName = "servedns"
)
type traceTags struct {
Name string
Type string
Rcode string
Proto string
Remote string
}
var tagByProvider = map[string]traceTags{
"default": {
Name: "coredns.io/name",
Type: "coredns.io/type",
Rcode: "coredns.io/rcode",
Proto: "coredns.io/proto",
Remote: "coredns.io/remote",
},
"datadog": {
Name: "coredns.io@name",
Type: "coredns.io@type",
Rcode: "coredns.io@rcode",
Proto: "coredns.io@proto",
Remote: "coredns.io@remote",
},
}
type trace struct {
count uint64 // as per Go spec, needs to be first element in a struct
@@ -46,6 +66,7 @@ type trace struct {
every uint64
datadogAnalyticsRate float64
Once sync.Once
tagSet traceTags
}
func (t *trace) Tracer() ot.Tracer {
@@ -68,6 +89,7 @@ func (t *trace) OnStartup() error {
tracer.WithAnalyticsRate(t.datadogAnalyticsRate),
)
t.tracer = tracer
t.tagSet = tagByProvider["datadog"]
default:
err = fmt.Errorf("unknown endpoint type: %s", t.EndpointType)
}
@@ -90,6 +112,8 @@ func (t *trace) setupZipkin() error {
return err
}
t.tracer = zipkinot.Wrap(tracer)
t.tagSet = tagByProvider["default"]
return err
}
@@ -119,11 +143,11 @@ func (t *trace) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
ctx = ot.ContextWithSpan(ctx, span)
status, err := plugin.NextOrFailure(t.Name(), t.Next, ctx, rw, r)
span.SetTag(tagName, req.Name())
span.SetTag(tagType, req.Type())
span.SetTag(tagProto, req.Proto())
span.SetTag(tagRemote, req.IP())
span.SetTag(tagRcode, rcode.ToString(rw.Rcode))
span.SetTag(t.tagSet.Name, req.Name())
span.SetTag(t.tagSet.Type, req.Type())
span.SetTag(t.tagSet.Proto, req.Proto())
span.SetTag(t.tagSet.Remote, req.IP())
span.SetTag(t.tagSet.Rcode, rcode.ToString(rw.Rcode))
return status, err
}

View File

@@ -28,6 +28,11 @@ func TestStartup(t *testing.T) {
t.Errorf("Error starting tracing plugin: %s", err)
return
}
if m.tagSet != tagByProvider["default"] {
t.Errorf("TagSet by proviser hasn't been corectly initialized")
}
if m.Tracer() == nil {
t.Errorf("Error, no tracer created")
}
@@ -51,7 +56,7 @@ func TestTrace(t *testing.T) {
question: new(dns.Msg).SetQuestion("example.net.", dns.TypeCNAME),
},
}
defaultTagSet := tagByProvider["default"]
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
w := dnstest.NewRecorder(&test.ResponseWriter{})
@@ -65,6 +70,7 @@ func TestTrace(t *testing.T) {
}),
every: 1,
tracer: m,
tagSet: defaultTagSet,
}
ctx := context.TODO()
if _, err := tr.ServeDNS(ctx, w, tc.question); err != nil {
@@ -83,20 +89,20 @@ func TestTrace(t *testing.T) {
t.Errorf("Unexpected span name: rootSpan.Name: want %v, got %v", defaultTopLevelSpanName, rootSpan.OperationName)
}
if rootSpan.Tag(tagName) != req.Name() {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", tagName, req.Name(), rootSpan.Tag(tagName))
if rootSpan.Tag(defaultTagSet.Name) != req.Name() {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", defaultTagSet.Name, req.Name(), rootSpan.Tag(defaultTagSet.Name))
}
if rootSpan.Tag(tagType) != req.Type() {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", tagType, req.Type(), rootSpan.Tag(tagType))
if rootSpan.Tag(defaultTagSet.Type) != req.Type() {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", defaultTagSet.Type, req.Type(), rootSpan.Tag(defaultTagSet.Type))
}
if rootSpan.Tag(tagProto) != req.Proto() {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", tagProto, req.Proto(), rootSpan.Tag(tagProto))
if rootSpan.Tag(defaultTagSet.Proto) != req.Proto() {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", defaultTagSet.Proto, req.Proto(), rootSpan.Tag(defaultTagSet.Proto))
}
if rootSpan.Tag(tagRemote) != req.IP() {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", tagRemote, req.IP(), rootSpan.Tag(tagRemote))
if rootSpan.Tag(defaultTagSet.Remote) != req.IP() {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", defaultTagSet.Remote, req.IP(), rootSpan.Tag(defaultTagSet.Remote))
}
if rootSpan.Tag(tagRcode) != rcode.ToString(tc.rcode) {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", tagRcode, rcode.ToString(tc.rcode), rootSpan.Tag(tagRcode))
if rootSpan.Tag(defaultTagSet.Rcode) != rcode.ToString(tc.rcode) {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", defaultTagSet.Rcode, rcode.ToString(tc.rcode), rootSpan.Tag(defaultTagSet.Rcode))
}
})
}