Auto Instrumentation of a Sample Node.js Application

Instrumentation is adding code to your program to collect data and insights to check how it operates. You can use this data to enhance the overall user experience and find performance bottlenecks. One method for instrumenting your application is using OpenTelemetry, an open-source framework for gathering, analyzing, and exporting telemetry data. This article will demonstrate Auto Instrumentation of a sample Node.js application.

What is OpenTelemetry

OpenTelemetry (also known as OTEL or OTel) is an observability framework that includes software and tools for creating and capturing telemetry data from cloud-native software.

OpenTelemetry provides a uniform format for instrumenting, creating, gathering, and exporting application telemetry data for monitoring platforms for analysis, namely metrics, logs, and traces.

Major components of OpenTelemetry are:

  • APIs and SDKs are available for each programming language to generate and emit telemetry.
  • Collector component for receiving, processing, and exporting telemetry data.
  • OTLP protocol for telemetry data transmission

We will look into each of these components one by one. 

API and SDKs

OpenTelemetry provides a single API and a single SDK (an OpenTelemetry client library) for any programming language, allowing you to instrument your application to create metrics and trace data manually.

The standard API ensures no code modifications are required when shifting between SDK implementations.

The SDK handles sampling, context propagation, and other necessary processing before exporting the data, often to OpenTelemetry Collector (see below). OpenTelemetry SDKs can transport data to different destinations by using a suite of SDK exporters that support multiple data formats.

Collector

The Collector receives processes and exports telemetry data to one or more backends. It is intended to be universal, allowing it to function with various open-source and commercial systems. The figure below shows the different components of the Collector:

There are three parts to the Collector:

  • Receiver 

The receiver determines how information is gathered: either by pushing information to the Collector at regular intervals or extracting it just when needed. The receiver can compile information from other sources if necessary.

  • Processor 

The processor carries out intermediary processes, such as batching and metadata addition, to prepare the data for export.

  • Exporter

Depending on the user specifications, the exporter delivers the telemetry data to an open-source or commercial backend. The exporter can push or pull this data, just like the receiver.

Implementing OpenTelemetry for use with TelemetryHub

To Implementing OpenTelemetry for use with TelemetryHub, you need to follow the following steps:

  1. Create an account on Telemetry Hub
  2. After creating your account, you will be redirected to a dashboard screen containing a menu pane on the left. In that menu pane, head to the Settings menu. 

This will lead you to the settings menu page:

In this settings menu, click on the “Manage” button. This will redirect you to a new page like this:

This page shows some of the already created Ingest Keys. We will create a new Key for our application by clicking the “Create Ingest Key” button on the right. This will open up a popup menu like this:

You must give your application’s name and click “Create Ingest Key”. We created an app with the name “sample_app”

  1. After configuring your OpenTelemetry account, you can create a sample application that we will use to get tracing data. 
  2. We have created a simple Node.js application in which we create a server and send a request to that server. This server then sends a response in JSON format giving a message of “Hello World”. The code below demonstrates this concept:
var http = require(‘http’); // 1 – Import Node.js core module

var server = http.createServer(function (req, res) {   // 2 – creating server

    if (req.url == ‘/’) { //check the URL of the current request

        // set response header

        res.writeHead(200, { ‘Content-Type’: ‘application/json’ });

        // set response content    

        res.write(JSON.stringify({ id:1,message: “Hello World”}));

        res.end();

   

    }

});

server.listen(5500); //3 – listen for any incoming requests

console.log(‘Node.js web server at port 5500 is running..’)

 

  1. The next step is to install all the required dependencies that will be required to use OpenTelemetry. These packages can be installed using the npm command:
npm install –save \

    @opentelemetry/api \

    @opentelemetry/auto-instrumentations-node \

    @opentelemetry/exporter-trace-otlp-proto \

    @opentelemetry/resources \

    @opentelemetry/sdk-node \

    @opentelemetry/sdk-trace-node \

    @opentelemetry/semantic-conventions

  1. After installing the packages, create a new “tracing.js” file and write the following code to import all the required OpenTelemetry packages:
const opentelemetry = require(“@opentelemetry/sdk-node”);

const {

  getNodeAutoInstrumentations

} = require(“@opentelemetry/auto-instrumentations-node”);

const {

  Resource

} = require(“@opentelemetry/resources”);

const {

  OTLPTraceExporter

} = require(“@opentelemetry/exporter-trace-otlp-proto”);

const {

  NodeTracerProvider

} = require(“@opentelemetry/sdk-trace-node”);

const {

  SemanticResourceAttributes,

} = require(“@opentelemetry/semantic-conventions”);

const {

  BatchSpanProcessor

  // ConsoleSpanExporter

} = require(“@opentelemetry/sdk-trace-base”);

 

  1. Next, configure the Exporter providing the Ingest key created at step 2. 
const OTLPoptions = {

    url: “https://otlp.telemetryhub.com/v1/traces”,

    headers: {

      “x-telemetryhub-key”: “YOUR_INGEST_KEY”

    },

  };

const otlpExporter = new OTLPTraceExporter(OTLPoptions);

 

  1. Now, provide the name of the application you created on your TelemetryHub account. You can add additional attributes as required. 
const provider = new NodeTracerProvider({

    resource: new Resource({

      [SemanticResourceAttributes.SERVICE_NAME]: “sample_app”,

    }),

});

 

  1. Now we need to send the created spans using the configured Exporter. This is done using the following function:

 

provider.addSpanProcessor(new BatchSpanProcessor(otlpExporter));

provider.register();

 

  1. The last step is to create and start the SDK to send the instrumentation data and get the traces on the TelemetryHub. 
const sdk = new opentelemetry.NodeSDK({

    traceExporter: otlpExporter,

    instrumentations: [getNodeAutoInstrumentations()],

  });

sdk.start()

 

Here is the complete code for “tracing.js”:

const opentelemetry = require(“@opentelemetry/sdk-node”);

const {

  getNodeAutoInstrumentations

} = require(“@opentelemetry/auto-instrumentations-node”);

const {

  Resource

} = require(“@opentelemetry/resources”);

const {

  OTLPTraceExporter

} = require(“@opentelemetry/exporter-trace-otlp-proto”);

const {

  NodeTracerProvider

} = require(“@opentelemetry/sdk-trace-node”);

const {

  SemanticResourceAttributes,

} = require(“@opentelemetry/semantic-conventions”);

const {

  BatchSpanProcessor

  // ConsoleSpanExporter

} = require(“@opentelemetry/sdk-trace-base”);

const OTLPoptions = {

    url: “https://otlp.telemetryhub.com/v1/traces”,

    headers: {

      “x-telemetryhub-key”: “c7ce98dc-d0c8-49ef-99d1-f734985ed0f8:ca86b7c8-9aea-4339-9d75-bfbc312be5f5:184580c”

    },

  };

const otlpExporter = new OTLPTraceExporter(OTLPoptions);

const provider = new NodeTracerProvider({

    resource: new Resource({

      [SemanticResourceAttributes.SERVICE_NAME]: “sample_app”,

    }),

});

provider.addSpanProcessor(new BatchSpanProcessor(otlpExporter));

provider.register();

const sdk = new opentelemetry.NodeSDK({

    traceExporter: otlpExporter,

    instrumentations: [getNodeAutoInstrumentations()],

  });

sdk.start()

 

Run the test app using the following command:

$ node –require ‘./tracing.js’ yourApp.js

In your browser URL bar, hit localhost:5500.  You should see the response like this:

To monitor the trace data, open your Telemetry Hub account. The first page shows you the traces and logs data. Since we haven’t created any logs and metrics, so it will show only traces data. 

The green boxes in the traces indicate the request trace. Pointing on any of the boxes shows the information about that particular trace. 

If we click on the “Traces” menu from the left pane, we can see the individual traces created by the application and drill into the spans, in addition to seeing the performance charts, histogram, and insights.

Conclusion

Using OpenTelemetry to instrument your JavaScript application is useful for learning more about how the application behaves and performs. OpenTelemetry offers a consistent way to instrument your whole stack and gain end-to-end visibility into your system with support for numerous languages and frameworks. You can use OpenTelemetry to instrument your own JavaScript applications and acquire useful insights into their behavior by following the instructions provided in this article.