Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zipkin native instrumentation using zipkin-go #2

Merged
merged 4 commits into from
Jan 17, 2018
Merged

Zipkin native instrumentation using zipkin-go #2

merged 4 commits into from
Jan 17, 2018

Conversation

basvanbeek
Copy link
Owner

First stab at new middleware for Zipkin.

Needs unit tests, improved documentation and improved code comments

Copy link

@codefromthecrypt codefromthecrypt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, nits only.

One overall comment could be that somewhere in the wiring, mention that remote context injection/extracting seems still an ot function, even if using a zipkin tracer.. unless I somehow missed where that's not the case

zipkinURL = fs.String("zipkin-url", "", "Enable Zipkin tracing via a collector URL e.g. http://localhost:9411/api/v1/spans")
lightstepToken = flag.String("lightstep-token", "", "Enable LightStep tracing via a LightStep access token")
appdashAddr = flag.String("appdash-addr", "", "Enable Appdash tracing via an Appdash server host:port")
zipkinV2URL = fs.String("zipkin-url", "", "Enable Zipkin v2 tracing (zipkin-go) via HTTP Reporter URL e.g. http://localhost:94111/api/v2/spans")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx for making this explicit, as people have unfortunately sent v2 to the v1 endpoint in the past!

noopTracer := (*zipkinV2URL == "")
reporter := zipkinhttp.NewReporter(*zipkinV2URL)
defer reporter.Close()
zEP, _ := zipkin.NewEndpoint(serviceName, hostPort)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pronounced "zee endpoint"

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol

return func(ctx context.Context, request interface{}) (interface{}, error) {
var sp zipkin.Span
// try to retrieve Span from Go context, create new Span if not found.
if sp = zipkin.SpanFromContext(ctx); sp == nil {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this creates a span based on the context, if a server span I'd usually expect a check for some incoming remote context.. does that happen prior?

return func(c *kitgrpc.Client) {
clientBefore(c)
clientAfter(c)
clientFinalizer(c)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Easy to understand

tags: make(map[string]string),
name: "",
logger: log.NewNopLogger(),
propagate: true,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a way to doclink this to options.AllowPropagation?

// here.
span.Finish()
// send span to the Reporter
span.Flush()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flush on finalize makes a lot of sense. notes here help.

hostPort = "" // if host:port is unknown we can keep this empty
serviceName = "addsvc-cli"
)
noopTracer := (*zipkinV2URL == "")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for readability purposes I'd call it useNoopTracer. It took me a couple of seconds to realize what was the intention in line 104.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed... will update

reporter, zipkin.WithLocalEndpoint(zEP), zipkin.WithNoopTracer(noopTracer),
)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
Copy link

@jcchavezs jcchavezs Jan 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could add more context to this error. Something like

fmt.Fprintf(os.Stderr, "error when creating the zipkin tracer: %s" err.Error()).

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

@@ -17,7 +17,7 @@ type Server struct {
before []RequestFunc
after []ServerResponseFunc
errorEncoder ErrorEncoder
finalizer ServerFinalizerFunc
finalizer []ServerFinalizerFunc
Copy link

@jcchavezs jcchavezs Jan 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is line 87 still correct or we should check the len of the slice (formerly it was a pointer)?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is correct as it is not initialized when not appended to, but since len is more explicit and handles both nil and []{}I will change

@@ -76,8 +76,8 @@ func ServerErrorLogger(logger log.Logger) ServerOption {

// ServerFinalizer is executed at the end of every HTTP request.
// By default, no finalizer is registered.
func ServerFinalizer(f ServerFinalizerFunc) ServerOption {
return func(s *Server) { s.finalizer = f }
func ServerFinalizer(f ...ServerFinalizerFunc) ServerOption {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since line 93 receives two pointers (that could be modified inside the finalizer), does it make sense to specify that the order matters?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only see one being *http.Request and that one in the context of a HTTP Server handler typically isn't changed by Go devs.

serviceName = "MyService"
serviceHostPort = "localhost:8000"
zipkinHTTPEndpoint = "localhost:9411"
zipkinHTTPEndpoint = "http://localhost:9411/api/v2/spans"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

@codefromthecrypt
Copy link

codefromthecrypt commented Jan 10, 2018 via email

@basvanbeek
Copy link
Owner Author

@adriancole there is nothing used/reused from zipkin-go-opentracing. maybe confusion is because OT is wired in differently then native Zipkin...

Example HTTPServerTrace does this:

  • ServerBefore: if AllowPropagation check for incoming b3 headers
  • ServerBefore: create new server span potentially with a parent
  • ServerAfter: check if span is found (it should) and finish it
  • ServerFinalizer: check if span is found (it should), try to finish it (because ServerAfter might not fire due to error) and flush

I also wired in TraceEndpoint Middleware which wraps a Go kit endpoint (free of transport details). The service could really do without as TraceServer and TraceClient are already detailed enough.

@codefromthecrypt
Copy link

codefromthecrypt commented Jan 10, 2018 via email

@basvanbeek basvanbeek changed the title WIP: Zipkin native instrumentation using zipkin-go Zipkin native instrumentation using zipkin-go Jan 17, 2018
@basvanbeek basvanbeek merged commit 335191f into master Jan 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants