TracesMetricsApp LogsCustom LogsProfiling
✖️✖️

This guide walks you through setting up Application Performance Monitoring (APM) on a Node.js application. These instructions can also be found on the Installation page in your Middleware Account. View example code here.

Prerequisites

1

Infra Agent

Infrastructure Agent (Infra Agent). To install the Infra Agent, see our Installation Guide.

2

Node.js Version

Node.js version 18.17.1 or above. Check your Node.js version with the following command:

bash
node --version
3

Python Version

Python version 3.8 or above. Check your Python version with the following command:

bash
python3 --version

Install

Step 1: Install Node.js APM Package

Run the following command in your terminal:

bash
npm install @middleware.io/node-apm --save

Step 2: Initialize Tracker

Add the following lines to the beginning of your application code base. The access token is your account key, which can be found on the Installation page.

Node.js
const tracker = require('@middleware.io/node-apm');
tracker.track({
    serviceName: "your-service-name",
    accessToken: "<xxxxxxxxxx>"
});

Step 3: Container Variables

Docker

Applications running in a container require an additional environment variable. If your application is not running in a container, move to Step 4.

For Docker containers, add the following environment variable to your application.

bash
MW_AGENT_SERVICE=<DOCKER_BRIDGE_GATEWAY_ADDRESS>
The DOCKER_BRIDGE_GATEWAY_ADDRESS is the IP address of the gateway between the Docker host and bridge network. This is 172.17.0.1 by default. Learn more about Docker bridge networking here

Kubernetes

bash
kubectl get service --all-namespaces | grep mw-service

Then add the following environment variable to your application deployment YAML file.

bash
MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local

Step 4: Capture Application Data

Traces

Distributed tracing is automatically enabled upon completion of Step 2.

Custom Logs

To ingest custom logs into Middleware, utilize the following functions inside your logging method based on desired log severity levels.

Node.js
tracker.info('Info sample');
tracker.warn('Warning sample');
tracker.debug('Debugging Sample');
tracker.error('Error Sample');

To add stack traces along with the error log, use the following error tracking function.

Node.js
tracker.error(new Error('Error sample with stack trace'));

Custom Metrics and Spans

Create custom instruments and spans by exposing the meter and tracer with the following pattern:

Node.js
const express = require("express");
const app = express();
const tracker = require("@middleware.io/node-apm");

// Initialize the tracker
tracker.track({
  // Service name differentiates your applications in the APM section of the Middleware platform.
  serviceName: "<your_service_name_here>",
  // You can find your access token in the Middleware platform by going to the installation page.
  accessToken: "<your_key_here>",
  // The target is your Middleware platform URL.
  // When you login to the Middleware platform, you can find your target URL in the URL bar.
  target: "<your_mw_url_here>",
});

// Create a tracer, used to create spans.
const tracer = tracker.getTracer();

// Create a meter, used to create custom metrics.
const meter = tracker.getMeter();

// Create a counter metric.
// For a list of other metric types, see the opentelemetry metrics API
// documentation. (https://opentelemetry.io/docs/specs/otel/metrics/api/)
let counter = meter.createCounter("health-check-counter");

/**
 * Generate a random integer between 0 and the range provided.
 * @param {Number} range
 * @returns {Number}
 */
function randInt(range) {
  // Create a span. A span must be closed.
  return tracer.startActiveSpan("randInt", (span) => {
    const randomInt = Math.floor(Math.random() * range);
    // Be sure to end the span
    span.end();
    return randomInt;
  });
}

app.get("/randInt", (req, res) => {
  // Calling the randInt function will generate a span.
  const randomInt = randInt(100);
  res.json({ number: randomInt });
});

app.get("/health", (req, res) => {
  // Increment the health-check-counter by 1.
  counter.add(1);
  res.json({ status: "ok" });
});

app.listen(5051, () => {
  console.log("Server is running on port 5051");
});

Profiling

Application Profiling is auto-configured upon completing Step 2.

Stack Traces

Use the errorRecord method to record a stack trace when an error occurs. See an example of this method below.

Node.js
app.get('/error', function (req, res) {
    try{
        throw new Error('oh error!');
    }catch (e) {
    track.errorRecord(e)
    }
    res.status(500).send("wrong");
}); 

Continuous Profiling

Continuous profiling captures real-time performance insights from your application to enable rapid identification of resource allocation, bottlenecks, and more. Navigate to the Continuous Profiling section to learn more about using Continuous Profiling with the Node.js APM.

Troubleshooting

node-gyp Failing/Missing Dependencies

If node-gyp fails to build or your infrastructure is missing dependencies, run the following command:

Shell
sudo apt-get build-dep build-essential
sudo apt-get install gcc
sudo apt-get install g++
sudo apt-get install make

Running Apps on Docker

If you are unable to run your Node.js app on Docker, open port 9319 locally to enable proper firewall configurations.

Need assistance or want to learn more about Middleware? Contact us at support[at]middleware.io.