[plugin][trace] - Have a consistent spanName (#4171)

Automatically submitted.
This commit is contained in:
Bob
2020-10-12 21:30:55 +02:00
committed by GitHub
parent 5f5cc3188f
commit 0835f5bb5f
5 changed files with 61 additions and 27 deletions

View File

@@ -28,9 +28,16 @@ Additional features can be enabled with this syntax:
~~~ ~~~
trace [ENDPOINT-TYPE] [ENDPOINT] { trace [ENDPOINT-TYPE] [ENDPOINT] {
every AMOUNT every AMOUNT
service NAME service NAME
client_server client_server
}
~~~
~~~
trace datadog {
every AMOUNT
service NAME
datadog_analytics_rate RATE
} }
~~~ ~~~
@@ -39,6 +46,8 @@ trace [ENDPOINT-TYPE] [ENDPOINT] {
* `service` **NAME** allows you to specify the service name reported to the tracing server. * `service` **NAME** allows you to specify the service name reported to the tracing server.
Default is `coredns`. Default is `coredns`.
* `client_server` will enable the `ClientServerSameSpan` OpenTracing feature. * `client_server` will enable the `ClientServerSameSpan` OpenTracing feature.
* `datadog_analytics_rate` **RATE** will enable [trace analytics](https://docs.datadoghq.com/tracing/app_analytics) on the traces sent
from *0* to *1*, *1* being every trace sent will be analyzed. This is a datadog only feature.
## Zipkin ## Zipkin
You can run Zipkin on a Docker host like this: You can run Zipkin on a Docker host like this:

View File

@@ -83,6 +83,21 @@ func traceParse(c *caddy.Controller) (*trace, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
case "datadog_analytics_rate":
args := c.RemainingArgs()
if len(args) > 1 {
return nil, c.ArgErr()
}
tr.datadogAnalyticsRate = 0
if len(args) == 1 {
tr.datadogAnalyticsRate,err = strconv.ParseFloat(args[0], 64)
}
if err != nil {
return nil, err
}
if tr.datadogAnalyticsRate > 1 || tr.datadogAnalyticsRate < 0 {
return nil,fmt.Errorf("datadog analytics rate must be between 0 and 1, '%f' is not supported", tr.datadogAnalyticsRate )
}
} }
} }
} }

View File

@@ -22,6 +22,7 @@ func TestTraceParse(t *testing.T) {
{`trace zipkin localhost:1234`, false, "http://localhost:1234/api/v1/spans", 1, `coredns`, false}, {`trace zipkin localhost:1234`, false, "http://localhost:1234/api/v1/spans", 1, `coredns`, false},
{`trace datadog localhost`, false, "localhost", 1, `coredns`, false}, {`trace datadog localhost`, false, "localhost", 1, `coredns`, false},
{`trace datadog http://localhost:8127`, false, "http://localhost:8127", 1, `coredns`, false}, {`trace datadog http://localhost:8127`, false, "http://localhost:8127", 1, `coredns`, false},
{"trace datadog localhost {\n datadog_analytics_rate 0.1\n}", false, "localhost", 1, `coredns`, false},
{"trace {\n every 100\n}", false, "http://localhost:9411/api/v1/spans", 100, `coredns`, false}, {"trace {\n every 100\n}", false, "http://localhost:9411/api/v1/spans", 100, `coredns`, false},
{"trace {\n every 100\n service foobar\nclient_server\n}", false, "http://localhost:9411/api/v1/spans", 100, `foobar`, true}, {"trace {\n every 100\n service foobar\nclient_server\n}", false, "http://localhost:9411/api/v1/spans", 100, `foobar`, true},
{"trace {\n every 2\n client_server true\n}", false, "http://localhost:9411/api/v1/spans", 2, `coredns`, true}, {"trace {\n every 2\n client_server true\n}", false, "http://localhost:9411/api/v1/spans", 2, `coredns`, true},
@@ -29,6 +30,7 @@ func TestTraceParse(t *testing.T) {
// fails // fails
{`trace footype localhost:4321`, true, "", 1, "", false}, {`trace footype localhost:4321`, true, "", 1, "", false},
{"trace {\n every 2\n client_server junk\n}", true, "", 1, "", false}, {"trace {\n every 2\n client_server junk\n}", true, "", 1, "", false},
{"trace datadog localhost {\n datadog_analytics_rate 2\n}", true, "", 1, "", false},
} }
for i, test := range tests { for i, test := range tests {
c := caddy.NewTestController("dns", test.input) c := caddy.NewTestController("dns", test.input)

View File

@@ -8,7 +8,6 @@ import (
"sync/atomic" "sync/atomic"
"github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin"
"github.com/coredns/coredns/plugin/metrics"
"github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/pkg/dnstest"
"github.com/coredns/coredns/plugin/pkg/log" "github.com/coredns/coredns/plugin/pkg/log"
"github.com/coredns/coredns/plugin/pkg/rcode" "github.com/coredns/coredns/plugin/pkg/rcode"
@@ -20,30 +19,33 @@ import (
zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing" zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing"
"github.com/openzipkin/zipkin-go" "github.com/openzipkin/zipkin-go"
zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http" zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
) )
const ( const (
tagName = "coredns.io/name" tagName = "coredns.io/name"
tagType = "coredns.io/type" tagType = "coredns.io/type"
tagRcode = "coredns.io/rcode" tagRcode = "coredns.io/rcode"
tagProto = "coredns.io/proto" tagProto = "coredns.io/proto"
tagRemote = "coredns.io/remote" tagRemote = "coredns.io/remote"
defaultTopLevelSpanName = "servedns"
) )
type trace struct { type trace struct {
count uint64 // as per Go spec, needs to be first element in a struct count uint64 // as per Go spec, needs to be first element in a struct
Next plugin.Handler Next plugin.Handler
Endpoint string Endpoint string
EndpointType string EndpointType string
tracer ot.Tracer tracer ot.Tracer
serviceEndpoint string serviceEndpoint string
serviceName string serviceName string
clientServer bool clientServer bool
every uint64 every uint64
Once sync.Once datadogAnalyticsRate float64
Once sync.Once
} }
func (t *trace) Tracer() ot.Tracer { func (t *trace) Tracer() ot.Tracer {
@@ -58,7 +60,13 @@ func (t *trace) OnStartup() error {
case "zipkin": case "zipkin":
err = t.setupZipkin() err = t.setupZipkin()
case "datadog": case "datadog":
tracer := opentracer.New(tracer.WithAgentAddr(t.Endpoint), tracer.WithServiceName(t.serviceName), tracer.WithDebugMode(log.D.Value())) tracer := opentracer.New(
tracer.WithAgentAddr(t.Endpoint),
tracer.WithDebugMode(log.D.Value()),
tracer.WithGlobalTag(ext.SpanTypeDNS, true),
tracer.WithServiceName(t.serviceName),
tracer.WithAnalyticsRate(t.datadogAnalyticsRate),
)
t.tracer = tracer t.tracer = tracer
default: default:
err = fmt.Errorf("unknown endpoint type: %s", t.EndpointType) err = fmt.Errorf("unknown endpoint type: %s", t.EndpointType)
@@ -73,7 +81,10 @@ func (t *trace) setupZipkin() error {
if err != nil { if err != nil {
log.Warningf("build Zipkin endpoint found err: %v", err) log.Warningf("build Zipkin endpoint found err: %v", err)
} }
tracer, err := zipkin.NewTracer(reporter, zipkin.WithLocalEndpoint(recorder)) tracer, err := zipkin.NewTracer(
reporter,
zipkin.WithLocalEndpoint(recorder),
)
if err != nil { if err != nil {
return err return err
} }
@@ -100,7 +111,7 @@ func (t *trace) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
} }
req := request.Request{W: w, Req: r} req := request.Request{W: w, Req: r}
span = t.Tracer().StartSpan(spanName(ctx, req)) span = t.Tracer().StartSpan(defaultTopLevelSpanName)
defer span.Finish() defer span.Finish()
rw := dnstest.NewRecorder(w) rw := dnstest.NewRecorder(w)
@@ -115,7 +126,3 @@ func (t *trace) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
return status, err return status, err
} }
func spanName(ctx context.Context, req request.Request) string {
return "servedns:" + metrics.WithServer(ctx) + " " + req.Name()
}

View File

@@ -79,9 +79,10 @@ func TestTrace(t *testing.T) {
rootSpan := fs[1] rootSpan := fs[1]
req := request.Request{W: w, Req: tc.question} req := request.Request{W: w, Req: tc.question}
if rootSpan.OperationName != spanName(ctx, req) { if rootSpan.OperationName != defaultTopLevelSpanName {
t.Errorf("Unexpected span name: rootSpan.Name: want %v, got %v", spanName(ctx, req), rootSpan.OperationName) t.Errorf("Unexpected span name: rootSpan.Name: want %v, got %v", defaultTopLevelSpanName, rootSpan.OperationName)
} }
if rootSpan.Tag(tagName) != req.Name() { if rootSpan.Tag(tagName) != req.Name() {
t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", tagName, req.Name(), rootSpan.Tag(tagName)) t.Errorf("Unexpected span tag: rootSpan.Tag(%v): want %v, got %v", tagName, req.Name(), rootSpan.Tag(tagName))
} }