Tracing Express services with zipkin-js

Roman Coedo
Trabe
Published in
4 min readJul 8, 2019
Photo by Marten Bjork

In the last few years the microservice architecture pattern has become mainstream. The pattern solves many problems of the monolithic architecture design but has some drawbacks, one of the biggest being how hard it is to debug the system as a whole.

One of the best tools you can have in your belt when you are dealing with microservices is distributed tracing. Distributed tracing lets you know what is happening in your system and which parts are involved, even in production.

In this article we are going to build a couple of Express microservices and use zipkin-js to trace them. You will need:

Also, a github repo with the full example can be found here.

Getting our zipkin instance up

Put this code into a docker-compose.yml file and get the instances up with the docker-compose up command. Two containers will be created: a mysql database for storage and zipkin itself.

Building an Express microservice

Our starting point is going to be a plain Express service. Our service has a /time endpoint that sends a JSON with the current date.

To start tracing our Express app with zipkin-js we need some extra libraries. We are going to use zipkin-instrumentation-express and zipkin-transport-http. The former is an Express middleware and the latter is a transport to send the traces to zipkin via HTTP.

It may seem like a lot of code but actually we are just creating a Tracer instance and adding the zipkin middleware to the Express app. The tracer can be configured using the constructor parameters but we are not getting into these details for this example.

This is all that is needed to get tracing working. If we now make a request to localhost:3001/time a trace will be sent to our zipkin endpoint. Something similar to this should appear in our zipkin-ui atlocalhost:9411/zipkin/:

And if we click the trace, we get a detailed view of it:

Communication between services

Things start to get more interesting when we have more than one service interacting. We are going to write a new service which is going to request the current date to our date service and then use the result to render some HTML.

We are going to use axios as our HTTP client to make the request and pug to render our template. To get axios working with zipkin we need to instrument it. We can do this with the zipkin-instrumentation-axios library.

The code for the service should look like this:

The code for the service looks familiar. It is pretty much the same we did before. We create a new Tracer instance and we add the middleware to the service. We instrument the axios client with the Tracer instance and a name for the client.

Now, if we get both services up and make a request to localhost:3000 we can see a trace like this in our zipkin-ui:

The instrumented HTTP client is forwarding some headers telling the date service “Yo! we are being traced and this is the trace identifier, attach your stuff to it!”. When the date service receive these headers, instead of creating a new trace, it just attaches a span to the existing one.

Tracing local operations

We can make our traces more informative by tracing local operations done in the services. In our example we don’t really have local operations worth tracing, so we are going to add some delays and trace these instead, just to see how it works.

If we make a request to our web service the trace will look like this:

New spans are attached for our local operations and we can now understand what is happening in our services just by looking at the trace.

Pretty neat, right?

--

--