> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# WSGI/ASGI Instrumentation

The WSGI and ASGI standards provide a common layer for the development of web frameworks and servers in Python. Most popular Python web frameworks follow these standards, allowing for any Python web application to be deployed with any Python web server.

<Tip>
  ASGI support was added in version `0.1.4` of the AppSignal for Python package.
</Tip>

AppSignal supports instrumentation for generic WSGI and ASGI web applications through OpenTelemetry.

<Tip>
  AppSignal also supports popular web frameworks directly, such as
  [Django](/python/instrumentations/django),
  [Flask](/python/instrumentations/flask),
  [FastAPI](/python/instrumentations/fastapi) or
  [Starlette](/python/instrumentations/starlette). If you're using a web
  framework we support directly, follow the instructions for that framework
  instead of the generic WSGI/ASGI instructions on this page.
</Tip>

## Installation

<Note>
  🐍 Don't forget to [install the AppSignal for Python package](/python/installation) in your application first.
</Note>

First, install either the `opentelemetry-instrumentation-wsgi` or the `opentelemetry-instrumentation-asgi` package, depending the gateway interface used in the application. To add it to your project, add the following line to your `requirements.txt` file:

<CodeGroup>
  ```python Python theme={null}
  # requirements.txt
  # For a WSGI application:
  opentelemetry-instrumentation-wsgi
  # For an ASGI application:
  opentelemetry-instrumentation-asgi
  ```
</CodeGroup>

## Setup

In your application's entry point (usually named `main.py` or `app.py`), before your application is initialised, call `appsignal.start()` to start your application:

<CodeGroup>
  ```python Python theme={null}
  import appsignal
  appsignal.start()

  # ... the rest of your code goes here ...
  ```
</CodeGroup>

Then, import `OpenTelemetryMiddleware` from the corresponding OpenTelemetry instrumentation, and wrap your application with it:

<CodeGroup>
  ```python Python theme={null}
  # For a WSGI application:
  from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware
  # For an ASGI application:
  from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware

  my_app = # ... your WSGI/ASGI application goes here ...

  my_app = OpenTelemetryMiddleware(my_app)
  ```
</CodeGroup>

## Grouping routes

By default, a generic WSGI or ASGI instrumentation will not have the necessary context to understand how routing is structured in your application. As such, the performance samples that AppSignal receives will not be grouped correctly. You must add routing information to the OpenTelemetry span manually.

One way to do so is by following OpenTelemetry's HTTP semantic conventions, setting the `http.route` attribute in your route handlers:

<CodeGroup>
  ```python Python theme={null}
  from opentelemetry.trace import get_current_span

  def get_user_route_handler():
    get_current_span().set_attribute("http.route", "/users/:user_id")
    # ... your route handler goes here ...
  ```
</CodeGroup>

AppSignal will automatically use the value of this attribute and use it to group requests, along with the request method. For example, a GET request that is handled by this method will appear as `GET /users/:user_id` in the AppSignal performance samples panel.

If you prefer to group requests in some other way (for example, by referring to the method or class that implements them) you can use the `appsignal.root_name` attribute:

<CodeGroup>
  ```python Python theme={null}
  from opentelemetry.trace import get_current_span

  class UserHandlers:
    def show():
      get_current_span().set_attribute("appsignal.root_name", "UserHandlers#show")
      # ... your route handler goes here ...
  ```
</CodeGroup>

By using `appsignal.root_name`, the request method will not be used. The value provided (in this case, `UserHandlers#show`) will be used to group all requests handled by this method.
