Getting started with Observability using SigNoz 🔭

You’ve faced mysterious slowdowns and downtime in your application. Logs are scattered, metrics are basic, and you’re still left guessing what parts of your code are failing. Observability solves this by bringing together traces, metrics, and logs in a single view. With OpenTelemetry and SigNoz, you can set this up quickly and self-host your data for full control.

Install SigNoz via Docker Compose 💿

SigNoz is an open-source observability platform that’s perfect for this job, and it’s easy to deploy locally using Docker. Make sure you’re on a server or local machine with Docker installed and at least 4 GB of memory allocated to Docker, this ensures all required services can run smoothly without resource errors. Begin by opening your terminal and running:

git clone -b main https://github.com/SigNoz/signoz.git && cd signoz/deploy/
cd docker
docker compose up -d --remove-orphans

This will pull all the required images (if not already present) and spin up multiple coordinated containers, each serving a part of the observability platform, such as the UI, collector, storage database (clickhouse in this case), and query service. Verify containers are running:

docker ps

You should see containers like signoz/signoz-otel-collector, signoz/clickhouse-server, and signoz/signoz. Next, open your browser and visit:

http://localhost:8080

You should see the SigNoz dashboard ready to receive and visualise trace data from your instrumented applications. If anything doesn’t work as expected, for example, if containers fail to start or the UI isn’t accessible, be sure to consult the dedicated Signoz documentation for detailed troubleshooting and setup guidance.

Build a Simple Node.js Dice App 🎲

Before you can add tracing to your application, you’ll need something to instrument, and for this purpose, a simple dice roller service is perfect. It’s lightweight & easy to understand. The idea is to build a small Node.js server using the popular Express framework, which will respond to HTTP requests by returning random dice roll results. This gives us a nice, testable endpoint that we can later trace with OpenTelemetry. Create a folder for your project:

mkdir dice-app
cd dice-app
npm init -y
npm install express

Now that you have your project set up, you’ll want to create your actual application code. Make a new file in this folder named app.js, and save the following code into it:

const express = require('express');
const app = express();
const PORT = 3000;

app.get('/rolldice', (req, res) => {
  const rolls = parseInt(req.query.rolls) || 3;
  const results = Array.from({ length: rolls }, () =>
    Math.floor(Math.random() * 6) + 1
  );
  res.json(results);
});

app.listen(PORT, () => {
  console.log(`Server listening at http://localhost:${PORT}`);
});

Now we will run the application using the command below:

node app.js

You should see the message “Server listening at http://localhost:3000” confirming that it’s up and running. To test it, you can use your browser or a command-line tool like curl. For example, try running:

curl "http://localhost:3000/rolldice?rolls=5"

This sends a GET request to your server asking for 5 dice rolls. The server will respond with a JSON array of 5 random numbers between 1 and 6, simulating the roll of 5 dice. This is a simple but effective way to demonstrate a working service that can generate meaningful traffic.

Add OpenTelemetry Packages 📦

You now want automatic tracing. Install the needed OpenTelemetry libraries. These OpenTelemetry packages let you add tracing to your Node.js app: @opentelemetry/sdk-node is the core SDK to set up and manage tracing, @opentelemetry/auto-instrumentations-node automatically captures spans from popular Node.js libraries with minimal setup, and @opentelemetry/exporter-trace-otlp-proto sends collected trace data in the OTLP (protobuf) format to backends like the OpenTelemetry Collector or observability platforms. Use the following command:

npm install \
  @opentelemetry/sdk-node \
  @opentelemetry/auto-instrumentations-node \
  @opentelemetry/exporter-trace-otlp-proto

Configure Tracing ⚙️

This code sets up OpenTelemetry tracing in a Node.js app by creating a NodeSDK instance configured to automatically capture spans from common libraries (like HTTP and Express). Create tracing.js in your root folder, where the dice roll app exists, with the following content:

const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-proto');

const exporter = new OTLPTraceExporter({
  url: 'http://localhost:4318/v1/traces'
});

const sdk = new NodeSDK({
  traceExporter: exporter,
  instrumentations: [getNodeAutoInstrumentations()],
  serviceName: 'signoz-demo-dice-app'
});

sdk.start();

We capture spans from common libraries using getNodeAutoInstrumentations(), and to export those spans to an OTLP-compatible backend (like the OpenTelemetry Collector or SigNoz) at http://localhost:4318/v1/traces using the OTLPTraceExporter. By calling sdk.start() we initialise the tracer, enabling end-to-end tracing of requests in the signoz-demo-dice-app service for performance monitoring and debugging. This sets the service.name attribute for all traces, helping SigNoz group telemetry under “signoz-demo-dice-app”

Start the App with Tracing 🏁

OpenTelemetry must load before your application logic. To confirm so, run:

node --require ./tracing.js app.js

This command makes sure the tracing setup runs first by pre-loading tracing.js, so when app.js starts, tracing is already enabled for the whole app.

Send Some Test Traffic 🚦

To see tracing in action, we generate a few HTTP requests to our running app using these curl commands:

curl "http://localhost:3000/rolldice?rolls=10"
curl "http://localhost:3000/rolldice?rolls=2"
curl "http://localhost:3000/rolldice"

Each command simulates a user accessing the /rolldice endpoint on your server (running locally on port 3000). The optional rolls query parameter tells the app how many dice rolls to simulate.

View Data in the SigNoz Dashboard 📊

In SigNoz, you can now visualise these traces in the UI, analyse the duration and flow of requests, identify performance bottlenecks, or spot errors. This automatic capture ensures you don’t need to manually add tracing code for basic HTTP interactions; it just works out of the box once your instrumentation is set up. Return to:

http://localhost:8080

Navigate to the Traces tab. Under Traces, you can inspect details like timestamps, durations, and spans that show how each request flowed through your service.

You can view the Services. In this, you should now see “signoz-demo-dice-app” listed. Selecting our service from the panel will help you view a graphical representation of Latency, Rate, Apdex, Key Operations, etc.

Troubleshooting Checklist ✅

SymptomWhat to Check
Only see unknown_service:nodeMake sure you started the app with --require ./tracing.js
No traces showing upEnsure SigNoz Collector is reachable at localhost:4318 and app logs show no errors. Also, make sure OTel environments are being exported correctly; if not, try adding them manually as export OTEL_TRACES_EXPORTER=console
SigNoz containers failing to startCheck Docker logs signoz-clickhouse for resource or startup errors

What’s Next? 🤔

Once you have basic tracing set up, you can further enhance your observability by adding metrics using the OpenTelemetry Metrics SDK to monitor things like request counts and latencies; capturing and correlating logs alongside traces for full context during debugging; deploying in a secure setup with authentication and encryption to protect your telemetry data; and adding custom spans in your code (for example, to trace critical workflows like a credit card payment process) to get deep, business-specific visibility into your application’s behavior.

Resource for You! 📚

Thanks for Reading ❤️

This setup sets the anchor for robust observability. From here, you can evolve your tracing, logs, metrics, and even multi-service pipelines, all with SigNoz as your single source of truth. I hope this walkthrough made the setup process clear and approachable. If you found this helpful, consider sharing it with your team so everyone can benefit from improved observability practices.

1
Subscribe to my newsletter

Read articles from Kaiwalya Koparkar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kaiwalya Koparkar
Kaiwalya Koparkar

I am Kaiwalya Koparkar, founder of Geek Around Community, a GitHub Campus Expert, MLH Coach, Open-Source Advocate & DevRel. I work as a Program Manager/ Community Manager in several communities. I love to speak at sessions, workshops, meetups, and conferences. In the past year, I have won over 10+ hackathons and mentored/judged/participated in over 35+ global hackathons.