Automatic Instrumentation and OpenTelemetry | Tutorial

January 6, 2022

You already know OpenTelemetry can help you monitor your application, so now it’s time to automate your instrumentation. This tutorial walks you through setting up OpenTelemetry and Zipkin.

Kovid Rathee
Data & Infrastructure Engineer

Application observability is one of the most important keys for solving performance, security, governance, scalability, and availability problems. You can improve your app’s observability with instrumentation, specifically in two different ways:

  1. Manual instrumentation, where you create telemetry data by creating traces and metric events using the tracer and meter objects.
  2. Automatic instrumentation where you don’t have to make any changes in your application code to send telemetry data.

OpenTelemetry is the de facto open standard for instrumentation. Its automatic instrumentation packages make it easier for developers to enable instrumentation for their application. OpenTelemetry also makes the instrumentation consistent throughout the application, making it much easier for developers and testers to debug any issues that might come up.

Let’s run through a short tutorial about using automatic instrumentation simply by including some boilerplate tracer code in your application. We’ll leave the rest to the wide range of libraries that support automatic instrumentation in OpenTelemetry.

Currently, OpenTelemetry supports automatic instrumentation for DNS, Express.js, GraphQL, MongoDB, PostgreSQL, MySQL, and Redis, among many more. You can check the complete list in the npm registry.

What Is Automatic Instrumentation?

Traditionally, tracing has meant manually adding checkpoints in the code to send data after making an HTTP call, producing a message, writing to the database, and so on. When instrumenting a service, you create spans by invoking any methods defined in the service. (A span) is just some information about the service event along with some metadata.

While you can use manual instrumentation, automatic instrumentation gives you a great chance to save up code changes in your application. It allows for instrumentation just by using an intelligent agent that reads the application activity and extracts traces by building spans and capturing relevant metadata.

Implementing Automatic Instrumentation

Automatic instrumentation is beneficial in several ways:

  • You can set it up within just a few minutes.
  • It’s a great starting point for you to observe your application and look at issues that matter.
  • Once the observability baseline is set up, you can figure out any custom instrumentation you might want.

The baseline approach is a good way to get started; that way, at least a large chunk of the application is consistently observable and isn’t dependent on any custom changes.

Let’s dive in.

Sample application
Sample application

This is a sample application that deploys a mock Express.js server along with a mock client to send requests to the server. OpenTelemetry is used to build in automatic instrumentation for this app. Zipkin is used to expose the instrumentation data via the browser.

Clone the Repository

You can implement automatic instrumentation in your application by using the official OpenTelemetry API or SDKs by integrating them into your application. To follow along, start by cloning the following repository:

git clone

This repository contains a demo app with an Express.js server and a client that makes requests to the server.

The intent is to get instrumentation data using OpenTelemetry for every request that comes through. This app uses some of the supported instrumentations and exporters for Node.js specified in the OpenTelemetry documentation.

To set up the demo app, please follow the instructions provided in the ReadMe document of the aforementioned repository.

Setting Up Zipkin

Now, there are several ways that you could look at the instrumentation data:

  • Using the command line.
  • Using one of the many open-source tools
  • Using a proprietary one

In this article, we’ll use Zipkin to search and visualize traces from the captured instrumentation data.

If you already have an application that uses another interface for search and visualization, such as ContainIQ, Prometheus, Splunk, Dynatrace, DataDog and so on, you can install the relevant exporter in your app. It will be a minor change, as OpenTelemetry supports a wide range of exporters out-of-the-box. You can find the complete list of exporters here.

You also need to install exporter dependencies in your application to export the collected data in a certain format. Once you start Zipkin and install the relevant dependencies, you can log onto <terminal inline>http://localhost:9411<terminal inline> and look at the instrumentation data for your app.

Use the following command to start Zipkin:

docker run -d -p 9411:9411 openzipkin/zipkin

If you’re not using Docker, you can always build Zipkin from source or deploy using the binaries.

Configure the OpenTelemetry API and SDK

To enable automatic instrumentation for your app, install dependencies for the OpenTelemetry API and SDK. Although you can configure the data source, exporter, etc., to get started, the only mandatory thing to configure is a service name. This signifies the name of the service you are instrumenting.

In addition to the core packages and dependencies, the following dependencies are pre-installed to take care of automatic instrumentation in the demo app:

You can choose the packages for automatic instrumentation that your app needs for increased observability from the official npm documentation.

The demo app also contains a <terminal inline>tracer.js<terminal inline> file that you need to run just before running any other piece of code that needs to be instrumented. The logic for exporting the data for Zipkin’s consumption is also written here. You can choose to have specific tracers for more custom use cases.

However, for the sake of consistency, it’s a good practice to reuse the tracer code as much as possible.

Run the Demo App

To run the app, start the Express.js server that will run on port <terminal inline>8080<terminal inline>. In a separate tab, run the following command to start the client, which will send mock HTTP requests to the Express.js server.

cd opentelemetry-express-zipkin
npm run server

The <terminal inline>sendRequest<terminal inline> method will be called ten times at an interval of one second each. To see the data, log onto your Zipkin server and look into any of the traces.

When you look at one of the traces, notice how OpenTelemetry has automatically instrumented your data by creating several spans intelligently. Here’s an image of a sample trace from the demo app:

Example trace with span visualization in Zipkin
Example trace with span visualization in Zipkin

In the next image, look at the <terminal inline>post /movies<terminal inline> span along with all the details that have been captured for this stage of the request. If you were instrumenting your application using manual instrumentation, you’d have to define the spans yourself. Here, you just have to provide the name of the service.

Example metadata for a span
Example metadata for a span

Visualization is just one part of the offering here. You can also aggregate the trace metrics and extract insights such as what percentile of requests are being served within 100 ms. Wherever there’s a skew, you can drill down and investigate particular requests and figure out what component of the app is taking time.

Properly presented telemetry data gives you a complete view of what’s happening with your application, so you’ll be able to detect, verify, and debug issues quickly and effectively.

Final Thoughts

Instrumentation sits at the core of the observability of your application. Having a well-observed application gives you great insights that enable you to improve performance, remove bottlenecks, and fix issues. This article showed you how to add automatic instrumentation to an Express.js app using the OpenTelemetry API and SDK without any hassle.

If you’ve built your app in another framework, head over to the official documentation for guidance.

The end goal of setting up instrumentation is to solve the observability problem. If you have a workload orchestrated by Kubernetes, ContainIQ is an observability platform that can help you observe the metrics, latencies, events, and logs captured by Kubernetes while also creating dashboards for monitoring purposes.

Article by

Kovid Rathee

Data & Infrastructure Engineer

Kovid is a Data & Infrastructure Engineer working as a Senior Consultant at Servian in Melbourne, Australia. In a career spanning over 10 years, he has worked for startups and corporates, product companies and service companies alike. Kovid started his career as an Assistant Professor at an engineering college and later moved to a full stack developer role, before finally moving into the data space where he has been working for the past 8 years. In his spare time, Kovid enjoys writing about data engineering, infrastructure-as-code, DevOps, and SRE.

Read More