Monitoring a Flask Application with SigNoz and OpenTelemetry: A Step-by-Step Guide

Introduction

Building a web application is only the first step in software development. Once an application is deployed, understanding how it performs under real-world conditions becomes equally important. Developers need to know how quickly requests are processed, which endpoints are failing, and where latency is being introduced. While application logs provide useful information, they often lack the context needed to trace requests across different components.

This is where observability becomes valuable. Observability combines metrics, logs, and distributed traces to provide a comprehensive view of an application's health and performance. Instead of guessing why an application is slow or unreliable, developers can identify bottlenecks using real telemetry data.

In this tutorial, you'll learn how to monitor a Flask application using OpenTelemetry and SigNoz. We'll set up a simple Flask application, instrument it with OpenTelemetry, connect it to SigNoz using the OpenTelemetry Collector, and visualize metrics, traces, and logs through interactive dashboards.

By the end of this guide, you'll understand how modern observability works and how to use SigNoz to troubleshoot performance issues effectively.

Prerequisites

Before getting started, make sure you have the following installed:

  • Python 3.10 or later

  • pip

  • Docker and Docker Compose

  • Git

  • Basic familiarity with Flask and the command line


Step 1: Create a Simple Flask Application

Create a new project directory.

mkdir flask-observability
cd flask-observability

Create a virtual environment.

python -m venv venv

Activate it.

Windows

venv\Scripts\activate

Linux/macOS

source venv/bin/activate

Install Flask.

pip install flask

Create app.py.

from flask import Flask
import time

app = Flask(__name__)

@app.route("/")
def home():
    return "Hello from Flask!"

@app.route("/slow")
def slow():
    time.sleep(2)
    return "This endpoint is intentionally slow."

if __name__ == "__main__":
    app.run(debug=True)

Run the application.

python app.py

Visit:

http://localhost:5000

and

http://localhost:5000/slow

The second endpoint intentionally waits for two seconds, making it useful for demonstrating distributed tracing.

Step 2: Install OpenTelemetry Packages

Install the required instrumentation libraries.

pip install \
opentelemetry-distro \
opentelemetry-exporter-otlp \
opentelemetry-instrumentation-flask

Initialize automatic instrumentation.

opentelemetry-bootstrap -a install

OpenTelemetry automatically instruments supported libraries, allowing telemetry data to be generated with minimal code changes.

Step 3: Start SigNoz

SigNoz provides an all-in-one observability platform capable of collecting traces, logs, and metrics.

Clone the repository.

git clone https://github.com/SigNoz/signoz.git

Move into the deployment directory.

cd signoz/deploy

Start the platform.

docker compose up -d

Docker downloads the required containers, including:

  • SigNoz frontend

  • OpenTelemetry Collector

  • ClickHouse database

  • Query service

After the containers finish starting, open your browser.

http://localhost:3301

You should see the SigNoz dashboard.

Step 4: Instrument the Flask Application

Return to the Flask project.

Instead of starting Flask normally, run it through OpenTelemetry.

OTEL_SERVICE_NAME=flask-demo \
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \
opentelemetry-instrument \
python app.py

This command performs three important tasks.

First, it assigns a service name.

Second, it exports telemetry to the OpenTelemetry Collector.

Finally, it automatically instruments the Flask application.

No manual tracing code is required.

Step 5: Generate Traffic

Open another terminal.

Use curl to generate requests.

curl http://localhost:5000/

Run several slow requests.

curl http://localhost:5000/slow

Or use a loop.

for i in {1..20}
do
curl http://localhost:5000/slow
done

These requests generate telemetry data that will appear inside SigNoz.

Step 6: Explore Traces

Open the SigNoz dashboard.

Navigate to:

Traces

You should now see traces being collected.

Selecting a trace displays a waterfall view showing the duration of every operation involved in processing the request.

The /slow endpoint should clearly appear with a significantly longer execution time than the root endpoint.

This visualization makes identifying performance bottlenecks straightforward.

Insert Screenshot Here: Trace waterfall for the /slow endpoint.

Step 7: Monitor Metrics

Next, open the Metrics Explorer.

Several useful metrics are collected automatically.

These include:

  • Request count

  • Request duration

  • Error rate

  • Throughput

  • CPU usage

  • Memory usage

Instead of relying solely on logs, developers can immediately determine whether an application is slowing down over time or experiencing spikes in traffic.

Useful charts to observe include:

  • Average response time

  • Requests per second

  • Error percentage

  • Latency distribution

Insert Screenshot Here: Metrics dashboard showing request latency.


Step 8: Correlate Logs with Traces

One of the most useful features of observability is correlation.

Rather than searching through thousands of log entries, developers can navigate directly from a trace to its related logs.

When trace identifiers are included in application logs, debugging becomes significantly faster.

For example, if a request takes five seconds to complete, developers can immediately inspect the associated logs without manually searching through timestamps.

This dramatically reduces troubleshooting time.

Step 9: Simulate an Error

Modify the Flask application.

@app.route("/error")
def error():
    raise Exception("Intentional Error")

Restart the application.

Visit:

http://localhost:5000/error

SigNoz records the failed request.

Inside the traces view, failed requests are highlighted, allowing developers to distinguish successful requests from failing ones immediately.

The error information includes stack traces and timing information that help identify the root cause.


Step 10: Understanding the Data

At this point, three different types of telemetry are being collected.

Metrics

Metrics provide numerical measurements over time.

Examples include:

  • CPU utilization

  • Memory usage

  • Average response time

  • Request count

Metrics are excellent for identifying trends.


Logs

Logs capture detailed events occurring inside an application.

Examples include:

  • Exceptions

  • Debug messages

  • Authentication events

Logs explain what happened.


Traces

Distributed traces follow a request throughout its lifecycle.

They answer questions such as:

  • Which function was slow?

  • Which database query consumed the most time?

  • Which service introduced latency?

Traces explain where the time was spent.

Combining all three provides complete observability.


Best Practices

When implementing observability in production, consider the following recommendations:

  • Assign meaningful service names.

  • Instrument applications as early as possible.

  • Use structured logging.

  • Correlate logs with traces.

  • Monitor latency instead of relying only on CPU usage.

  • Create dashboards for your most critical APIs.

  • Configure alerts for high error rates and increasing response times.

  • Regularly review traces to identify performance regressions.

These practices improve application reliability while reducing the time required to diagnose production issues.


Common Issues

No telemetry appears

Verify that the OpenTelemetry Collector is running and that the endpoint is configured correctly.


No traces

Ensure the application is launched using:

opentelemetry-instrument

instead of:

python app.py

Docker containers fail

Check container status.

docker ps

Review logs.

docker logs <container_name>

Conclusion

Observability is no longer limited to large-scale distributed systems. Even a simple Flask application benefits from collecting metrics, traces, and logs. By combining OpenTelemetry with SigNoz, developers gain real-time visibility into application performance without making significant changes to their codebase.

Throughout this tutorial, we created a basic Flask application, enabled automatic instrumentation with OpenTelemetry, connected it to SigNoz, generated traffic, explored distributed traces, monitored application metrics, correlated logs with traces, and simulated application errors. Together, these capabilities provide a practical foundation for diagnosing issues, understanding system behavior, and improving application reliability.

As applications grow in complexity, investing in observability early helps teams spend less time troubleshooting and more time building reliable software. Whether you're developing personal projects or production-grade services, integrating OpenTelemetry and SigNoz can significantly improve your ability to monitor, analyze, and optimize your applications.

Comments