﻿---
title: Supported technologies
description: The Elastic APM Python Agent supports the technologies listed below. Elastic supports OpenTelemetry, which allows logs, metrics, and trace signal collection...
url: https://www.elastic.co/elastic/docs-builder/docs/2987/reference/apm/agents/python/supported-technologies
products:
  - APM Agent
  - APM Python Agent
applies_to:
  - Serverless Observability projects: Generally available
  - Elastic Stack: Generally available
  - Application Performance Monitoring Agent for Python: Generally available
---

# Supported technologies
The Elastic APM Python Agent supports the technologies listed below.
Elastic supports OpenTelemetry, which allows logs, metrics, and trace signal collection for many of these technologies. Consider using the [EDOT Python SDK](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2987/reference/opentelemetry/edot-sdks/python) for observability data so you continue to get the full power of Elastic's platform.

The Elastic APM Python Agent comes with support for the following frameworks:
- [Django](https://www.elastic.co/elastic/docs-builder/docs/2987/reference/apm/agents/python/django-support)
- [Flask](https://www.elastic.co/elastic/docs-builder/docs/2987/reference/apm/agents/python/flask-support)
- [Aiohttp Server](#supported-aiohttp)
- [Tornado](#supported-tornado)
- [Starlette/FastAPI](#supported-starlette)
- [Sanic](#supported-sanic)
- [GRPC](#supported-grpc)

For other frameworks and custom Python code, the agent exposes a set of [APIs](https://www.elastic.co/elastic/docs-builder/docs/2987/reference/apm/agents/python/api-reference) for integration.

### Python

The following Python versions are supported:
- 3.6
- 3.7
- 3.8
- 3.9
- 3.10
- 3.11
- 3.12
- 3.13


### Django

We support these Django versions:
- 1.11
- 2.0
- 2.1
- 2.2
- 3.0
- 3.1
- 3.2
- 4.0
- 4.2
- 5.0

For upcoming Django versions, we generally aim to ensure compatibility starting with the first Release Candidate.
<note>
  we currently don’t support Django running in ASGI mode.
</note>


### Flask

We support these Flask versions:
- 0.10 (Deprecated)
- 0.11 (Deprecated)
- 0.12 (Deprecated)
- 1.0
- 1.1
- 2.0
- 2.1
- 2.2
- 2.3
- 3.0


### Aiohttp Server

We support these aiohttp versions:
- 3.x


### Tornado

We support these tornado versions:
- 6.x


### Sanic

We support these sanic versions:
- > 20.12.2,<26


### Starlette/FastAPI

We support these Starlette versions:
- > 0.13.0,<1

Any FastAPI version which uses a supported Starlette version should also be supported.

### GRPC

We support these `grpcio` versions:
- > 1.24.0,<2


## Automatic Instrumentation

The Python APM agent comes with automatic instrumentation of various 3rd party modules and standard library modules.

### Scheduling


##### Celery

We support these Celery versions:
- 4.x (deprecated)
- 5.x

Celery tasks will be recorded automatically with Django and Flask only.

### Databases


#### Elasticsearch

Instrumented methods:
- `elasticsearch.transport.Transport.perform_request`
- `elasticsearch.connection.http_urllib3.Urllib3HttpConnection.perform_request`
- `elasticsearch.connection.http_requests.RequestsHttpConnection.perform_request`
- `elasticsearch._async.transport.AsyncTransport.perform_request`
- `elasticsearch_async.connection.AIOHttpConnection.perform_request`

Additionally, the instrumentation wraps the following methods of the `Elasticsearch` client class:
- `elasticsearch.client.Elasticsearch.delete_by_query`
- `elasticsearch.client.Elasticsearch.search`
- `elasticsearch.client.Elasticsearch.count`
- `elasticsearch.client.Elasticsearch.update`

Collected trace data:
- the query string (if available)
- the `query` element from the request body (if available)
- the response status code
- the count of affected rows (if available)

We recommend using keyword arguments only with elasticsearch-py, as recommended by [the elasticsearch-py docs](https://elasticsearch-py.readthedocs.io/en/latest/api.html#api-documentation). If you are using positional arguments, we will be unable to gather the `query` element from the request body.

#### SQLite

Instrumented methods:
- `sqlite3.connect`
- `sqlite3.dbapi2.connect`
- `pysqlite2.dbapi2.connect`

The instrumented `connect` method returns a wrapped connection/cursor which instruments the actual `Cursor.execute` calls.
Collected trace data:
- parametrized SQL query


#### MySQLdb

Library: `MySQLdb` (`<2`)
Instrumented methods:
- `MySQLdb.connect`

The instrumented `connect` method returns a wrapped connection/cursor which instruments the actual `Cursor.execute` calls.
Collected trace data:
- parametrized SQL query


#### mysql-connector

Library: `mysql-connector-python` (`<9`)
Instrumented methods:
- `mysql.connector.connect`

The instrumented `connect` method returns a wrapped connection/cursor which instruments the actual `Cursor.execute` calls.
Collected trace data:
- parametrized SQL query


#### pymysql

Library: `pymysql` (`<2`)
Instrumented methods:
- `pymysql.connect`

The instrumented `connect` method returns a wrapped connection/cursor which instruments the actual `Cursor.execute` calls.
Collected trace data:
- parametrized SQL query


#### aiomysql

Library: `aiomysql` (`<1`)
Instrumented methods:
- `aiomysql.cursors.Cursor.execute`

Collected trace data:
- parametrized SQL query


#### PostgreSQL Psycopg2

Library: `psycopg2`, `psycopg2-binary` (`>=2.9,<3`)
Instrumented methods:
- `psycopg2.connect`

The instrumented `connect` method returns a wrapped connection/cursor which instruments the actual `Cursor.execute` calls.
Collected trace data:
- parametrized SQL query


#### PostgreSQL Psycopg

Library: `psycopg`, `psycopg-binary` (`>3.0.0,<4`)
Instrumented methods:
- `psycopg.connect`

The instrumented `connect` method returns a wrapped connection/cursor which instruments the actual `Cursor.execute` calls.
Collected trace data:
- parametrized SQL query


#### aiopg

Library: `aiopg` (`>=1.0,<2`)
Instrumented methods:
- `aiopg.cursor.Cursor.execute`
- `aiopg.cursor.Cursor.callproc`

Collected trace data:
- parametrized SQL query


#### asyncpg

Library: `asyncpg` (`>=0.20,<2`)
Instrumented methods:
- `asyncpg.connection.Connection.execute`
- `asyncpg.connection.Connection.executemany`

Collected trace data:
- parametrized SQL query


#### PyODBC

Library: `pyodbc` (`>=4.0,<6`)
Instrumented methods:
- `pyodbc.connect`

The instrumented `connect` method returns a wrapped connection/cursor which instruments the actual `Cursor.execute` calls.
Collected trace data:
- parametrized SQL query


#### MS-SQL

Library: `pymssql` (`>=2.1.0,<3`)
Instrumented methods:
- `pymssql.connect`

The instrumented `connect` method returns a wrapped connection/cursor which instruments the actual `Cursor.execute` calls.
Collected trace data:
- parametrized SQL query


#### MongoDB

Library: `pymongo` (`>=2.9,<5`)
Instrumented methods:
- `pymongo.collection.Collection.aggregate`
- `pymongo.collection.Collection.bulk_write`
- `pymongo.collection.Collection.count`
- `pymongo.collection.Collection.create_index`
- `pymongo.collection.Collection.create_indexes`
- `pymongo.collection.Collection.delete_many`
- `pymongo.collection.Collection.delete_one`
- `pymongo.collection.Collection.distinct`
- `pymongo.collection.Collection.drop`
- `pymongo.collection.Collection.drop_index`
- `pymongo.collection.Collection.drop_indexes`
- `pymongo.collection.Collection.ensure_index`
- `pymongo.collection.Collection.find_and_modify`
- `pymongo.collection.Collection.find_one`
- `pymongo.collection.Collection.find_one_and_delete`
- `pymongo.collection.Collection.find_one_and_replace`
- `pymongo.collection.Collection.find_one_and_update`
- `pymongo.collection.Collection.group`
- `pymongo.collection.Collection.inline_map_reduce`
- `pymongo.collection.Collection.insert`
- `pymongo.collection.Collection.insert_many`
- `pymongo.collection.Collection.insert_one`
- `pymongo.collection.Collection.map_reduce`
- `pymongo.collection.Collection.reindex`
- `pymongo.collection.Collection.remove`
- `pymongo.collection.Collection.rename`
- `pymongo.collection.Collection.replace_one`
- `pymongo.collection.Collection.save`
- `pymongo.collection.Collection.update`
- `pymongo.collection.Collection.update_many`
- `pymongo.collection.Collection.update_one`

Collected trace data:
- database name
- method name


#### Redis

Library: `redis` (`>=2.8,<8`)
Instrumented methods:
- `redis.client.Redis.execute_command`
- `redis.client.Pipeline.execute`

Collected trace data:
- Redis command name


#### aioredis

Library: `aioredis` (`<=2.0.1`)
Instrumented methods:
- `aioredis.pool.ConnectionsPool.execute`
- `aioredis.commands.transaction.Pipeline.execute`
- `aioredis.connection.RedisConnection.execute`

Collected trace data:
- Redis command name


#### Cassandra

Library: `cassandra-driver` (`>=3.24,<4.0`)
Instrumented methods:
- `cassandra.cluster.Session.execute`
- `cassandra.cluster.Cluster.connect`

Collected trace data:
- CQL query


#### Python Memcache

Library: `python-memcached` (`>=1.51,<2`)
Instrumented methods:
- `memcache.Client.add`
- `memcache.Client.append`
- `memcache.Client.cas`
- `memcache.Client.decr`
- `memcache.Client.delete`
- `memcache.Client.delete_multi`
- `memcache.Client.disconnect_all`
- `memcache.Client.flush_all`
- `memcache.Client.get`
- `memcache.Client.get_multi`
- `memcache.Client.get_slabs`
- `memcache.Client.get_stats`
- `memcache.Client.gets`
- `memcache.Client.incr`
- `memcache.Client.prepend`
- `memcache.Client.replace`
- `memcache.Client.set`
- `memcache.Client.set_multi`
- `memcache.Client.touch`

Collected trace data:
- Destination (address and port)


#### pymemcache

Library: `pymemcache` (`>=3.0,<4.1`)
Instrumented methods:
- `pymemcache.client.base.Client.add`
- `pymemcache.client.base.Client.append`
- `pymemcache.client.base.Client.cas`
- `pymemcache.client.base.Client.decr`
- `pymemcache.client.base.Client.delete`
- `pymemcache.client.base.Client.delete_many`
- `pymemcache.client.base.Client.delete_multi`
- `pymemcache.client.base.Client.flush_all`
- `pymemcache.client.base.Client.get`
- `pymemcache.client.base.Client.get_many`
- `pymemcache.client.base.Client.get_multi`
- `pymemcache.client.base.Client.gets`
- `pymemcache.client.base.Client.gets_many`
- `pymemcache.client.base.Client.incr`
- `pymemcache.client.base.Client.prepend`
- `pymemcache.client.base.Client.quit`
- `pymemcache.client.base.Client.replace`
- `pymemcache.client.base.Client.set`
- `pymemcache.client.base.Client.set_many`
- `pymemcache.client.base.Client.set_multi`
- `pymemcache.client.base.Client.stats`
- `pymemcache.client.base.Client.touch`

Collected trace data:
- Destination (address and port)


#### kafka-python

Library: `kafka-python` (`>=2.0,<3`)
Instrumented methods:
- `kafka.KafkaProducer.send`,
- `kafka.KafkaConsumer.poll`,
- `kafka.KafkaConsumer.__next__`

Collected trace data:
- Destination (address and port)
- topic (if applicable)


### External HTTP requests


#### Standard library

Library: `urllib.request` (Python 3)
Instrumented methods:
- `urllib.request.AbstractHTTPHandler.do_open`

Collected trace data:
- HTTP method
- requested URL


#### urllib3

Library: `urllib3` (`<3`)
Instrumented methods:
- `urllib3.connectionpool.HTTPConnectionPool.urlopen`

Additionally, we instrumented vendored instances of urllib3 in the following libraries:
- `requests`
- `botocore`

Both libraries have "unvendored" urllib3 in more recent versions, we recommend to use the newest versions.
Collected trace data:
- HTTP method
- requested URL


#### requests

Library: `requests` (`<3`)
Instrumented methods:
- `requests.sessions.Session.send`

Collected trace data:
- HTTP method
- requested URL


#### AIOHTTP Client

Library: `aiohttp` (`>=3,<4`)
Instrumented methods:
- `aiohttp.client.ClientSession._request`

Collected trace data:
- HTTP method
- requested URL


#### httpx

Library: `httpx` (`<1`)
Instrumented methods:
- `httpx.Client.send

Collected trace data:
- HTTP method
- requested URL


### Services


#### AWS Boto3 / Botocore

Library: `boto3` (`>=1.0,<2`)
Instrumented methods:
- `botocore.client.BaseClient._make_api_call`

Collected trace data for all services:
- AWS region (e.g. `eu-central-1`)
- AWS service name (e.g. `s3`)
- operation name (e.g. `ListBuckets`)

Additionally, some services collect more specific data

#### AWS Aiobotocore

Library: `aiobotocore` (`>=2.2.0,<3`)
Instrumented methods:
- `aiobotocore.client.BaseClient._make_api_call`

Collected trace data for all services:
- AWS region (e.g. `eu-central-1`)
- AWS service name (e.g. `s3`)
- operation name (e.g. `ListBuckets`)

Additionally, some services collect more specific data

##### S3

- Bucket name


##### DynamoDB

- Table name


##### SNS

- Topic name


##### SQS

- Queue name


### Template Engines


#### Django Template Language

Library: `Django` (see [Django](#supported-django) for supported versions)
Instrumented methods:
- `django.template.Template.render`

Collected trace data:
- template name


#### Jinja2

Library: `jinja2`
Instrumented methods:
- `jinja2.Template.render`

Collected trace data:
- template name