From f113cc090cee63e59d38cdda0dbeea9cad51ebdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Ch=C3=A1vez?= Date: Wed, 11 Nov 2020 13:51:49 +0100 Subject: [PATCH] feat: adds support for isNoop check on spans. (#181) * feat: adds support for isNoop check on spans. Span.IsNoop is specially usefull to avoid expensive operations when the tags or logs are not being recorded e.g. if you are about to read the body and process it to obtain certain tags, the check would save that computation as no changes will take effect. * chore: fixes license year. * chore: changes the IsNoop change into a package level function as per @basvanbeek's suggestion IsNoop is more of the concern of the tracer and not necessarily of the span's concern, hence turning this method into a function. --- middleware/grpc/server.go | 8 +++++--- middleware/grpc/shared.go | 5 ++++- middleware/http/server.go | 19 ++++++++++++------- middleware/http/transport.go | 8 +++++++- noop.go | 9 ++++++++- span.go | 2 +- span_implementation.go | 2 +- 7 files changed, 38 insertions(+), 15 deletions(-) diff --git a/middleware/grpc/server.go b/middleware/grpc/server.go index 8f7faac1..26b21e25 100644 --- a/middleware/grpc/server.go +++ b/middleware/grpc/server.go @@ -1,4 +1,4 @@ -// Copyright 2019 The OpenZipkin Authors +// Copyright 2020 The OpenZipkin Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -83,8 +83,10 @@ func (s *serverHandler) TagRPC(ctx context.Context, rti *stats.RPCTagInfo) conte span := s.tracer.StartSpan(name, zipkin.Kind(model.Server), zipkin.Parent(sc), zipkin.RemoteEndpoint(remoteEndpointFromContext(ctx, ""))) - for k, v := range s.defaultTags { - span.Tag(k, v) + if !zipkin.IsNoop(span) { + for k, v := range s.defaultTags { + span.Tag(k, v) + } } return zipkin.NewContext(ctx, span) diff --git a/middleware/grpc/shared.go b/middleware/grpc/shared.go index c32c0bbd..f0b167eb 100644 --- a/middleware/grpc/shared.go +++ b/middleware/grpc/shared.go @@ -1,4 +1,4 @@ -// Copyright 2019 The OpenZipkin Authors +// Copyright 2020 The OpenZipkin Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -39,6 +39,9 @@ func spanName(rti *stats.RPCTagInfo) string { func handleRPC(ctx context.Context, rs stats.RPCStats) { span := zipkin.SpanFromContext(ctx) + if zipkin.IsNoop(span) { + return + } switch rs := rs.(type) { case *stats.End: diff --git a/middleware/http/server.go b/middleware/http/server.go index 0b4c7604..1e9775e7 100644 --- a/middleware/http/server.go +++ b/middleware/http/server.go @@ -1,4 +1,4 @@ -// Copyright 2019 The OpenZipkin Authors +// Copyright 2020 The OpenZipkin Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -107,8 +107,6 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } - remoteEndpoint, _ := zipkin.NewEndpoint("", r.RemoteAddr) - if len(h.name) == 0 { spanName = r.Method } else { @@ -120,16 +118,23 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { spanName, zipkin.Kind(model.Server), zipkin.Parent(sc), - zipkin.RemoteEndpoint(remoteEndpoint), ) + // add our span to context + ctx := zipkin.NewContext(r.Context(), sp) + + if zipkin.IsNoop(sp) { + // While the span is not being recorded, we still want to propagate the context. + h.next.ServeHTTP(w, r.WithContext(ctx)) + return + } + + remoteEndpoint, _ := zipkin.NewEndpoint("", r.RemoteAddr) + sp.SetRemoteEndpoint(remoteEndpoint) for k, v := range h.defaultTags { sp.Tag(k, v) } - // add our span to context - ctx := zipkin.NewContext(r.Context(), sp) - // tag typical HTTP request items zipkin.TagHTTPMethod.Set(sp, r.Method) zipkin.TagHTTPPath.Set(sp, r.URL.Path) diff --git a/middleware/http/transport.go b/middleware/http/transport.go index 7facdb5f..af029186 100644 --- a/middleware/http/transport.go +++ b/middleware/http/transport.go @@ -1,4 +1,4 @@ -// Copyright 2019 The OpenZipkin Authors +// Copyright 2020 The OpenZipkin Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -154,6 +154,12 @@ func (t *transport) RoundTrip(req *http.Request) (res *http.Response, err error) req.Context(), req.URL.Scheme+"/"+req.Method, zipkin.Kind(model.Client), zipkin.RemoteEndpoint(t.remoteEndpoint), ) + if zipkin.IsNoop(sp) { + // While the span is not being recorded, we still want to propagate the context. + _ = b3.InjectHTTP(req)(sp.Context()) + return t.rt.RoundTrip(req) + } + for k, v := range t.defaultTags { sp.Tag(k, v) } diff --git a/noop.go b/noop.go index 1368b9e7..cd1c8f60 100644 --- a/noop.go +++ b/noop.go @@ -1,4 +1,4 @@ -// Copyright 2019 The OpenZipkin Authors +// Copyright 2020 The OpenZipkin Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -39,3 +39,10 @@ func (*noopSpan) Finish() {} func (*noopSpan) FinishedWithDuration(duration time.Duration) {} func (*noopSpan) Flush() {} + +// IsNoop tells whether the span is noop or not. Usually used to avoid resource misusage +// when customizing a span as data won't be recorded +func IsNoop(s Span) bool { + _, ok := s.(*noopSpan) + return ok +} diff --git a/span.go b/span.go index cc915681..8c9dc7c6 100644 --- a/span.go +++ b/span.go @@ -1,4 +1,4 @@ -// Copyright 2019 The OpenZipkin Authors +// Copyright 2020 The OpenZipkin Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/span_implementation.go b/span_implementation.go index 72904a84..f07b5429 100644 --- a/span_implementation.go +++ b/span_implementation.go @@ -1,4 +1,4 @@ -// Copyright 2019 The OpenZipkin Authors +// Copyright 2020 The OpenZipkin Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.