mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-30 01:34:21 -04:00 
			
		
		
		
	[plugin][trace] - Have a consistent spanName (#4171)
Automatically submitted.
This commit is contained in:
		| @@ -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: | ||||||
|   | |||||||
| @@ -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 ) | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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() |  | ||||||
| } |  | ||||||
| @@ -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)) | ||||||
| 			} | 			} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user