Monitoring Django with OpenTelemetry and Uptrace
Tags: monitoring, programming, python, django
Published: 2022-11-23 14:47:24

Still using Jaeger/Sentry? Uptrace is an open-source APM tool that supports distributed tracing, metrics, and logs. You can use it to monitor applications and set up automatic alerts to receive notifications via email, Slack, Telegram, and more.

![Uptrace distributed tracing tool](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0smxxm3aa4t6yvqiiy36.png)

---

## What is tracing?

[Distributed Tracing](https://uptrace.dev/opentelemetry/distributed-tracing.html#what-is-tracing) allows you to see how a request progresses through different services and components, timings of every operation, any logs and errors as they occur. In a distributed environment, tracing also helps you understand relationships and interactions between distributed micro-services and systems.

![Distributed tracing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fmm95e3niz8jive6t476.png)

Using tracing, you can break down requests into [spans](https://uptrace.dev/opentelemetry/distributed-tracing.html#spans). **Span** is an operation (unit of work) your app performs handling a request, for example, a database query or a network call.

**Trace** is a tree of spans that shows the path that a request makes through an app. Root span is the first span in a trace.

![Spans and trace](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khnbmqbvyt6ph1m58iq7.png)

To learn more about tracing, see [Distributed tracing using OpenTelemetry](https://uptrace.dev/opentelemetry/distributed-tracing.html).

## What is OpenTelemetry?

[OpenTelemetry](https://uptrace.dev/opentelemetry/) is an open-source observability framework hosted by Cloud Native Computing Foundation. It is a merger of OpenCensus and OpenTracing projects.

OpenTelemetry aims to provide a single standard across all types of observability signals such as [OpenTelemetry tracing](https://uptrace.dev/opentelemetry/distributed-tracing.html) and [OpenTelemetry metrics](https://uptrace.dev/opentelemetry/metrics.html).

OpenTelemetry specifies how to collect and send telemetry data to backend platforms. With OpenTelemetry, you can instrument your application once and then add or change vendors without changing the instrumentation.

OpenTelemetry is available for most programming languages and provides interoperability across different languages and environments.

## Creating spans

To measure performance of database queries or HTTP requests, you can create a span using OpenTelemetry Python API:

```python
from opentelemetry import trace

tracer = trace.get_tracer("app_or_package_name", "1.0.0")

def some_func(**kwargs):
    with tracer.start_as_current_span("some-func") as span:
        // the code you are measuring
```

To record contextual information, you can annotate spans with [attributes](https://uptrace.dev/opentelemetry/distributed-tracing.md#attributes). For example, an HTTP endpoint may have such attributes as `http.method = GET` and `http.route = /projects/:id`.

```python
# To avoid expensive computations, check that span is recording
# before setting any attributes.
if span.is_recording():
    span.set_attribute("http.method", "GET")
    span.set_attribute("http.route", "/projects/:id")
```

You can also record exceptions and set the span status code to indicate an error:

```python
except ValueError as exc:
    # Record the exception and update the span status.
    span.record_exception(exc)
    span.set_status(trace.Status(trace.StatusCode.ERROR, str(exc)))
```

See [OpenTelemetry Python tracing](https://uptrace.dev/opentelemetry/python-tracing.html) for details.

## What is Uptrace?

Uptrace is an open source [DataDog competitor](https://uptrace.dev/blog/datadog-competitors.html) with an intuitive query builder, rich dashboards, alerting rules, and integrations for most languages and frameworks. It can process billions of spans and metrics on a single server and allows to monitor your applications at 10x lower cost.

Uptrace uses ClickHouse database to store traces, metrics, and logs. You can use it to monitor applications and set up automatic alerts to receive notifications via email, Slack, Telegram, and more.

## Example application

In this tutorial, you will be instrumenting a [toy app](https://github.com/uptrace/uptrace/tree/master/example/django) that uses Django and PostgreSQL database client. You can retrieve the source code with the following command:

```shell
git clone git@github.com:uptrace/uptrace.git
cd example/django
```

The app comes with some dependencies that you can install with:

```shell
pip install -r requirements.txt
```

Then you can run migrations to initialize the database:

```shell
./manage.py migrate
```

## Configuring OpenTelemetry

Uptrace provides [OpenTelemetry Python](https://uptrace.dev/get/opentelemetry-python.html) distro that configures OpenTelemetry SDK for you. To install the distro:

```shell
pip install uptrace
```

Then you need to initialize OpenTelemetry whenever the app is started, for example, in `manage.py`:

```python
# manage.py

import uptrace

def main():
    uptrace.configure_opentelemetry(
        # Copy DSN here or use UPTRACE_DSN env var.
        # dsn="",
        service_name="myservice",
        service_version="v1.0.0",
    )

    # other code
```

See [Uptrace Python](https://uptrace.dev/get/opentelemetry-python.html) documentation for details.

## Instrumenting Django

To instrument Django, you need a corresponding [OpenTelemetry Django instrumentation](https://uptrace.dev/get/instrument/opentelemetry-django.html):

```shell
pip install opentelemetry-instrumentation-django
```

Django instrumentation uses `DJANGO_SETTINGS_MODULE` env variable to find settings file. Django defines that variable in `manage.py` file so you should instrument Django app from that file:

```python
# manage.py

from opentelemetry.instrumentation.django import DjangoInstrumentor

def main():
    # DjangoInstrumentor uses DJANGO_SETTINGS_MODULE to instrument the project.
    # Make sure the var is available before you call the DjangoInstrumentor.
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

    DjangoInstrumentor().instrument()
```

## Running the example

You can start Uptrace with a single command using [Docker example](https://github.com/uptrace/uptrace/tree/master/example/docker):

```go
docker-compose up -d
```

And then start the [app](https://github.com/uptrace/uptrace/tree/master/example/django) passing Uptrace DSN as an env variable:

```shell
export UPTRACE_DSN=http://project2_secret_token@localhost:14317/2
./manage.py runserver
```

The app should be serving requests on `http://localhost:8000` and should render a link to Uptrace UI. After opening the link, you should see this:

![Django](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3y0gmrxv75ynvbxasmu.png)

## Popular instrumentations

You also check the following popular [OpenTelemetry instrumentations](https://uptrace.dev/get/instrument/):

- [OpenTelemetry Flask](https://uptrace.dev/get/instrument/opentelemetry-flask.html)
- [OpenTelemetry FastAPI](https://uptrace.dev/get/instrument/opentelemetry-fastapi.html)
- [OpenTelemetry SQLAlchemy](https://uptrace.dev/get/instrument/opentelemetry-sqlalchemy.html)