pax_global_header 0000666 0000000 0000000 00000000064 15216207663 0014522 g ustar 00root root 0000000 0000000 52 comment=e8c1f3db7d092ac67b36e1fa01c64207e29d00b2
python-elastic-apm-6.26.2/ 0000775 0000000 0000000 00000000000 15216207663 0015335 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.ci/ 0000775 0000000 0000000 00000000000 15216207663 0016006 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.ci/.matrix_exclude.yml 0000664 0000000 0000000 00000027335 15216207663 0021636 0 ustar 00root root 0000000 0000000 exclude:
- VERSION: pypy-3 # pypy3 currently fails on CI, e.g. https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-python%2Fapm-agent-python-mbp/detail/PR-1099/2/pipeline#step-3497-log-1
FRAMEWORK: none
# Django
# Django 4.0 requires Python 3.8+
- VERSION: pypy-3 # current pypy-3 is compatible with Python 3.7
FRAMEWORK: django-4.0
- VERSION: python-3.6
FRAMEWORK: django-4.0
- VERSION: python-3.7
FRAMEWORK: django-4.0
# Django 4.2 requires Python 3.8+
- VERSION: python-3.6
FRAMEWORK: django-4.2
- VERSION: python-3.7
FRAMEWORK: django-4.2
# Django 5.0 requires Python 3.10+
- VERSION: python-3.6
FRAMEWORK: django-5.0
- VERSION: python-3.7
FRAMEWORK: django-5.0
- VERSION: python-3.8
FRAMEWORK: django-5.0
- VERSION: python-3.9
FRAMEWORK: django-5.0
- VERSION: pypy-3 # current pypy-3 is compatible with Python 3.7
FRAMEWORK: celery-5-django-4
- VERSION: python-3.6
FRAMEWORK: celery-5-django-4
- VERSION: python-3.7
FRAMEWORK: celery-5-django-4
- VERSION: python-3.6
FRAMEWORK: celery-5-django-5
- VERSION: python-3.7
FRAMEWORK: celery-5-django-5
- VERSION: python-3.8
FRAMEWORK: celery-5-django-5
- VERSION: python-3.9
FRAMEWORK: celery-5-django-5
# Elasticsearch
- VERSION: python-3.6
FRAMEWORK: elasticsearch-9
- VERSION: python-3.7
FRAMEWORK: elasticsearch-9
# Flask
- VERSION: pypy-3
FRAMEWORK: flask-0.11 # see https://github.com/pallets/flask/commit/6e46d0cd, 0.11.2 was never released
- VERSION: python-3.6
FRAMEWORK: flask-2.1
- VERSION: python-3.6
FRAMEWORK: flask-2.2
- VERSION: python-3.6
FRAMEWORK: flask-2.3
- VERSION: python-3.6
FRAMEWORK: flask-3.0
- VERSION: python-3.7
FRAMEWORK: flask-2.3
- VERSION: python-3.7
FRAMEWORK: flask-3.0
- VERSION: python-3.14
FRAMEWORK: flask-1.0
# Python 3.9
- VERSION: python-3.9
FRAMEWORK: cassandra-3.24
# Python 3.10 removed a bunch of classes from collections, now in collections.abc
- VERSION: python-3.10
FRAMEWORK: django-1.11
- VERSION: python-3.10
FRAMEWORK: django-2.0
- VERSION: python-3.11 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-flask-2
- VERSION: python-3.11 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-django-3
- VERSION: python-3.11 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-django-4
- VERSION: python-3.12 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-flask-2
- VERSION: python-3.12 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-django-3
- VERSION: python-3.12 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-django-4
- VERSION: python-3.13 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-flask-2
- VERSION: python-3.13 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-django-3
- VERSION: python-3.13 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-django-4
- VERSION: python-3.14 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-flask-2
- VERSION: python-3.14 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-django-3
- VERSION: python-3.14 # https://github.com/celery/billiard/issues/377
FRAMEWORK: celery-5-django-4
- VERSION: python-3.10
FRAMEWORK: graphene-2
- VERSION: python-3.10
FRAMEWORK: aiohttp-3.0
- VERSION: python-3.10
FRAMEWORK: aiohttp-4.0
- VERSION: python-3.10
FRAMEWORK: cassandra-3.24
- VERSION: python-3.10
FRAMEWORK: pymongo-3.5
- VERSION: python-3.11
FRAMEWORK: django-1.11
- VERSION: python-3.11
FRAMEWORK: django-2.0
- VERSION: python-3.11
FRAMEWORK: django-2.1
- VERSION: python-3.11
FRAMEWORK: graphene-2
- VERSION: python-3.11
FRAMEWORK: aiohttp-3.0
- VERSION: python-3.11
FRAMEWORK: aiohttp-4.0
- VERSION: python-3.11
FRAMEWORK: cassandra-3.24
- VERSION: python-3.11
FRAMEWORK: pymongo-3.5
- VERSION: python-3.12
FRAMEWORK: django-1.11
- VERSION: python-3.12
FRAMEWORK: django-2.0
- VERSION: python-3.12
FRAMEWORK: django-2.1
- VERSION: python-3.12
FRAMEWORK: graphene-2
- VERSION: python-3.12
FRAMEWORK: aiohttp-3.0
- VERSION: python-3.12
FRAMEWORK: aiohttp-4.0
- VERSION: python-3.12
FRAMEWORK: cassandra-3.24
- VERSION: python-3.12
FRAMEWORK: pymongo-3.5
- VERSION: python-3.13
FRAMEWORK: django-1.11
- VERSION: python-3.13
FRAMEWORK: django-2.0
- VERSION: python-3.13
FRAMEWORK: django-2.1
- VERSION: python-3.13
FRAMEWORK: django-2.2
- VERSION: python-3.13
FRAMEWORK: django-3.0
- VERSION: python-3.13
FRAMEWORK: django-3.1
- VERSION: python-3.13
FRAMEWORK: django-3.2
- VERSION: python-3.13
FRAMEWORK: django-4.0
- VERSION: python-3.13
FRAMEWORK: graphene-2
- VERSION: python-3.13
FRAMEWORK: aiohttp-3.0
- VERSION: python-3.13
FRAMEWORK: aiohttp-4.0
- VERSION: python-3.13
FRAMEWORK: cassandra-3.24
- VERSION: python-3.14
FRAMEWORK: django-1.11
- VERSION: python-3.14
FRAMEWORK: django-2.0
- VERSION: python-3.14
FRAMEWORK: django-2.1
- VERSION: python-3.14
FRAMEWORK: django-2.2
- VERSION: python-3.14
FRAMEWORK: django-3.0
- VERSION: python-3.14
FRAMEWORK: django-3.1
- VERSION: python-3.14
FRAMEWORK: django-3.2
- VERSION: python-3.14
FRAMEWORK: django-4.0
- VERSION: python-3.14
FRAMEWORK: django-4.2
- VERSION: python-3.14
FRAMEWORK: django-5.0
- VERSION: python-3.14
FRAMEWORK: graphene-2
- VERSION: python-3.14
FRAMEWORK: aiohttp-3.0
- VERSION: python-3.14
FRAMEWORK: aiohttp-4.0
- VERSION: python-3.14
FRAMEWORK: cassandra-3.24
- VERSION: python-3.14
FRAMEWORK: pymongo-3.5
# pymongo
- VERSION: python-3.10
FRAMEWORK: pymongo-3.1
- VERSION: python-3.11
FRAMEWORK: pymongo-3.1
- VERSION: python-3.12
FRAMEWORK: pymongo-3.1
- VERSION: python-3.13
FRAMEWORK: pymongo-3.1
- VERSION: python-3.14
FRAMEWORK: pymongo-3.1
- VERSION: python-3.10
FRAMEWORK: pymongo-3.2
- VERSION: python-3.11
FRAMEWORK: pymongo-3.2
- VERSION: python-3.12
FRAMEWORK: pymongo-3.2
- VERSION: python-3.13
FRAMEWORK: pymongo-3.2
- VERSION: python-3.14
FRAMEWORK: pymongo-3.2
- VERSION: python-3.10
FRAMEWORK: pymongo-3.3
- VERSION: python-3.11
FRAMEWORK: pymongo-3.3
- VERSION: python-3.12
FRAMEWORK: pymongo-3.3
- VERSION: python-3.13
FRAMEWORK: pymongo-3.3
- VERSION: python-3.14
FRAMEWORK: pymongo-3.3
- VERSION: python-3.8
FRAMEWORK: pymongo-3.4
- VERSION: python-3.9
FRAMEWORK: pymongo-3.4
- VERSION: python-3.10
FRAMEWORK: pymongo-3.4
- VERSION: python-3.11
FRAMEWORK: pymongo-3.4
- VERSION: python-3.12
FRAMEWORK: pymongo-3.4
- VERSION: python-3.13
FRAMEWORK: pymongo-3.4
- VERSION: python-3.13
FRAMEWORK: pymongo-3.5
- VERSION: python-3.14
FRAMEWORK: pymongo-3.4
- VERSION: python-3.14
FRAMEWORK: pymongo-3.5
- VERSION: pypy-3
FRAMEWORK: pymongo-3.0
# pymssql
- VERSION: pypy-3 # currently fails with error on pypy3
FRAMEWORK: pymssql-newest
- VERSION: python-3.6 # dropped support for py3.6
FRAMEWORK: pymssql-newest
# pyodbc
- VERSION: pypy-3
FRAMEWORK: pyodbc-newest
# boto3
- VERSION: python-3.10
FRAMEWORK: boto3-1.5
- VERSION: python-3.10
FRAMEWORK: boto3-1.6
- VERSION: python-3.11
FRAMEWORK: boto3-1.5
- VERSION: python-3.11
FRAMEWORK: boto3-1.6
- VERSION: python-3.12
FRAMEWORK: boto3-1.5
- VERSION: python-3.12
FRAMEWORK: boto3-1.6
- VERSION: python-3.13
FRAMEWORK: boto3-1.5
- VERSION: python-3.13
FRAMEWORK: boto3-1.6
- VERSION: python-3.14
FRAMEWORK: boto3-1.5
- VERSION: python-3.14
FRAMEWORK: boto3-1.6
# aiohttp client, only supported in Python 3.7+
- VERSION: pypy-3
FRAMEWORK: aiohttp-3.0
- VERSION: python-3.6
FRAMEWORK: aiohttp-3.0
- VERSION: pypy-3
FRAMEWORK: aiohttp-4.0
- VERSION: python-3.6
FRAMEWORK: aiohttp-4.0
- VERSION: pypy-3
FRAMEWORK: aiohttp-newest
- VERSION: python-3.6
FRAMEWORK: aiohttp-newest
# tornado, only supported in Python 3.7+
- VERSION: pypy-3
FRAMEWORK: tornado-newest
- VERSION: python-3.6
FRAMEWORK: tornado-newest
# Starlette, only supported in python 3.7+
- VERSION: pypy-3
FRAMEWORK: starlette-0.13
- VERSION: python-3.6
FRAMEWORK: starlette-0.13
- VERSION: pypy-3
FRAMEWORK: starlette-0.14
- VERSION: python-3.6
FRAMEWORK: starlette-0.14
- VERSION: pypy-3
FRAMEWORK: starlette-newest
- VERSION: python-3.6
FRAMEWORK: starlette-newest
# aiopg
- VERSION: pypy-3
FRAMEWORK: aiopg-newest
- VERSION: python-3.6
FRAMEWORK: aiopg-newest
# asyncpg
- VERSION: pypy-3
FRAMEWORK: asyncpg-newest
- VERSION: pypy-3
FRAMEWORK: asyncpg-0.28
- VERSION: python-3.6
FRAMEWORK: asyncpg-newest
- VERSION: python-3.6
FRAMEWORK: asyncpg-0.28
- VERSION: python-3.13
FRAMEWORK: asyncpg-0.28
- VERSION: python-3.14
FRAMEWORK: asyncpg-0.28
# sanic
- VERSION: pypy-3
FRAMEWORK: sanic-newest
- VERSION: pypy-3
FRAMEWORK: sanic-20.12
- VERSION: python-3.6
FRAMEWORK: sanic-20.12
- VERSION: python-3.6
FRAMEWORK: sanic-newest
- VERSION: python-3.8
FRAMEWORK: sanic-newest
- VERSION: python-3.13
FRAMEWORK: sanic-20.12
- VERSION: python-3.14
FRAMEWORK: sanic-20.12
# aioredis
- VERSION: pypy-3
FRAMEWORK: aioredis-newest
- VERSION: python-3.6
FRAMEWORK: aioredis-newest
# aiomysql
- VERSION: pypy-3
FRAMEWORK: aiomysql-newest
- VERSION: python-3.6
FRAMEWORK: aiomysql-newest
# aiobotocore
- VERSION: pypy-3
FRAMEWORK: aiobotocore-newest
- VERSION: python-3.6
FRAMEWORK: aiobotocore-newest
# mysql-connector-python
- VERSION: python-3.6
FRAMEWORK: mysql_connector-newest
# twisted
- VERSION: python-3.11
FRAMEWORK: twisted-18
- VERSION: python-3.11
FRAMEWORK: twisted-17
- VERSION: python-3.11
FRAMEWORK: twisted-16
- VERSION: python-3.12
FRAMEWORK: twisted-18
- VERSION: python-3.12
FRAMEWORK: twisted-17
- VERSION: python-3.12
FRAMEWORK: twisted-16
- VERSION: python-3.13
FRAMEWORK: twisted-18
- VERSION: python-3.13
FRAMEWORK: twisted-17
- VERSION: python-3.13
FRAMEWORK: twisted-16
- VERSION: python-3.14
FRAMEWORK: twisted-18
- VERSION: python-3.14
FRAMEWORK: twisted-17
- VERSION: python-3.14
FRAMEWORK: twisted-16
# pylibmc
- VERSION: python-3.11
FRAMEWORK: pylibmc-1.4
- VERSION: python-3.12
FRAMEWORK: pylibmc-1.4
- VERSION: python-3.13
FRAMEWORK: pylibmc-1.4
- VERSION: python-3.14
FRAMEWORK: pylibmc-1.4
# grpc
- VERSION: python-3.6
FRAMEWORK: grpc-newest
- VERSION: python-3.7
FRAMEWORK: grpc-1.24
- VERSION: python-3.8
FRAMEWORK: grpc-1.24
- VERSION: python-3.9
FRAMEWORK: grpc-1.24
- VERSION: python-3.10
FRAMEWORK: grpc-1.24
- VERSION: python-3.11
FRAMEWORK: grpc-1.24
- VERSION: python-3.12
FRAMEWORK: grpc-1.24
- VERSION: python-3.13
FRAMEWORK: grpc-1.24
- VERSION: python-3.14
FRAMEWORK: grpc-1.24
- VERSION: python-3.7
FRAMEWORK: flask-1.0
- VERSION: python-3.7
FRAMEWORK: flask-1.1
- VERSION: python-3.7
FRAMEWORK: jinja2-2
# TODO py3.12
- VERSION: python-3.12
FRAMEWORK: sanic-20.12 # no wheels available yet
- VERSION: python-3.14
FRAMEWORK: cassandra-newest # c extension issue
# httpx
- VERSION: python-3.13
FRAMEWORK: httpx-0.13
- VERSION: python-3.13
FRAMEWORK: httpx-0.14
- VERSION: python-3.13
FRAMEWORK: httpx-0.21
- VERSION: python-3.14
FRAMEWORK: httpx-0.13
- VERSION: python-3.14
FRAMEWORK: httpx-0.14
- VERSION: python-3.14
FRAMEWORK: httpx-0.21
python-elastic-apm-6.26.2/.ci/.matrix_framework.yml 0000664 0000000 0000000 00000002502 15216207663 0022167 0 ustar 00root root 0000000 0000000 # this is a limited list of matrix builds to be used for PRs
# see .jenkins_framework_full.yml for a full list
FRAMEWORK:
- none
- django-1.11
- django-3.2
- django-4.0
- django-4.2
- django-5.0
- flask-0.12
- flask-2.3
- flask-3.0
- jinja2-3
- opentelemetry-newest
- opentracing-newest
- twisted-newest
- celery-5-flask-2
- celery-5-django-4
- celery-5-django-5
- requests-newest
- boto3-newest
- pymongo-newest
- redis-newest
- aioredis-newest
#- aioredis-2 # not supported yet
- psycopg-newest
- psycopg2-newest
- psycopg_pool-newest
- pymssql-newest
- pyodbc-newest
- memcached-newest
- pylibmc-newest
- elasticsearch-7
- elasticsearch-8
- elasticsearch-9
- cassandra-newest
- psutil-newest
#- eventlet-newest
- gevent-newest
- mysql_connector-newest
- pymysql-newest
- mysqlclient-newest
- aiohttp-newest
- aiopg-newest
- asyncpg-newest
- tornado-newest
# this has a dependency on requests, run it to catch update issues before merging. Drop after baseline > 0.21.0
- starlette-0.14
- starlette-newest
- pymemcache-newest
- graphene-2
- httpx-newest
- httplib2-newest
- prometheus_client-newest
- sanic-newest
- aiomysql-newest
- aiobotocore-newest
- kafka-python-newest
- grpc-newest
- azurefunctions-newest
- azure-newest
python-elastic-apm-6.26.2/.ci/.matrix_framework_fips.yml 0000664 0000000 0000000 00000000757 15216207663 0023222 0 ustar 00root root 0000000 0000000 # this is a limited list of matrix builds to be used for PRs
# see .matrix_framework_full.yml for a full list
FRAMEWORK:
- none
- django-5.0
- flask-3.0
- jinja2-3
- opentelemetry-newest
- opentracing-newest
- twisted-newest
- celery-5-flask-2
- celery-5-django-5
- requests-newest
- psutil-newest
- gevent-newest
- aiohttp-newest
- tornado-newest
- starlette-newest
- graphene-2
- httpx-newest
- httplib2-newest
- prometheus_client-newest
- sanic-newest
python-elastic-apm-6.26.2/.ci/.matrix_framework_full.yml 0000664 0000000 0000000 00000003276 15216207663 0023222 0 ustar 00root root 0000000 0000000 # This is the full list of matrix builds, to be triggered with a daily build
# or manually
FRAMEWORK:
- none
- django-1.11
- django-2.0
- django-2.1
- django-2.2
- django-3.0
- django-3.1
- django-3.2
- django-4.0
- django-4.2
- django-5.0
# - django-master
- flask-0.10
- flask-0.11
- flask-0.12
- flask-1.0
- flask-1.1
- flask-2.0
- flask-2.1
- flask-2.2
- flask-2.3
- flask-3.0
- jinja2-2
- jinja2-3
- celery-5-flask-2
- celery-5-django-3
- celery-5-django-4
- celery-5-django-5
- opentelemetry-newest
- opentracing-newest
- opentracing-2.0
- twisted-newest
- twisted-18
- twisted-17
- twisted-16
- requests-newest
- boto3-1.5
- boto3-1.6
- boto3-newest
- pymongo-3.1
- pymongo-3.2
- pymongo-3.3
- pymongo-3.4
- pymongo-3.5
- pymongo-3.6
- pymongo-newest
- redis-3
- redis-2
- redis-newest
- psycopg-newest
- psycopg2-newest
- psycopg_pool-newest
- pymssql-newest
- memcached-newest
- pylibmc-1.4
- pylibmc-newest
- cassandra-3.24
- cassandra-newest
- psutil-newest
- psutil-5.0
- psutil-4.0
#- eventlet-newest
- elasticsearch-7
- elasticsearch-8
- elasticsearch-9
- gevent-newest
- aiohttp-3.0
- aiohttp-newest
- aiopg-newest
- asyncpg-0.28
- asyncpg-newest
- tornado-newest
- starlette-0.13
- starlette-0.14
- starlette-newest
- pymemcache-3.0
- pymemcache-newest
- graphene-2
- httpx-0.13
- httpx-0.14
- httpx-0.21
- httpx-newest
- httplib2-newest
- sanic-20.12
- sanic-newest
- aiobotocore-newest
- kafka-python-newest
- grpc-newest
#- grpc-1.24 # This appears to have problems with python>3.6?
- azurefunctions-newest
- azure-newest
python-elastic-apm-6.26.2/.ci/.matrix_python.yml 0000664 0000000 0000000 00000000050 15216207663 0021507 0 ustar 00root root 0000000 0000000 VERSION:
- python-3.6
- python-3.13
python-elastic-apm-6.26.2/.ci/.matrix_python_fips.yml 0000664 0000000 0000000 00000000031 15216207663 0022527 0 ustar 00root root 0000000 0000000 VERSION:
- python-3.12
python-elastic-apm-6.26.2/.ci/.matrix_python_full.yml 0000664 0000000 0000000 00000000324 15216207663 0022535 0 ustar 00root root 0000000 0000000 VERSION:
- python-3.6
- python-3.7
- python-3.8
- python-3.9
- python-3.10
- python-3.11
- python-3.12
- python-3.13
- python-3.14
# - pypy-3 # excluded due to build issues with SQLite/Django
python-elastic-apm-6.26.2/.ci/bench.sh 0000775 0000000 0000000 00000001270 15216207663 0017424 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
set -exo pipefail
## Buildkite specific configuration
if [ "$CI" == "true" ] ; then
# If HOME is not set then use the Buildkite workspace
# that's normally happening when running in the CI
# owned by Elastic.
if [ -z "$HOME" ] ; then
HOME=$BUILDKITE_BUILD_CHECKOUT_PATH
export HOME
fi
# required when running the benchmark
PATH=$PATH:$HOME/.local/bin
export PATH
fi
## Bench specific
LANG='C.UTF-8'
LC_ALL="${LANG}"
export LANG
export LC_ALL
# APM_AGENT_PYTHON* env variables are provided by the Buildkite hooks.
./scripts/run-benchmarks.sh "$(pwd)" "${APM_AGENT_PYTHON_ES_URL_SECRET}" "${APM_AGENT_PYTHON_ES_USER_SECRET}" "${APM_AGENT_PYTHON_ES_PASS_SECRET}"
python-elastic-apm-6.26.2/.ci/create-arn-table.sh 0000775 0000000 0000000 00000001670 15216207663 0021457 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
set -o pipefail
#
# Create the AWS ARN table given the below environment variables:
#
# AWS_FOLDER - that's the location of the publish-layer-version output for each region
AWS_FOLDER=${AWS_FOLDER?:No aws folder provided}
# Get the repository root directory (where .git is located)
REPO_ROOT="$(realpath $(dirname "${BASH_SOURCE[0]}")/..)"
ARN_FILE="${REPO_ROOT}/.arn-file.md"
{
echo ""
echo "Elastic APM Python agent layer ARNs
"
echo ''
echo '|Region|ARN|'
echo '|------|---|'
} > "${ARN_FILE}"
for f in $(ls "${AWS_FOLDER}"); do
LAYER_VERSION_ARN=$(grep '"LayerVersionArn"' "$AWS_FOLDER/${f}" | cut -d":" -f2- | sed 's/ //g' | sed 's/"//g' | cut -d"," -f1)
echo "INFO: create-arn-table ARN(${LAYER_VERSION_ARN}):region(${f})"
echo "|${f}|${LAYER_VERSION_ARN}|" >> "${ARN_FILE}"
done
{
echo ''
echo ' '
echo ''
} >> "${ARN_FILE}"
echo "INFO: Created ARN table at ${ARN_FILE}"
python-elastic-apm-6.26.2/.ci/docker/ 0000775 0000000 0000000 00000000000 15216207663 0017255 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.ci/docker/README.md 0000664 0000000 0000000 00000001750 15216207663 0020537 0 ustar 00root root 0000000 0000000 # apm-agent-python docker images for testing
Utility script for building and pushing the images based on `.ci/.matrix_python_full.yml`.
> :information_source: This script is mainly used in [publish-docker-images](https://github.com/elastic/apm-agent-python/actions/workflows/build-images.yml) workflow,
which can be triggered safely at any time.
## Options
| Name | Description |
|----------|-----------------------------------------------------------|
| name | Name of the docker image. (`/:`) |
| registry | Registry of the docker image. (`/:`) |
| action | Either `build` or `push`. |
## Usage
### Build
To build the images run
```bash
./util.sh --action build
```
You can set your own docker registry with the flag `--registry x.y.z/org`. The default is `elasticobservability`.
### Push
To push the images run
```bash
./util.sh --action push
```
python-elastic-apm-6.26.2/.ci/docker/util.sh 0000775 0000000 0000000 00000002453 15216207663 0020575 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
set -euo pipefail
project_root=$(dirname "$(dirname "$(dirname "$(realpath "$0" )")")")
IMAGE_NAME="apm-agent-python-testing"
REGISTRY="elasticobservability"
while (( "$#" )); do
case "$1" in
-n|--name)
IMAGE_NAME=$2
shift 2
;;
-r|--registry)
REGISTRY=$2
shift 2
;;
-a|--action)
ACTION=$2
shift 2
;;
--) # end argument parsing
shift
break
;;
-*|--*=) # unsupported flags
echo "Error: Unsupported flag $1" >&2
exit 1
;;
*) # preserve positional arguments
shift
;;
esac
done
versions=$(yq '.VERSION[]' "${project_root}/.ci/.matrix_python_full.yml")
for version in $versions; do
full_image_name="${REGISTRY}/${IMAGE_NAME}:${version}"
case $ACTION in
build)
cache_image="${full_image_name}"
# check that we have an image before using it as a cache
docker manifest inspect "${full_image_name}" || cache_image=
DOCKER_BUILDKIT=1 docker build \
--progress=plain \
--cache-from="${cache_image}" \
-f "${project_root}/tests/Dockerfile" \
--build-arg PYTHON_IMAGE="${version/-/:}" \
-t "${full_image_name}" \
"${project_root}/tests"
;;
push)
docker push "${full_image_name}"
;;
esac
done
python-elastic-apm-6.26.2/.ci/publish-aws.sh 0000775 0000000 0000000 00000006511 15216207663 0020606 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
set -euo pipefail
#
# Publishes the created artifacts from ./dev-utils/make-distribution.sh to AWS as AWS Lambda Layers in every region.
# Finalized by generating an ARN table which will be used in the release notes.
#
# AWS_FOLDER is used for temporary output of publishing layers used to create the arn table. (Optional)
# ELASTIC_LAYER_NAME is the name of the lambda layer e.g. elastic-apm-python-ver-3-44-1 for the git tag v3.44.1 (Required)
# This needs to be set in GH actions
# https://dotjoeblog.wordpress.com/2021/03/14/github-actions-aws-error-exit-code-255/
# eu-west-1 is just a random region
export AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:-eu-west-1}
export AWS_FOLDER=${AWS_FOLDER:-.aws}
FULL_LAYER_NAME=${ELASTIC_LAYER_NAME:?layer name not provided}
ALL_AWS_REGIONS=$(aws ec2 describe-regions --output json --no-cli-pager | jq -r '.Regions[].RegionName')
rm -rf "${AWS_FOLDER}"
mkdir -p "${AWS_FOLDER}"
failed_regions=()
# Delete previous layers
for region in $ALL_AWS_REGIONS; do
layer_versions=$(aws --cli-connect-timeout 30 lambda list-layer-versions --region="${region}" --layer-name="${ELASTIC_LAYER_NAME}" | jq '.LayerVersions[].Version') || {
echo "WARNING: Could not list layer versions in ${region}, skipping deletion"
continue
}
echo "Found layer versions for ${FULL_LAYER_NAME} in ${region}: ${layer_versions:-none}"
for version_number in $layer_versions; do
echo "- Deleting ${FULL_LAYER_NAME}:${version_number} in ${region}"
aws --cli-connect-timeout 30 lambda delete-layer-version \
--region="${region}" \
--layer-name="${FULL_LAYER_NAME}" \
--version-number="${version_number}"
done
done
zip_file="./build/dist/elastic-apm-python-lambda-layer.zip"
for region in $ALL_AWS_REGIONS; do
echo "Publish ${FULL_LAYER_NAME} in ${region}"
if ! publish_output=$(aws --cli-connect-timeout 30 lambda \
--output json \
publish-layer-version \
--region="${region}" \
--layer-name="${FULL_LAYER_NAME}" \
--description="AWS Lambda Extension Layer for the Elastic APM Python Agent" \
--license-info="BSD-3-Clause" \
--compatible-runtimes python3.6 python3.7 python3.8 python3.9 python3.10 python3.11 python3.12 python3.13\
--zip-file="fileb://${zip_file}"); then
echo "WARNING: Failed to publish to ${region}"
failed_regions+=("${region}")
continue
fi
echo "${publish_output}" > "${AWS_FOLDER}/${region}"
layer_version=$(echo "${publish_output}" | jq '.Version')
echo "Grant public layer access ${FULL_LAYER_NAME}:${layer_version} in ${region}"
if ! grant_access_output=$(aws --cli-connect-timeout 30 lambda \
--output json \
add-layer-version-permission \
--region="${region}" \
--layer-name="${FULL_LAYER_NAME}" \
--action="lambda:GetLayerVersion" \
--principal='*' \
--statement-id="${FULL_LAYER_NAME}" \
--version-number="${layer_version}"); then
echo "WARNING: Failed to grant public access in ${region}"
failed_regions+=("${region}")
continue
fi
echo "${grant_access_output}" > "${AWS_FOLDER}/.${region}-public"
done
sh -c "./.ci/create-arn-table.sh"
if [ ${#failed_regions[@]} -gt 0 ]; then
echo "WARNING: Failed to publish to the following regions: ${failed_regions[*]}"
echo "WARNING: The layer is not available in those regions. Please publish manually or investigate connectivity."
fi
python-elastic-apm-6.26.2/.ci/updatecli/ 0000775 0000000 0000000 00000000000 15216207663 0017760 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.ci/updatecli/values.d/ 0000775 0000000 0000000 00000000000 15216207663 0021501 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.ci/updatecli/values.d/apm-data-spec.yml 0000664 0000000 0000000 00000000061 15216207663 0024635 0 ustar 00root root 0000000 0000000 apm_schema_specs_path: tests/upstream/json-specs
python-elastic-apm-6.26.2/.ci/updatecli/values.d/apm-gherkin.yml 0000664 0000000 0000000 00000000052 15216207663 0024423 0 ustar 00root root 0000000 0000000 apm_gherkin_specs_path: tests/bdd/features python-elastic-apm-6.26.2/.ci/updatecli/values.d/apm-json-specs.yml 0000664 0000000 0000000 00000000057 15216207663 0025065 0 ustar 00root root 0000000 0000000 apm_json_specs_path: tests/upstream/json-specs
python-elastic-apm-6.26.2/.ci/updatecli/values.d/scm.yml 0000664 0000000 0000000 00000000370 15216207663 0023006 0 ustar 00root root 0000000 0000000 scm:
enabled: true
owner: elastic
repository: apm-agent-python
branch: main
commitusingapi: true
# begin update-compose policy values
user: obltmachine
email: obltmachine@users.noreply.github.com
# end update-compose policy values python-elastic-apm-6.26.2/.ci/updatecli/values.d/update-compose.yml 0000664 0000000 0000000 00000000055 15216207663 0025151 0 ustar 00root root 0000000 0000000 spec:
files:
- "updatecli-compose.yaml" python-elastic-apm-6.26.2/.editorconfig 0000664 0000000 0000000 00000000452 15216207663 0020013 0 ustar 00root root 0000000 0000000 # editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.asciidoc]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
[*.feature]
indent_size = 2
[*.yml]
indent_size = 2
python-elastic-apm-6.26.2/.flake8 0000664 0000000 0000000 00000000233 15216207663 0016506 0 ustar 00root root 0000000 0000000 [flake8]
exclude=
build/**,
src/**,
tests/**,
dist/**,
conftest.py,
setup.py
max-line-length=120
ignore=E731,W503,E203,BLK100,B301
python-elastic-apm-6.26.2/.github/ 0000775 0000000 0000000 00000000000 15216207663 0016675 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.github/CODEOWNERS 0000664 0000000 0000000 00000000247 15216207663 0020273 0 ustar 00root root 0000000 0000000 * @elastic/apm-agent-python
/.github/actions/ @elastic/apm-agent-python @elastic/observablt-ci
/.github/workflows/ @elastic/apm-agent-python @elastic/observablt-ci
python-elastic-apm-6.26.2/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 15216207663 0021060 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.github/ISSUE_TEMPLATE/Bug_report.md 0000664 0000000 0000000 00000001456 15216207663 0023520 0 ustar 00root root 0000000 0000000 ---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**: ...
**To Reproduce**
1. ...
2. ...
3. ...
4. ...
**Environment (please complete the following information)**
- OS: [e.g. Linux]
- Python version:
- Framework and version [e.g. Django 2.1]:
- APM Server version:
- Agent version:
**Additional context**
Add any other context about the problem here.
- Agent config options
Click to expand
```
replace this line with your agent config options
remember to mask any sensitive fields like tokens
```
- `requirements.txt`:
Click to expand
```
replace this line with your `requirements.txt`
```
python-elastic-apm-6.26.2/.github/ISSUE_TEMPLATE/Feature_request.md 0000664 0000000 0000000 00000001060 15216207663 0024542 0 ustar 00root root 0000000 0000000 ---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
python-elastic-apm-6.26.2/.github/PULL_REQUEST_TEMPLATE.md 0000664 0000000 0000000 00000000211 15216207663 0022470 0 ustar 00root root 0000000 0000000 ## What does this pull request do?
## Related issues
Closes #ISSUE
python-elastic-apm-6.26.2/.github/actions/ 0000775 0000000 0000000 00000000000 15216207663 0020335 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.github/actions/build-distribution/ 0000775 0000000 0000000 00000000000 15216207663 0024151 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.github/actions/build-distribution/action.yml 0000664 0000000 0000000 00000000666 15216207663 0026161 0 ustar 00root root 0000000 0000000 ---
name: common build distribution tasks
description: Run the build distribution
runs:
using: "composite"
steps:
- uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Build lambda layer zip
run: ./dev-utils/make-distribution.sh
shell: bash
- uses: actions/upload-artifact@v7
with:
name: build-distribution
path: ./build/
if-no-files-found: error
python-elastic-apm-6.26.2/.github/actions/packages/ 0000775 0000000 0000000 00000000000 15216207663 0022113 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.github/actions/packages/action.yml 0000664 0000000 0000000 00000001227 15216207663 0024115 0 ustar 00root root 0000000 0000000 ---
name: common package tasks
description: Run the packages
runs:
using: "composite"
steps:
- uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Override the version if there is no tag release.
run: |
if [[ "${GITHUB_REF}" != refs/tags/* ]]; then
echo "ELASTIC_CI_POST_VERSION=${{ github.run_id }}" >> "${GITHUB_ENV}"
fi
shell: bash
- name: Build packages
run: ./dev-utils/make-packages.sh
shell: bash
- name: Upload Packages
uses: actions/upload-artifact@v7
with:
name: packages
path: |
dist/*.whl
dist/*tar.gz
python-elastic-apm-6.26.2/.github/dependabot.yml 0000664 0000000 0000000 00000002303 15216207663 0021523 0 ustar 00root root 0000000 0000000 ---
version: 2
registries:
docker-elastic:
type: docker-registry
url: https://docker.elastic.co
username: ${{secrets.ELASTIC_DOCKER_USERNAME}}
password: ${{secrets.ELASTIC_DOCKER_PASSWORD}}
updates:
# Enable version updates for python
- package-ecosystem: "pip"
# Look for `requirements.txt` file in the `dev-utils` directory
directory: "/dev-utils/"
# Check for updates once a week
schedule:
interval: "weekly"
day: "sunday"
time: "22:00"
ignore:
- dependency-name: "urllib3" # ignore until lambda runtimes use OpenSSL 1.1.1+
versions: [">=2.0.0"]
# GitHub actions
- package-ecosystem: "github-actions"
directories:
- '/'
- '/.github/actions/*'
schedule:
interval: "weekly"
day: "sunday"
time: "22:00"
groups:
github-actions:
patterns:
- "*"
- package-ecosystem: "docker"
directories:
- '/'
registries: "*"
schedule:
interval: "daily"
- package-ecosystem: pre-commit
directory: "/"
schedule:
interval: 'weekly'
day: 'sunday'
time: '22:00'
open-pull-requests-limit: 5
labels:
- 'changelog:dependencies'
python-elastic-apm-6.26.2/.github/workflows/ 0000775 0000000 0000000 00000000000 15216207663 0020732 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/.github/workflows/README.md 0000664 0000000 0000000 00000005424 15216207663 0022216 0 ustar 00root root 0000000 0000000 ## CI/CD
There are 5 main stages that run on GitHub actions:
* Linting
* Test
* Packaging
* Benchmarking
* Release
The whole process should look like:
`Checkout` -> `Linting` -> `Test` -> `Packaging` -> `Benchmark` -> `Release`
### Scenarios
* Full matrix compatibility should be triggered on a daily basis or manually.
* Subset matrix compatibility runs on branches, tags and PRs basis.
* Automated release in the CI gets triggered when a tag release is created.
* Pull Requests that are only affecting the docs files should not trigger any test or similar stages that are not required.
* Builds do not get triggered automatically for Pull Requests from contributors that are not Elasticians when need to access to any GitHub Secrets.
### Compatibility matrix
Python agent supports compatibility to different python versions and frameworks, those are defined in:
* [frameworks](https://github.com/elastic/apm-agent-python/blob/main/.ci/.matrix_framework.yml) for all the PRs.
* [frameworks](https://github.com/elastic/apm-agent-python/blob/main/.ci/.matrix_framework_full.yml) for the `daily` builds.
* Python [versions](https://github.com/elastic/apm-agent-python/blob/main/.ci/.matrix_python_full.yml) for all the `daily` builds.
* Python [versions](https://github.com/elastic/apm-agent-python/blob/main/.ci/.matrix_python.yml) for all the `*nix` builds.
* Python [versions](https://github.com/elastic/apm-agent-python/blob/1e38ec53115edc70c36c6485259733a8cde02ed9/.github/workflows/test.yml#L88-L101) for all the `windows` builds.
* [Exclude list](https://github.com/elastic/apm-agent-python/blob/main/.ci/.matrix_exclude.yml) for the above entries.
### How to interact with the CI?
#### On a PR basis
Once a PR has been opened then there are two different ways you can trigger builds in the CI:
1. Commit based
1. UI based, any Elasticians can force a build through the GitHub UI
1. PR review comment-based, any Elastic employees can force a full matrix test run through a PR review comment with the following syntax: `/test matrix`.
#### Branches
Every time there is a merge to main or any release branches the whole workflow will compile and test every entry in the compatibility matrix for Linux and Windows.
### Release process
This process has been fully automated and it gets triggered when a tag release has been created.
The tag release follows the naming convention: `v...`, where ``, `` and `` are numbers as defined [here](https://github.com/elastic/apm-agent-python/blob/1e38ec53115edc70c36c6485259733a8cde02ed9/.github/workflows/release.yml#L5-L6C1)
### OpenTelemetry
Every workflow and its logs are exported to OpenTelemetry traces/logs/metrics. Those details can be seen [here](https://ela.st/oblt-ci-cd-stats) (**NOTE**: only available for Elasticians).
python-elastic-apm-6.26.2/.github/workflows/build-images.yml 0000664 0000000 0000000 00000001545 15216207663 0024024 0 ustar 00root root 0000000 0000000 ---
name: build-images
on:
workflow_dispatch: ~
permissions:
contents: read
jobs:
build-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/apm-agent-python-testing
steps:
- uses: actions/checkout@v6
- name: Login to ghcr.io
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- run: ./util.sh --action build --registry ${{ env.REGISTRY }} --name ${{ env.IMAGE_NAME }}
working-directory: .ci/docker
- run: ./util.sh --action push --registry ${{ env.REGISTRY }} --name ${{ env.IMAGE_NAME }}
working-directory: .ci/docker
python-elastic-apm-6.26.2/.github/workflows/docs-build.yml 0000664 0000000 0000000 00000000503 15216207663 0023500 0 ustar 00root root 0000000 0000000 name: docs-build
on:
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
push:
branches: [main]
merge_group: ~
permissions:
contents: read
pull-requests: read
jobs:
build:
uses: elastic/docs-actions/.github/workflows/docs-build.yml@v1
with:
enable-vale-linting: true
python-elastic-apm-6.26.2/.github/workflows/docs-deploy.yml 0000664 0000000 0000000 00000000503 15216207663 0023675 0 ustar 00root root 0000000 0000000 name: docs-deploy
on:
workflow_run:
workflows: [docs-build]
types: [completed]
permissions:
contents: read
deployments: write
id-token: write
pull-requests: write
actions: read
jobs:
deploy:
uses: elastic/docs-actions/.github/workflows/docs-deploy.yml@v1
with:
enable-vale-linting: true
python-elastic-apm-6.26.2/.github/workflows/docs-preview-cleanup.yml 0000664 0000000 0000000 00000000402 15216207663 0025505 0 ustar 00root root 0000000 0000000 name: docs-preview-cleanup
on:
pull_request_target:
branches: [main]
types: [closed]
permissions:
contents: none
deployments: write
id-token: write
jobs:
cleanup:
uses: elastic/docs-actions/.github/workflows/docs-preview-cleanup.yml@v1
python-elastic-apm-6.26.2/.github/workflows/github-commands-comment.yml 0000664 0000000 0000000 00000000431 15216207663 0026174 0 ustar 00root root 0000000 0000000 ---
name: github-commands-comment
on:
pull_request_target:
types:
- opened
permissions:
contents: read
jobs:
comment:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: elastic/oblt-actions/elastic/github-commands@v1
python-elastic-apm-6.26.2/.github/workflows/labeler.yml 0000664 0000000 0000000 00000002557 15216207663 0023074 0 ustar 00root root 0000000 0000000 name: "Issue Labeler"
on:
issues:
types: [opened]
pull_request_target:
types: [opened]
# '*: write' permissions for https://docs.github.com/en/rest/issues/labels?apiVersion=2022-11-28#add-labels-to-an-issue
permissions:
contents: read
issues: write
pull-requests: write
jobs:
triage:
runs-on: ubuntu-latest
env:
NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Get token
id: get_token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.OBS_AUTOMATION_APP_ID }}
private-key: ${{ secrets.OBS_AUTOMATION_APP_PEM }}
permission-members: read
- name: Add agent-python label
run: gh issue edit "$NUMBER" --add-label "agent-python" --repo "${{ github.repository }}"
- id: is_elastic_member
uses: elastic/oblt-actions/github/is-member-of@v1
with:
github-org: "elastic"
github-user: ${{ github.actor }}
github-token: ${{ steps.get_token.outputs.token }}
- name: Add community and triage labels
if: contains(steps.is_elastic_member.outputs.result, 'false') && github.actor != 'dependabot[bot]' && github.actor != 'elastic-observability-automation[bot]'
run: gh issue edit "$NUMBER" --add-label "community,triage" --repo "${{ github.repository }}"
python-elastic-apm-6.26.2/.github/workflows/matrix-command.yml 0000664 0000000 0000000 00000002564 15216207663 0024404 0 ustar 00root root 0000000 0000000 name: matrix-command
on:
pull_request_review:
types:
- submitted
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
permissions:
contents: read
jobs:
command-validation:
if: startsWith(github.event.review.body, '/test matrix')
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
pull-requests: write
steps:
- name: Is comment allowed?
uses: actions/github-script@v9
with:
script: |
const actorPermission = (await github.rest.repos.getCollaboratorPermissionLevel({
...context.repo,
username: context.actor
})).data.permission
const isPermitted = ['write', 'admin'].includes(actorPermission)
if (!isPermitted) {
const errorMessage = 'Only users with write permission to the repository can run GitHub commands'
await github.rest.issues.createComment({
...context.repo,
issue_number: context.issue.number,
body: errorMessage,
})
core.setFailed(errorMessage)
return
}
test:
needs:
- command-validation
uses: ./.github/workflows/test.yml
with:
full-matrix: true
ref: ${{ github.event.pull_request.head.sha }}
python-elastic-apm-6.26.2/.github/workflows/microbenchmark.yml 0000664 0000000 0000000 00000001265 15216207663 0024445 0 ustar 00root root 0000000 0000000 name: microbenchmark
on:
workflow_dispatch:
push:
branches:
- main
paths-ignore:
- '**.md'
- '**.asciidoc'
# limit the access of the generated GITHUB_TOKEN
permissions:
contents: read
jobs:
microbenchmark:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Run microbenchmark
uses: elastic/oblt-actions/buildkite/run@v1
with:
pipeline: "apm-agent-microbenchmark"
token: ${{ secrets.BUILDKITE_TOKEN }}
wait-for: false
env-vars: |
script=.ci/bench.sh
repo=apm-agent-python
sha=${{ github.sha }}
BRANCH_NAME=${{ github.ref_name }}
python-elastic-apm-6.26.2/.github/workflows/packages.yml 0000664 0000000 0000000 00000000562 15216207663 0023236 0 ustar 00root root 0000000 0000000 name: packages
on:
workflow_call: ~
pull_request:
paths-ignore:
- '**/*.md'
- '**/*.asciidoc'
push:
branches:
- main
paths-ignore:
- '**/*.md'
- '**/*.asciidoc'
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/packages
python-elastic-apm-6.26.2/.github/workflows/pre-commit.yml 0000664 0000000 0000000 00000000314 15216207663 0023527 0 ustar 00root root 0000000 0000000 name: pre-commit
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: elastic/oblt-actions/pre-commit@v1
python-elastic-apm-6.26.2/.github/workflows/release.yml 0000664 0000000 0000000 00000014306 15216207663 0023101 0 ustar 00root root 0000000 0000000 name: release
on:
push:
tags:
- "v*.*.*"
branches:
- main
permissions:
contents: read
jobs:
build-distribution:
permissions:
artifact-metadata: write
attestations: write
contents: write
id-token: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/build-distribution
- name: generate build provenance
uses: actions/attest@v4
with:
subject-path: "${{ github.workspace }}/build/dist/elastic-apm-python-lambda-layer.zip"
test:
uses: ./.github/workflows/test-release.yml
needs: build-distribution
with:
full-matrix: true
enabled: ${{ startsWith(github.ref, 'refs/tags') }}
skip-build: true
packages:
permissions:
artifact-metadata: write
attestations: write
contents: write
id-token: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/packages
- name: generate build provenance
uses: actions/attest@v4
with:
subject-path: "${{ github.workspace }}/dist/*"
publish-pypi:
needs:
- test
- packages
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v8
with:
name: packages
path: dist
- name: Upload pypi.org
if: startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
repository-url: https://upload.pypi.org/legacy/
- name: Upload test.pypi.org
if: ${{ ! startsWith(github.ref, 'refs/tags') }}
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
repository-url: https://test.pypi.org/legacy/
publish-lambda-layers:
permissions:
contents: read
id-token: write
needs:
- build-distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v8
with:
name: build-distribution
path: ./build
- uses: elastic/oblt-actions/aws/auth@v1
with:
aws-account-id: "267093732750"
- name: Publish lambda layers to AWS
if: startsWith(github.ref, 'refs/tags')
run: |
# Convert v1.2.3 to ver-1-2-3
VERSION=${GITHUB_REF_NAME/v/ver-}
VERSION=${VERSION//./-}
ELASTIC_LAYER_NAME="elastic-apm-python-${VERSION}" .ci/publish-aws.sh
- uses: actions/upload-artifact@v7
if: startsWith(github.ref, 'refs/tags')
with:
name: arn-file
path: "${{ github.workspace }}/.arn-file.md"
if-no-files-found: error
publish-docker:
needs:
- build-distribution
runs-on: ubuntu-latest
permissions:
artifact-metadata: write
attestations: write
contents: write
id-token: write
strategy:
fail-fast: false
matrix:
dockerfile: [ 'Dockerfile', 'Dockerfile.wolfi' ]
env:
DOCKER_IMAGE_NAME: docker.elastic.co/observability/apm-agent-python
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
with:
cache-binary: false
- name: Log in to the Elastic Container registry
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ${{ secrets.ELASTIC_DOCKER_REGISTRY }}
username: ${{ secrets.ELASTIC_DOCKER_USERNAME }}
password: ${{ secrets.ELASTIC_DOCKER_PASSWORD }}
- uses: actions/download-artifact@v8
with:
name: build-distribution
path: ./build
- name: Extract metadata (tags, labels)
id: docker-meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ${{ env.DOCKER_IMAGE_NAME }}
tags: |
type=raw,value=latest,prefix=test-,enable={{is_default_branch}}
type=semver,pattern={{version}}
flavor: |
suffix=${{ contains(matrix.dockerfile, 'wolfi') && '-wolfi' || '' }}
- name: Build and push image
id: docker-push
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
file: ${{ matrix.dockerfile }}
tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker-meta.outputs.labels }}
build-args: |
AGENT_DIR=./build/dist/package/python
- name: generate build provenance (containers)
uses: actions/attest@v4
with:
subject-name: "${{ env.DOCKER_IMAGE_NAME }}"
subject-digest: ${{ steps.docker-push.outputs.digest }}
push-to-registry: true
github-draft:
permissions:
contents: write
needs:
- publish-lambda-layers
if: startsWith(github.ref, 'refs/tags')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v8
with:
name: arn-file
- name: Create GitHub Draft Release
run: >-
gh release create "${GITHUB_REF_NAME}"
--title="${GITHUB_REF_NAME}"
--generate-notes
--notes-file=".arn-file.md"
--draft
env:
GH_TOKEN: ${{ github.token }}
notify:
runs-on: ubuntu-latest
if: always()
needs:
- publish-lambda-layers
- publish-pypi
- publish-docker
- github-draft
steps:
- id: check
uses: elastic/oblt-actions/check-dependent-jobs@v1
with:
jobs: ${{ toJSON(needs) }}
- if: startsWith(github.ref, 'refs/tags')
uses: elastic/oblt-actions/slack/notify-result@v1
with:
bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: "#apm-agent-python"
status: ${{ steps.check.outputs.status }}
python-elastic-apm-6.26.2/.github/workflows/run-matrix.yml 0000664 0000000 0000000 00000002556 15216207663 0023573 0 ustar 00root root 0000000 0000000 name: run-matrix
on:
workflow_call:
inputs:
include:
required: true
description: Matrix include JSON string
type: string
permissions:
contents: read
jobs:
docker:
name: "docker (version: ${{ matrix.version }}, framework: ${{ matrix.framework }})"
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 10
matrix:
include: ${{ fromJSON(inputs.include) }}
env:
# These env variables are used in the docker-compose.yml and the run_tests.sh script.
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/apm-agent-python-testing
steps:
- uses: actions/checkout@v6
- name: Run tests
run: ./tests/scripts/docker/run_tests.sh ${{ matrix.version }} ${{ matrix.framework }}
env:
LOCALSTACK_VOLUME_DIR: localstack_data
- if: success() || failure()
name: Upload JUnit Test Results
uses: actions/upload-artifact@v7
with:
name: test-results-${{ matrix.framework }}-${{ matrix.version }}
path: "**/*-python-agent-junit.xml"
- if: success() || failure()
name: Upload Coverage Reports
uses: actions/upload-artifact@v7
with:
name: coverage-reports-${{ matrix.framework }}-${{ matrix.version }}
path: "**/.coverage*"
include-hidden-files: true
python-elastic-apm-6.26.2/.github/workflows/test-docs.yml 0000664 0000000 0000000 00000003303 15216207663 0023361 0 ustar 00root root 0000000 0000000 ---
# This workflow sets the test / all status check to success in case it's a docs only PR and test.yml is not triggered
# https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks
name: test # The name must be the same as in test.yml
on:
pull_request:
paths-ignore: # This expression needs to match the paths ignored on test.yml.
- '**'
- '!**/*.md'
- '!**/*.asciidoc'
permissions:
contents: read
jobs:
all:
runs-on: ubuntu-latest
steps:
- run: 'echo "No build required"'
# As long as this workflow uses the same name than .github/workflows/test.yml and
# the test-reporter requires artifacts with the test results to exist.
# let's produce a dummy test so the test-report don't fail in this particular
# case
- name: Generate junit placeholder - to integrate with test-reporter
run: |-
cat > docs-python-agent-junit.xml << ENDOFFILE
ENDOFFILE
- if: success() || failure()
name: Upload JUnit Test Results
uses: actions/upload-artifact@v7
with:
name: test-results-docs
path: "docs-python-agent-junit.xml"
python-elastic-apm-6.26.2/.github/workflows/test-fips.yml 0000664 0000000 0000000 00000004060 15216207663 0023373 0 ustar 00root root 0000000 0000000
# run test suite inside a FIPS 140 container
name: test-fips
on:
workflow_dispatch:
schedule:
- cron: '0 4 * * 1'
permissions:
contents: read
jobs:
create-matrix:
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.generate.outputs.matrix }}
steps:
- uses: actions/checkout@v6
- id: generate
uses: elastic/oblt-actions/version-framework@v1
with:
versions-file: .ci/.matrix_python_fips.yml
frameworks-file: .ci/.matrix_framework_fips.yml
test-fips:
needs: create-matrix
runs-on: ubuntu-24.04
# https://docs.github.com/en/actions/writing-workflows/choosing-where-your-workflow-runs/running-jobs-in-a-container
# docker run -it --rm --name fipsy docker.elastic.co/wolfi/python-fips:3.12
container:
image: docker.elastic.co/wolfi/python-fips:3.12-dev
options: --user root
credentials:
username: ${{ secrets.ELASTIC_DOCKER_USERNAME }}
password: ${{ secrets.ELASTIC_DOCKER_PASSWORD }}
timeout-minutes: 30
strategy:
fail-fast: false
max-parallel: 10
matrix: ${{ fromJSON(needs.create-matrix.outputs.matrix) }}
steps:
- uses: actions/checkout@v6
- name: check that python has fips mode enabled
run: |
python3 -c 'import _hashlib; assert _hashlib.get_fips_mode() == 1'
- name: install run_tests.sh requirements
run: apk add netcat-openbsd tzdata
- name: Run tests
run: ./tests/scripts/run_tests.sh
env:
FRAMEWORK: ${{ matrix.framework }}
notify-on-failure:
if: always()
runs-on: ubuntu-24.04
needs: test-fips
steps:
- id: check
uses: elastic/oblt-actions/check-dependent-jobs@v1
with:
jobs: ${{ toJSON(needs) }}
- name: Notify in Slack
if: steps.check.outputs.status == 'failure'
uses: elastic/oblt-actions/slack/notify-result@v1
with:
bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
status: ${{ steps.check.outputs.status }}
channel-id: "#apm-agent-python"
python-elastic-apm-6.26.2/.github/workflows/test-release.yml 0000664 0000000 0000000 00000002430 15216207663 0024051 0 ustar 00root root 0000000 0000000 name: test-release
on:
workflow_call:
inputs:
full-matrix:
description: "Run the full matrix"
required: true
type: boolean
ref:
description: "The git ref of elastic/apm-agent-python to run test workflow from."
required: false
type: string
enabled:
description: "Whether to run the workfow"
required: true
type: boolean
skip-build:
description: "Skip the build distribution step"
required: false
type: boolean
default: false
workflow_dispatch:
inputs:
full-matrix:
description: "Run the full matrix"
required: true
type: boolean
enabled:
description: "Whether to run the workfow"
required: true
type: boolean
skip-build:
description: "Skip the build distribution step"
required: false
type: boolean
default: false
jobs:
test:
if: ${{ inputs.enabled }}
uses: ./.github/workflows/test.yml
with:
full-matrix: ${{ inputs.full-matrix }}
skip-build: ${{ inputs.skip-build }}
run-if-disabled:
if: ${{ ! inputs.enabled }}
runs-on: ubuntu-latest
steps:
- run: echo "do something to help with the reusable workflows with needs"
python-elastic-apm-6.26.2/.github/workflows/test-reporter.yml 0000664 0000000 0000000 00000000776 15216207663 0024306 0 ustar 00root root 0000000 0000000 ---
## Workflow to process the JUnit test results and add a report to the checks.
name: test-reporter
on:
workflow_run:
workflows:
- test
types:
- completed
permissions:
contents: read
actions: read
checks: write
jobs:
report:
runs-on: ubuntu-latest
steps:
- uses: elastic/oblt-actions/test-report@v1
with:
artifact: /test-results(.*)/
name: 'Test Report $1'
path: "**/*-python-agent-junit.xml"
reporter: java-junit
python-elastic-apm-6.26.2/.github/workflows/test.yml 0000664 0000000 0000000 00000016725 15216207663 0022447 0 ustar 00root root 0000000 0000000 name: test # The name must be the same as in test-docs.yml
on:
workflow_call:
inputs:
full-matrix:
description: "Run the full matrix"
required: true
type: boolean
ref:
description: "The git ref of elastic/apm-agent-python to run test workflow from."
required: false
type: string
skip-build:
description: "Skip the build distribution step"
required: false
type: boolean
default: false
pull_request:
paths-ignore:
- "**/*.md"
- "**/*.asciidoc"
push:
branches:
- main
paths-ignore:
- "**/*.md"
- "**/*.asciidoc"
schedule:
- cron: "0 2 * * *"
workflow_dispatch:
inputs:
full-matrix:
description: "Run the full matrix"
required: true
type: boolean
skip-build:
description: "Skip the build distribution step"
required: false
type: boolean
default: false
permissions:
contents: read
jobs:
build-distribution:
if: ${{ !inputs.skip-build }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/build-distribution
create-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.generate.outputs.matrix }}
data: ${{ steps.split.outputs.data }}
chunks: ${{ steps.split.outputs.chunks }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
- id: generate
uses: elastic/oblt-actions/version-framework@v1
with:
# Use .ci/.matrix_python_full.yml if it's a scheduled workflow, otherwise use .ci/.matrix_python.yml
versions-file: .ci/.matrix_python${{ (github.event_name == 'schedule' || github.event_name == 'push' || inputs.full-matrix) && '_full' || '' }}.yml
# Use .ci/.matrix_framework_full.yml if it's a scheduled workflow, otherwise use .ci/.matrix_framework.yml
frameworks-file: .ci/.matrix_framework${{ (github.event_name == 'schedule' || github.event_name == 'push' || inputs.full-matrix) && '_full' || '' }}.yml
excluded-file: .ci/.matrix_exclude.yml
- name: Split matrix
shell: python
id: split
run: |
import os
import json
def split(lst, n):
return [lst[i::n] for i in range(n)]
matrix = json.loads(os.environ['GENERATED_MATRIX'])
# Using the number 4 because the full matrix has roughly 400+ items
# Hence, it is split into chunks of size ~100
# We are doing this because the matrix in GH actions has a max limit of 256
chunks = split(matrix['include'], 4)
chunks_json = json.dumps(chunks)
with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
print(f'chunks={chunks_json}', file=f)
env:
GENERATED_MATRIX: ${{ steps.generate.outputs.matrix }}
chunks-0:
needs: create-matrix
uses: ./.github/workflows/run-matrix.yml
with:
include: ${{ toJSON(fromJSON(needs.create-matrix.outputs.chunks)[0]) }}
chunks-1:
needs: create-matrix
uses: ./.github/workflows/run-matrix.yml
with:
include: ${{ toJSON(fromJSON(needs.create-matrix.outputs.chunks)[1]) }}
chunks-2:
needs: create-matrix
uses: ./.github/workflows/run-matrix.yml
with:
include: ${{ toJSON(fromJSON(needs.create-matrix.outputs.chunks)[2]) }}
chunks-3:
needs: create-matrix
uses: ./.github/workflows/run-matrix.yml
with:
include: ${{ toJSON(fromJSON(needs.create-matrix.outputs.chunks)[3]) }}
windows:
name: "windows (version: ${{ matrix.version }}, framework: ${{ matrix.framework }}, asyncio: ${{ matrix.asyncio }})"
runs-on: windows-2022
strategy:
fail-fast: false
matrix:
include:
# - version: "3.6"
# framework: "none"
# asyncio: "true"
# - version: "3.7"
# framework: none
# asyncio: true
- version: "3.8"
framework: none
asyncio: true
- version: "3.9" # waiting for greenlet to have binary wheels for 3.9
framework: none
asyncio: true
env:
VERSION: ${{ matrix.version }}
FRAMEWORK: ${{ matrix.framework }}
ASYNCIO: ${{ matrix.asyncio }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.version }}
cache: pip
cache-dependency-path: "tests/requirements/reqs-${{ matrix.framework }}.txt"
- name: Install tools
run: .\scripts\install-tools.bat
- name: Run tests
run: .\scripts\run-tests.bat
- if: success() || failure()
name: Upload JUnit Test Results
uses: actions/upload-artifact@v7
with:
name: test-results-${{ matrix.framework }}-${{ matrix.version }}-asyncio-${{ matrix.asyncio }}
path: "**/*-python-agent-junit.xml"
retention-days: 1
- if: success() || failure()
name: Upload Coverage Reports
uses: actions/upload-artifact@v7
with:
name: coverage-reports-${{ matrix.framework }}-${{ matrix.version }}-asyncio-${{ matrix.asyncio }}
path: "**/.coverage*"
retention-days: 1
# This job is here to have a single status check that can be set as required.
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idneeds
# If a run contains a series of jobs that need each other, a failure applies to all jobs in the dependency chain from the point of failure onwards.
all:
if: always()
runs-on: ubuntu-latest
needs:
- chunks-0
- chunks-1
- chunks-2
- chunks-3
- windows
steps:
- id: check
uses: elastic/oblt-actions/check-dependent-jobs@v1
with:
jobs: ${{ toJSON(needs) }}
- run: ${{ steps.check.outputs.is-success }}
- if: failure() && (github.event_name == 'schedule' || github.event_name == 'push')
uses: elastic/oblt-actions/slack/notify-result@v1
with:
bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
status: ${{ steps.check.outputs.status }}
channel-id: "#apm-agent-python"
coverage:
name: Combine & check coverage.
needs: all
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
- uses: actions/setup-python@v6
with:
# Use latest Python, so it understands all syntax.
python-version: 3.11
- run: python -Im pip install --upgrade coverage[toml]
- uses: actions/download-artifact@v8
with:
pattern: coverage-reports-*
merge-multiple: true
- name: Combine coverage & fail if it's <84%.
run: |
python -Im coverage combine
python -Im coverage html --skip-covered --skip-empty
# Report and write to summary.
python -Im coverage report | sed 's/^/ /' >> $GITHUB_STEP_SUMMARY
# Report again and fail if under 84%.
python -Im coverage report --fail-under=84
- name: Upload HTML report
uses: actions/upload-artifact@v7
with:
name: html-coverage-report
path: htmlcov
- uses: geekyeggo/delete-artifact@176a747ab7e287e3ff4787bf8a148716375ca118 # 6.0.0
with:
name: coverage-reports-*
python-elastic-apm-6.26.2/.github/workflows/updatecli.yml 0000664 0000000 0000000 00000003157 15216207663 0023435 0 ustar 00root root 0000000 0000000 name: updatecli
on:
workflow_dispatch: ~
schedule:
- cron: '0 6 * * *'
permissions:
contents: read
jobs:
compose:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v6
- name: Get token
id: get_token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.OBS_AUTOMATION_APP_ID }}
private-key: ${{ secrets.OBS_AUTOMATION_APP_PEM }}
permission-contents: write
permission-pull-requests: write
- uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: elastic/oblt-actions/updatecli/run@v1
with:
command: --experimental compose diff
version-file: .tool-versions
env:
GITHUB_TOKEN: ${{ steps.get_token.outputs.token }}
- uses: elastic/oblt-actions/updatecli/run@v1
with:
command: --experimental compose apply
version-file: .tool-versions
env:
GITHUB_TOKEN: ${{ steps.get_token.outputs.token }}
- if: failure()
uses: elastic/oblt-actions/slack/send@v1
with:
bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: "#apm-agent-python"
message: ":traffic_cone: updatecli failed for `${{ github.repository }}@${{ github.ref_name }}`, @robots-ci please look what's going on "
python-elastic-apm-6.26.2/.gitignore 0000664 0000000 0000000 00000000611 15216207663 0017323 0 ustar 00root root 0000000 0000000 *.pyc
*.log
*.egg
*.db
*.pid
*.swp
.coverage*
.DS_Store
.idea
.vscode
.benchmarks
pip-log.txt
/*.egg-info
/build
/cover
/dist
/example_project/local_settings.py
/docs/html
/docs/doctrees
/example_project/*.db
tests/.schemacache
coverage
.tox
.eggs
.cache
/testdb.sql
venv
benchmarks/result*
coverage.xml
tests/*-junit.xml
*.code-workspace
.pytest_cache/
.python-version
.env
.aws
.arn-file.md
python-elastic-apm-6.26.2/.pre-commit-config.yaml 0000664 0000000 0000000 00000002047 15216207663 0021621 0 ustar 00root root 0000000 0000000 repos:
- repo: https://github.com/pycqa/isort
rev: 8.0.1
hooks:
- id: isort
exclude: "(tests/utils/stacks/linenos.py|tests/utils/stacks/linenos2.py|tests/contrib/grpc/grpc_app/.*pb2.*.py)"
- repo: https://github.com/ambv/black
rev: 26.5.1
hooks:
- id: black
language_version: python3
exclude: "(tests/utils/stacks/linenos.py|tests/utils/stacks/linenos2.py|tests/contrib/grpc/grpc_app/.*pb2.*.py)"
- repo: https://github.com/PyCQA/flake8
rev: 7.3.0
hooks:
- id: flake8
exclude: "(tests/utils/stacks/linenos.py|tests/utils/stacks/linenos2.py|tests/contrib/grpc/grpc_app/.*pb2.*.py)"
- repo: local
hooks:
- id: license-header-check
name: License header check
description: Checks the existance of license headers in all Python files
entry: ./tests/scripts/license_headers_check.sh
exclude: "(tests/utils/stacks/linenos.py|tests/utils/stacks/linenos2.py|tests/contrib/grpc/grpc_app/.*pb2.*.py)"
language: script
types: [python]
python-elastic-apm-6.26.2/.tool-versions 0000664 0000000 0000000 00000000022 15216207663 0020153 0 ustar 00root root 0000000 0000000 updatecli v0.116.3 python-elastic-apm-6.26.2/AUTHORS 0000664 0000000 0000000 00000000074 15216207663 0016406 0 ustar 00root root 0000000 0000000 See http://github.com/elastic/apm-agent-python/contributors
python-elastic-apm-6.26.2/CHANGELOG.asciidoc 0000664 0000000 0000000 00000151523 15216207663 0020333 0 ustar 00root root 0000000 0000000 ifdef::env-github[]
NOTE: Release notes are best read in our documentation at
https://www.elastic.co/guide/en/apm/agent/python/current/release-notes.html[elastic.co]
endif::[]
////
[[release-notes-x.x.x]]
==== x.x.x - YYYY-MM-DD
[float]
===== Breaking changes
[float]
===== Features
* Cool new feature: {pull}2526[#2526]
[float]
===== Bug fixes
////
//=== Unreleased
// Unreleased changes go here
// When the next release happens, nest these changes under the "Python Agent version 6.x" heading
//[float]
//===== Features
//
//[float]
//===== Bug fixes
//
[[release-notes-6.x]]
=== Python Agent version 6.x
[[release-notes-6.26.2]]
==== 6.26.2 - 2026-06-22
[float]
===== Bug fixes
* Fix httpcore instrumentation handling of default port {pull}2669[#2669]
* Handle FastAPI 0.137 ``_IncludedRouter`` in route name resolution {pull}2682[#2682]
[[release-notes-6.26.1]]
==== 6.26.1 - 2026-05-25
[float]
===== Bug fixes
* Make AWS lambda layers publication more robust against regions failure {pull}2658[#2658]
[[release-notes-6.26.0]]
==== 6.26.0 - 2026-05-25
[float]
===== Bug fixes
* Remove usage of modules and patterns deprecated on recent Python versions {pull}2531[#2531]
* Avoid warnings reading recent Flask versions {pull}2635[#2635]
* Add back instrumentation of the connection object with ``psycopg[pool]`` {pull}2460[#2460]
* Fix GRPC target reporting when it does not contain the port {pull}2584[#2584]
* Do not consider canceled span available for compression {pull}2651[#2651]
[[release-notes-6.25.0]]
==== 6.25.0 - 2025-12-23
[float]
===== Features
* Introduce `ELASTIC_APM_SKIP_SERVER_INFO` to reduce overhead on serverless with APM server 8.7.1+ {pull}2516[#2516]
* List all exported symbols in elasticapm module `__all__` {pull}2504[#2504]
[float]
===== Bug fixes
* Handle Tornado 6.5.3 `HttpHeaders` `in` operator behavior change {pull}2512[#2512]
[[release-notes-6.24.1]]
==== 6.24.1 - 2025-11-21
[float]
===== Bug fixes
* Fix handling of psycopg ServerCursor and AsyncServerCursor instrumentation {pull}2489[#2489]
* Fix contrib/opentelemetry set_status to match base signature {pull}2457[#2457]
[[release-notes-6.24.0]]
==== 6.24.0 - 2025-08-12
[float]
===== Features
* Add support for recent sanic versions {pull}2190[#2190], {pull}2194[#2194]
* Make server certificate verification mandatory in fips mode {pull}2227[#2227]
* Add support Python 3.13 {pull}2216[#2216]
* Add support for azure-data-tables package for azure instrumentation {pull}2187[#2187]
* Add span links from SNS messages {pull}2363[#2363]
[float]
===== Bug fixes
* Fix psycopg2 cursor execute and executemany signatures {pull}2331[#2331]
* Fix psycopg cursor execute and executemany signatures {pull}2332[#2332]
* Fix asgi middleware distributed tracing {pull}2334[#2334]
* Fix typing of start in Span / capture_span to float {pull}2335[#2335]
* Fix azure instrumentation client_class and metrics sets invocation {pull}2337[#2337]
* Fix mysql_connector instrumentation connection retrieval {pull}2344[#2344]
* Remove spurious Django QuerySet evaluation in case of database errors {pull}2158[#2158]
[[release-notes-6.23.0]]
==== 6.23.0 - 2024-07-30
[float]
===== Features
* Make published Docker images multi-platform with the addition of linux/arm64 {pull}2080[#2080]
[float]
===== Bug fixes
* Fix handling consumer iteration if transaction not sampled in kafka instrumentation {pull}2075[#2075]
* Fix race condition with urllib3 at shutdown {pull}2085[#2085]
* Fix compatibility with setuptools>=72 that removed test command {pull}2090[#2090]
===== Deprecations
* Python 3.6 support will be removed in version 7.0.0 of the agent
* The log shipping LoggingHandler will be removed in version 7.0.0 of the agent.
* The log shipping feature in the Flask instrumentation will be removed in version 7.0.0 of the agent.
* The log shipping feature in the Django instrumentation will be removed in version 7.0.0 of the agent.
* The OpenTracing bridge will be removed in version 7.0.0 of the agent.
* Celery 4.0 support is deprecated because it's not installable anymore with a modern pip
[[release-notes-6.22.3]]
==== 6.22.3 - 2024-06-10
[float]
===== Bug fixes
* Fix outcome in ASGI and Starlette apps on error status codes without an exception {pull}2060[#2060]
[[release-notes-6.22.2]]
==== 6.22.2 - 2024-05-20
[float]
===== Bug fixes
* Fix CI release workflow {pull}2046[#2046]
[[release-notes-6.22.1]]
==== 6.22.1 - 2024-05-17
[float]
===== Features
* Relax wrapt dependency to only exclude 1.15.0 {pull}2005[#2005]
[[release-notes-6.22.0]]
==== 6.22.0 - 2024-04-03
[float]
===== Features
* Add ability to override default JSON serialization {pull}2018[#2018]
[[release-notes-6.21.4]]
==== 6.21.4 - 2024-03-19
[float]
===== Bug fixes
* Fix urllib3 2.0.1+ crash with many args {pull}2002[#2002]
[[release-notes-6.21.3]]
==== 6.21.3 - 2024-03-08
[float]
===== Bug fixes
* Fix artifacts download in CI workflows {pull}1996[#1996]
[[release-notes-6.21.2]]
==== 6.21.2 - 2024-03-07
[float]
===== Bug fixes
* Fix artifacts upload in CI build-distribution workflow {pull}1993[#1993]
[[release-notes-6.21.1]]
==== 6.21.1 - 2024-03-07
[float]
===== Bug fixes
* Fix CI release workflow {pull}1990[#1990]
[[release-notes-6.21.0]]
==== 6.21.0 - 2024-03-06
[float]
===== Bug fixes
* Fix starlette middleware setup without client argument {pull}1952[#1952]
* Fix blocking of gRPC stream-to-stream requests {pull}1967[#1967]
* Always take into account body reading time for starlette requests {pull}1970[#1970]
* Make urllib3 transport tests more robust against local env {pull}1969[#1969]
* Clarify starlette integration documentation {pull}1956[#1956]
* Make dbapi2 query scanning for dollar quotes a bit more correct {pull}1976[#1976]
* Normalize headers in AWS Lambda integration on API Gateway v1 requests {pull}1982[#1982]
[[release-notes-6.20.0]]
==== 6.20.0 - 2024-01-10
[float]
===== Features
* Async support for dbapi2 (starting with psycopg) {pull}1944[#1944]
* Add object name to procedure call spans in dbapi2 {pull}1938[#1938]
* Add support for python 3.10 and 3.11 lambda runtimes
[float]
===== Bug fixes
* Fix asyncpg support for 0.29+ {pull}1935[#1935]
* Fix dbapi2 signature extraction to handle square brackets in table name {pull}1947[#1947]
[float]
===== Pending Deprecations
* The log shipping LoggingHandler will be removed in version 7.0.0 of the agent.
[[release-notes-6.19.0]]
==== 6.19.0 - 2023-10-11
[float]
===== Features
* Add Python 3.12 support
* Collect the `configured_hostname` and `detected_hostname` separately, and switch to FQDN for the `detected_hostname`. {pull}1891[#1891]
* Improve postgres dollar-quote detection to be much faster {pull}1905[#1905]
[float]
===== Bug fixes
* Fix url argument fetching in aiohttp_client instrumentation {pull}1890[#1890]
* Fix a bug in the AWS Lambda instrumentation when `event["headers"] is None` {pull}1907[#1907]
* Fix a bug in AWS Lambda where metadata could be incomplete, causing validation errors with the APM Server {pull}1914[#1914]
* Fix a bug in AWS Lambda where sending the partial transaction would be
recorded as an extra span {pull}1914[#1914]
[float]
===== Pending Deprecations
* The log shipping feature in the Flask instrumentation will be removed in version 7.0.0 of the agent.
[[release-notes-6.18.0]]
==== 6.18.0 - 2023-07-25
[float]
===== Features
* Add support for grpc aio server interceptor {pull}1870[#1870]
[float]
===== Bug fixes
* Fix a bug in the Elasticsearch client instrumentation which was causing loss of database context (including statement) when interacting with Elastic Cloud {pull}1878[#1878]
[[release-notes-6.17.0]]
==== 6.17.0 - 2023-07-03
[float]
==== Features
* Add `server_ca_cert_file` option to provide custom CA certificate {pull}1852[#1852]
* Add `include_process_args` option to allow users to opt-in to collecting process args {pull}1867[#1867]
[float]
===== Bug fixes
* Fix a bug in the GRPC instrumentation when reaching the maximum amount of spans per transaction {pull}1861[#1861]
[[release-notes-6.16.2]]
==== 6.16.2 - 2023-06-12
[float]
===== Bug fixes
* Fix compatibility issue with older versions of OpenSSL in lambda runtimes {pull}1847[#1847]
* Add `latest` tag to docker images {pull}1848[#1848]
* Fix issue with redacting `user:pass` in URLs in Python 3.11.4 {pull}1850[#1850]
[[release-notes-6.16.1]]
==== 6.16.1 - 2023-06-06
[float]
===== Bug fixes
* Fix release process for docker and the lambda layer {pull}1845[#1845]
[[release-notes-6.16.0]]
==== 6.16.0 - 2023-06-05
[float]
===== Features
* Add lambda layer for instrumenting AWS Lambda functions {pull}1826[#1826]
* Implement instrumentation of Azure Functions {pull}1766[#1766]
* Add support for Django to wrapper script {pull}1780[#1780]
* Add support for Starlette to wrapper script {pull}1830[#1830]
* Add `transport_json_serializer` configuration option {pull}1777[#1777]
* Add S3 bucket and key name to OTel attributes {pull}1790[#1790]
* Implement partial transaction support in AWS lambda {pull}1784[#1784]
* Add instrumentation for redis.asyncio {pull}1807[#1807]
* Add support for urllib3 v2.0.1+ {pull}1822[#1822]
* Add `service.environment` to log correlation {pull}1833[#1833]
* Add `ecs_logging` as a dependency {pull}1840[#1840]
* Add support for synchronous psycopg3 {pull}1841[#1841]
[float]
===== Bug fixes
* Fix spans being dropped if they don't have a name {pull}1770[#1770]
* Fix AWS Lambda support when `event` is not a dict {pull}1775[#1775]
* Fix deprecation warning with urllib3 2.0.0 pre-release versions {pull}1778[#1778]
* Fix `activation_method` to only send to APM server 8.7.1+ {pull}1787[#1787]
* Fix span.context.destination.service.resource for S3 spans to have an "s3/" prefix. {pull}1783[#1783]
+
*Note*: While this is considered a bugfix, it can potentially be a breaking
change in the Kibana APM app: It can break the history of the S3-Spans / metrics
for users relying on `context.destination.service.resource`. If users happen to
run agents both with and without this fix (for same or different languages), the
same S3-buckets can appear twice in the service map (with and without
s3-prefix).
* Fix instrumentation to not bubble up exceptions during instrumentation {pull}1791[#1791]
* Fix HTTP transport to not print useless and confusing stack trace {pull}1809[#1809]
[[release-notes-6.15.1]]
==== 6.15.1 - 2023-03-06
[float]
===== Bug fixes
* Fix issue with botocore instrumentation creating spans with an incorrect `service.name` {pull}1765[#1765]
* Fix a bug in the GRPC instrumentation when the agent is disabled or not recording {pull}1761[#1761]
[[release-notes-6.15.0]]
==== 6.15.0 - 2023-02-16
[float]
===== Features
* Add `service.agent.activation_method` to the metadata {pull}1743[#1743]
[float]
===== Bug fixes
* Small fix to underlying Starlette logic to prevent duplicate Client objects {pull}1735[#1735]
* Change `server_url` default to `http://127.0.0.1:8200` to avoid ipv6 ambiguity {pull}1744[#1744]
* Fix an issue in GRPC instrumentation with unsampled transactions {pull}1740[#1740]
* Fix error in async Elasticsearch instrumentation when spans are dropped {pull}1758[#1758]
[[release-notes-6.14.0]]
==== 6.14.0 - 2023-01-30
[float]
===== Features
* GRPC support {pull}1703[#1703]
* Wrapper script Flask support (experimental) {pull}1709[#1709]
[float]
===== Bug fixes
* Fix an async issue with long elasticsearch queries {pull}1725[#1725]
* Fix a minor inconsistency with the W3C tracestate spec {pull}1728[#1728]
* Fix a cold start performance issue with our AWS Lambda integration {pull}1727[#1727]
* Mark `**kwargs` config usage in our AWS Lambda integration as deprecated {pull}1727[#1727]
[[release-notes-6.13.2]]
==== 6.13.2 - 2022-11-17
[float]
===== Bug fixes
* Fix error in Elasticsearch instrumentation when spans are dropped {pull}1690[#1690]
* Lower log level for errors in APM Server version fetching {pull}1692[#1692]
* Fix for missing parent.id when logging from a DroppedSpan under a leaf span {pull}1695[#1695]
[[release-notes-6.13.1]]
==== 6.13.1 - 2022-11-03
[float]
===== Bug fixes
* Fix elasticsearch instrumentation for track_total_hits=False {pull}1687[#1687]
[[release-notes-6.13.0]]
==== 6.13.0 - 2022-10-26
[float]
===== Features
* Add support for Python 3.11
* Add backend granularity data to SQL backends as well as Cassandra and pymongo {pull}1585[#1585], {pull}1639[#1639]
* Add support for instrumenting the Elasticsearch 8 Python client {pull}1642[#1642]
* Add `*principal*` to default `sanitize_field_names` configuration {pull}1664[#1664]
* Add docs and better support for custom metrics, including in AWS Lambda {pull}1643[#1643]
* Add support for capturing span links from AWS SQS in AWS Lambda {pull}1662[#1662]
[float]
===== Bug fixes
* Fix Django's `manage.py check` when agent is disabled {pull}1632[#1632]
* Fix an issue with long body truncation for Starlette {pull}1635[#1635]
* Fix an issue with transaction outcomes in Flask for uncaught exceptions {pull}1637[#1637]
* Fix Starlette instrumentation to make sure transaction information is still present during exception handling {pull}1674[#1674]
[[release-notes-6.12.0]]
==== 6.12.0 - 2022-09-07
[float]
===== Features
* Add redis query to context data for redis instrumentation {pull}1406[#1406]
* Add AWS request ID to all botocore spans (at `span.context.http.request.id`) {pull}1625[#1625]
[float]
===== Bug fixes
* Differentiate Lambda URLs from API Gateway in AWS Lambda integration {pull}1609[#1609]
* Restrict the size of Django request bodies to prevent APM Server rejection {pull}1610[#1610]
* Restrict length of `exception.message` for exceptions captured by the agent {pull}1619[#1619]
* Restrict length of Starlette request bodies {pull}1549[#1549]
* Fix error when using elasticsearch(sniff_on_start=True) {pull}1618[#1618]
* Improve handling of ignored URLs and capture_body=off for Starlette {pull}1549[#1549]
* Fix possible error in the transport flush for Lambda functions {pull}1628[#1628]
[[release-notes-6.11.0]]
==== 6.11.0 - 2022-08-09
[float]
===== Features
* Added lambda support for ELB triggers {pull}1605[#1605]
[[release-notes-6.10.2]]
==== 6.10.2 - 2022-08-04
[float]
===== Bug fixes
* Fixed an issue with non-integer ports in Django {pull}1590[#1590]
* Fixed an issue with non-integer ports in Redis {pull}1591[#1591]
* Fixed a performance issue for local variable shortening via `varmap()` {pull}1593[#1593]
* Fixed `elasticapm.label()` when a Client object is not available {pull}1596[#1596]
[[release-notes-6.10.1]]
==== 6.10.1 - 2022-06-30
[float]
===== Bug fixes
* Fix an issue with Kafka instrumentation and unsampled transactions {pull}1579[#1579]
[[release-notes-6.10.0]]
==== 6.10.0 - 2022-06-22
[float]
===== Features
* Add instrumentation for https://github.com/aio-libs/aiobotocore[`aiobotocore`] {pull}1520[#1520]
* Add instrumentation for https://kafka-python.readthedocs.io/en/master/[`kafka-python`] {pull}1555[#1555]
* Add API for span links, and implement span link support for OpenTelemetry bridge {pull}1562[#1562]
* Add span links to SQS ReceiveMessage call {pull}1575[#1575]
* Add specific instrumentation for SQS delete/batch-delete {pull}1567[#1567]
* Add `trace_continuation_strategy` setting {pull}1564[#1564]
[float]
===== Bug fixes
* Fix return for `opentelemetry.Span.is_recording()` {pull}1530[#1530]
* Fix error logging for bad SERVICE_NAME config {pull}1546[#1546]
* Do not instrument old versions of Tornado > 6.0 due to incompatibility {pull}1566[#1566]
* Fix transaction names for class based views in Django 4.0+ {pull}1571[#1571]
* Fix a problem with our logging handler failing to report internal errors in its emitter {pull}1568[#1568]
[[release-notes-6.9.1]]
==== 6.9.1 - 2022-03-30
[float]
===== Bug fixes
* Fix `otel_attributes`-related regression with older versions of APM Server (<7.16) {pull}1510[#1510]
[[release-notes-6.9.0]]
==== 6.9.0 - 2022-03-29
[float]
===== Features
* Add OpenTelemetry API bridge {pull}1411[#1411]
* Change default for `sanitize_field_names` to sanitize `*auth*` instead of `authorization` {pull}1494[#1494]
* Add `span_stack_trace_min_duration` to replace deprecated `span_frames_min_duration` {pull}1498[#1498]
* Enable exact_match span compression by default {pull}1504[#1504]
* Allow parent celery tasks to specify the downstream `parent_span_id` in celery headers {pull}1500[#1500]
[float]
===== Bug fixes
* Fix Sanic integration to properly respect the `capture_body` config {pull}1485[#1485]
* Lambda fixes to align with the cross-agent spec {pull}1489[#1489]
* Lambda fix for custom `service_name` {pull}1493[#1493]
* Change default for `stack_trace_limit` from 500 to 50 {pull}1492[#1492]
* Switch all duration handling to use `datetime.timedelta` objects {pull}1488[#1488]
[[release-notes-6.8.1]]
==== 6.8.1 - 2022-03-09
[float]
===== Bug fixes
* Fix `exit_span_min_duration` and disable by default {pull}1483[#1483]
[[release-notes-6.8.0]]
==== 6.8.0 - 2022-02-22
[float]
===== Features
* use "unknown-python-service" as default service name if no service name is configured {pull}1438[#1438]
* add transaction name to error objects {pull}1441[#1441]
* don't send unsampled transactions to APM Server 8.0+ {pull}1442[#1442]
* implement snapshotting of certain configuration during transaction lifetime {pull}1431[#1431]
* propagate traceparent IDs via Celery {pull}1371[#1371]
* removed Python 2 compatibility shims {pull}1463[#1463]
** Note: Python 2 support was already removed with version 6.0 of the agent, this now removes unused compatibilit shims.
[float]
===== Bug fixes
* fix span compression for redis, mongodb, cassandra and memcached {pull}1444[#1444]
* fix recording of status_code for starlette {pull}1466[#1466]
* fix aioredis span context handling {pull}1462[#1462]
[[release-notes-6.7.2]]
==== 6.7.2 - 2021-12-07
[float]
===== Bug fixes
* fix AttributeError in sync instrumentation of httpx {pull}1423[#1423]
* add setting to disable span compression, default to disabled {pull}1429[#1429]
[[release-notes-6.7.1]]
==== 6.7.1 - 2021-11-29
[float]
===== Bug fixes
* fix an issue with Sanic exception tracking {pull}1414[#1414]
* asyncpg: Limit SQL queries in context data to 10000 characters {pull}1416[#1416]
[[release-notes-6.7.0]]
==== 6.7.0 - 2021-11-17
[float]
===== Features
* Add support for Sanic framework {pull}1390[#1390]
[float]
===== Bug fixes
* fix compatibility issues with httpx 0.21 {pull}1403[#1403]
* fix `span_compression_exact_match_max_duration` default value {pull}1407[#1407]
[[release-notes-6.6.3]]
==== 6.6.3 - 2021-11-15
[float]
===== Bug fixes
* fix an issue with `metrics_sets` configuration referencing the `TransactionMetricSet` removed in 6.6.2 {pull}1397[#1397]
[[release-notes-6.6.2]]
==== 6.6.2 - 2021-11-10
[float]
===== Bug fixes
* Fix an issue where compressed spans would count against `transaction_max_spans` {pull}1377[#1377]
* Make sure HTTP connections are not re-used after a process fork {pull}1374[#1374]
* Fix an issue with psycopg2 instrumentation when multiple hosts are defined {pull}1386[#1386]
* Update the `User-Agent` header to the new https://github.com/elastic/apm/pull/514[spec] {pull}1378[#1378]
* Improve status_code handling in AWS Lambda integration {pull}1382[#1382]
* Fix `aiohttp` exception handling to allow for non-500 responses including `HTTPOk` {pull}1384[#1384]
* Force transaction names to strings {pull}1389[#1389]
[float]
===== Other
* Remove unused `http.request.socket.encrypted` context field {pull}1332[#1332]
* Remove unused transaction metrics (APM Server handles these metrics instead) {pull}1388[#1388]
[[release-notes-6.6.1]]
==== 6.6.1 - 2021-11-02
[float]
===== Bug fixes
* Fix some context fields and metadata handling in AWS Lambda support {pull}1368[#1368]
[[release-notes-6.6.0]]
==== 6.6.0 - 2021-10-18
[float]
===== Features
* Add experimental support for AWS lambda instrumentation {pull}1193[#1193]
* Add support for span compression {pull}1321[#1321]
* Auto-infer destination resources for easier instrumentation of new resources {pull}1359[#1359]
* Add support for dropped span statistics {pull}1327[#1327]
[float]
===== Bug fixes
* Ensure that Prometheus histograms are encoded correctly for APM Server {pull}1354[#1354]
* Remove problematic (and duplicate) `event.dataset` from logging integrations {pull}1365[#1365]
* Fix for memcache instrumentation when configured with a unix socket {pull}1357[#1357]
[[release-notes-6.5.0]]
==== 6.5.0 - 2021-10-04
[float]
===== Features
* Add instrumentation for Azure Storage (blob/table/fileshare) and Azure Queue {pull}1316[#1316]
[float]
===== Bug fixes
* Improve span coverage for `asyncpg` {pull}1328[#1328]
* aiohttp: Correctly pass custom client to tracing middleware {pull}1345[#1345]
* Fixed an issue with httpx instrumentation {pull}1337[#1337]
* Fixed an issue with Django 4.0 removing a private method {pull}1347[#1347]
[[release-notes-6.4.0]]
==== 6.4.0 - 2021-08-31
[float]
===== Features
* Rename the experimental `log_ecs_formatting` config to `log_ecs_reformatting` {pull}1300[#1300]
* Add support for Prometheus histograms {pull}1165[#1165]
[float]
===== Bug fixes
* Fixed cookie sanitization when Cookie is capitalized {pull}1301[#1301]
* Fix a bug with exception capturing for bad UUIDs {pull}1304[#1304]
* Fix potential errors in json serialization {pull}1203[#1203]
* Fix an issue with certain aioredis commands {pull}1308[#1308]
[[release-notes-6.3.3]]
==== 6.3.3 - 2021-07-14
[float]
===== Bug fixes
* ensure that the elasticsearch instrumentation handles DroppedSpans correctly {pull}1190[#1190]
[[release-notes-6.3.2]]
==== 6.3.2 - 2021-07-07
[float]
===== Bug fixes
* Fix handling of non-http scopes in Starlette/FastAPI middleware {pull}1187[#1187]
[[release-notes-6.3.1]]
==== 6.3.1 - 2021/07/07
[float]
===== Bug fixes
* Fix issue with Starlette/FastAPI hanging on startup {pull}1185[#1185]
[[release-notes-6.3.0]]
==== 6.3.0 - 2021/07/06
[float]
===== Features
* Add additional context information about elasticsearch client requests {pull}1108[#1108]
* Add `use_certifi` config option to allow users to disable `certifi` {pull}1163[#1163]
[float]
===== Bug fixes
* Fix for Starlette 0.15.0 error collection {pull}1174[#1174]
* Fix for Starlette static files {pull}1137[#1137]
[[release-notes-6.2.3]]
==== 6.2.3 - 2021/06/28
[float]
===== Bug fixes
* suppress the default_app_config attribute in Django 3.2+ {pull}1155[#1155]
* bump log level for multiple set_client calls to WARNING {pull}1164[#1164]
* fix issue with adding disttracing to SQS messages when dropping spans {pull}1170[#1170]
[[release-notes-6.2.2]]
==== 6.2.2 - 2021/06/07
[float]
===== Bug fixes
* Fix an attribute access bug introduced in 6.2.0 {pull}1149[#1149]
[[release-notes-6.2.1]]
==== 6.2.1 - 2021/06/03
[float]
===== Bug fixes
* catch and log exceptions in interval timer threads {pull}1145[#1145]
[[release-notes-6.2.0]]
==== 6.2.0 - 2021/05/31
[float]
===== Features
* Added support for aioredis 1.x {pull}1082[#2526]
* Added support for aiomysql {pull}1107[#1107]
* Added Redis pub/sub instrumentation {pull}1129[#1129]
* Added specific instrumentation for AWS SQS {pull}1123[#1123]
[float]
===== Bug fixes
* ensure metrics are flushed before agent shutdown {pull}1139[#1139]
* added safeguard for exceptions in processors {pull}1138[#1138]
* ensure sockets are closed which were opened for cloud environment detection {pull}1134[#1134]
[[release-notes-6.1.3]]
==== 6.1.3 - 2021/04/28
[float]
===== Bug fixes
* added destination information to asyncpg instrumentation {pull}1115[#1115]
* fixed issue with collecting request meta data with Django REST Framework {pull}1117[#1117]
* fixed httpx instrumentation for newly released httpx 0.18.0 {pull}1118[#1118]
[[release-notes-6.1.2]]
==== 6.1.2 - 2021/04/14
[float]
===== Bug fixes
* fixed issue with empty transaction name for the root route with Django {pull}1095[#1095]
* fixed on-the-fly initialisation of Flask apps {pull}1099[#1099]
[[release-notes-6.1.1]]
==== v6.1.1 - 2021/04/08
[float]
===== Bug fixes
* fixed a validation issue with the newly introduced instrumentation for S3, SNS and DynamoDB {pull}1090[#1090]
[[release-notes-6.1.0]]
==== v6.1.0 - 2021/03/31
[float]
===== Features
* Add global access to Client singleton object at `elasticapm.get_client()` {pull}1043[#1043]
* Add `log_ecs_formatting` config option {pull}1058[#1058] {pull}1063[#1063]
* Add instrumentation for httplib2 {pull}1031[#1031]
* Add better instrumentation for some AWS services (S3, SNS, DynamoDB) {pull}1054[#1054]
* Added beta support for collecting metrics from prometheus_client {pull}1083[#1083]
[float]
===== Bug fixes
* Fix for potential `capture_body: error` hang in Starlette/FastAPI {pull}1038[#1038]
* Fix a rare error around processing stack frames {pull}1012[#1012]
* Fix for Starlette/FastAPI to correctly capture request bodies as strings {pull}1042[#1041]
* Fix transaction names for Starlette Mount routes {pull}1037[#1037]
* Fix for elastic excepthook arguments {pull}1050[#1050]
* Fix issue with remote configuration when resetting config values {pull}1068[#1068]
* Use a label for the elasticapm Django app that is compatible with Django 3.2 validation {pull}1064[#1064]
* Fix an issue with undefined routes in Starlette {pull}1076[#1076]
[[release-notes-6.0.0]]
==== v6.0.0 - 2021/02/01
[float]
===== Breaking changes
* Python 2.7 and 3.5 support has been deprecated. The Python agent now requires Python 3.6+ {pull}1021[#1021]
* No longer collecting body for `elasticsearch-py` `update` and `delete_by_query` {pull}1013[#1013]
* Align `sanitize_field_names` config with the
https://github.com/elastic/apm/blob/3fa78e2a1eeea81c73c2e16e96dbf6b2e79f3c64/specs/agents/sanitization.md[cross-agent spec].
If you are using a non-default `sanitize_field_names`, surrounding each of your entries with stars (e.g.
`*secret*`) will retain the old behavior. {pull}982[#982]
* Remove credit card sanitization for field values. This improves performance, and the security value of this check was
dubious anyway. {pull}982[#982]
* Remove HTTP querystring sanitization. This improves performance, and is meant to standardize behavior across the
agents, as defined in https://github.com/elastic/apm/pull/334. {pull}982[#982]
* Remove `elasticapm.tag()` (deprecated since 5.0.0) {pull}1034[#1034]
[float]
===== Bug fixes
* Fix for GraphQL span spamming from scalar fields with required flag {pull}1015[#1015]
[[release-notes-5.x]]
=== Python Agent version 5.x
[[release-notes-5.10.1]]
==== v5.10.1 - 2021/01/20
[float]
===== Bug fixes
* Fix for custom serializers in elasticsearch-py {pull}998[#998]
* Fix large query truncation in psycopg2 {pull}994[#994]
* Fix memory metrics reporting when `memory.usage_in_bytes` is unavailable {pull}987[#987]
* Fix for Starlette/FastAPI integration to properly obey `enabled` config {pull}1000[#1000]
[[release-notes-5.10.0]]
==== v5.10.0 - 2020/11/18
[float]
===== Features
* Implement "sample_rate" property for transactions and spans, and propagate through tracestate {pull}891[#891]
* Add support for callbacks on config changes {pull}912[#912]
* Override `sys.excepthook` to catch all exceptions {pull}943[#943]
* Implement `log_level` config (supports central config) {pull}946[#946]
* Implement `transaction_ignore_urls` config (supports central config) {pull}923[#923]
* Add public API to retrieve trace parent header {pull}956[#956]
* Added support for cgroup memory metrics {pull}846[#846]
[float]
===== Bug fixes
* Fix to collect the whole query body in `elasticsearch-py` {pull}940[#940]
* Fix for GraphQL transaction naming {pull}881[#881]
* Ensure that query string max length is maintained after sanitization {pull}968[#968]
* Adapted kubernetes kubepod regex for detecting kubernetes metadata {pull}958[#958]
* Updated Starlette integration to use the route as transaction name if possible {pull}957[#957]
[[release-notes-5.9.0]]
==== v5.9.0 - 2020/09/23
[float]
===== Features
* Add instrumentation support for https://github.com/encode/httpx[`httpx`] and https://github.com/encode/httpcore[`httpcore`] {pull}898[#898]
* Implement "outcome" property for transactions and spans {pull}899[#899]
* Add support for `asyncpg` {pull}889[#889]
[float]
===== Bug fixes
* Fix validation of config to properly require `required` config items. {pull}927[#927]
[[release-notes-5.8.1]]
==== v5.8.1 - 2020/07/13
[float]
===== Bug fixes
* Updated CLOUD_PROVIDER config to allow for new options defined in https://github.com/elastic/apm/issues/289[#289] {pull}878[#878]
* Fixed a bug in AWS metadata collection on docker containers in AWS Elastic Beanstalk {pull}884[#884]
* Fixed a bug in local variable serialization that could occur in multi-threaded applications {pull}885[#885]
[[release-notes-5.8.0]]
==== v5.8.0 - 2020/06/30
[float]
===== Features
* Added graphql (graphene) support {pull}850[#850]
* Collect cloud provider metadata {pull}826[#826]
* Added `sanitize_field_names` config {pull}860[#860]
[float]
===== Bug fixes
* Fix header fetching for ASGI implementations {pull}856[#856]
[[release-notes-5.7.0]]
==== v5.7.0 - 2020/06/11
[float]
===== Features
* capture number of affected rows for INSERT/UPDATE/DELETE SQL queries {pull}614[#614]
* Added instrumentation for AsyncElasticsearch {pull}843[#843]
[float]
===== Bug fixes
* Added error handling around frame processing in Django {pull}837[#837]
* Limit SQL queries in context data to 10000 characters {pull}842[#842]
* Omit the "sync" property on spans by default {pull}854[#854]
* Update the pid/ppid in transport metadata when they change {pull}825[#825]
* Added better error handling around closing the transport {pull}838[#838]
* Fixed an issue with the django admin command not detecting misconfigured server urls {pull}855[#855]
[[release-notes-5.6.0]]
==== v5.6.0 - 2020/05/06
[float]
===== New features
* Added SERVICE_NODE_NAME config {pull}592[#592]
* Added instrumentation support for https://github.com/pinterest/pymemcache[`pymemcache`] {pull}812[#812]
* Added new configuration options `enabled` and `recording` {pull}790[#790]
[float]
===== Bug fixes
* Fixed an issue with metrics collection raising RuntimeErrors {pull}802[#802]
* Fixed an issue with getting extended destination data from pymongo {pull}797[#797]
* Fixed an issue with Tornado instrumentation when Tornado isn't the "main" framework {pull}813[#813]
* Fixed an issue with streaming requests being consumed by the agent even if capture_body is disabled {pull}817[#817]
[float]
===== Pending Deprecations
* Python 2.7 suppot will be dropped in version 6.0 of the agent.
[[release-notes-5.5.2]]
==== v5.5.2 - 2020/03/20
[float]
===== Bug fixes
* Fixed an issue with Redis using unix domain sockets and destination information {pull}766[#766]
[[release-notes-5.5.1]]
==== v5.5.1 - 2020/03/19
[float]
===== Bug fixes
* Fixed Starlette middleware when capturing request body while the content-type header is absent {pull}763[#763]
[[release-notes-5.5.0]]
==== v5.5.0 - 2020/03/19
[float]
===== Features
* Added destination information to database/HTTP spans, used for service maps {pull}618[#618]
[float]
===== Deprecations
* *Python 3.4 is no longer supported.*
[[release-notes-5.4.3]]
==== v5.4.3 - 2020/02/27
https://github.com/elastic/apm-agent-python/compare/v5.4.2\...v5.4.3[Check the diff]
[float]
===== Bug fixes
* fixed a bug in our aiohttp.client support if used with a yarl URL {pull}733[#733]
[[release-notes-5.4.2]]
==== v5.4.2 - 2020/02/18
https://github.com/elastic/apm-agent-python/compare/v5.4.1\...v5.4.2[Check the diff]
[float]
===== Bug fixes
* fixed a bug in our celery implementation related to the threading refactor in 5.4.0 {pull}724[#724]
[[release-notes-5.4.1]]
==== v5.4.1 - 2020/02/18
https://github.com/elastic/apm-agent-python/compare/v5.4.0\...v5.4.1[Check the diff]
[float]
===== Bug fixes
* fixed an issue with a DEBUG log message raising an error in some cases {pull}722[#722]
[[release-notes-5.4.0]]
==== v5.4.0 - 2020/02/17
https://github.com/elastic/apm-agent-python/compare/v5.3.3\...v5.4.0[Check the diff]
[float]
===== Deprecations
This will be the last minor release to support the following versions:
* Python 3.4
* Django 1.8, 1.9 and 1.10
* Flask < 1.0
In addition, as of this release we only supported capturing extended
information on Elasticsearch queries when using keyword arguments with the
elasticsearch-py API. This is in keeping with the
https://elasticsearch-py.readthedocs.io/en/master/api.html#api-documentation[upstream policy]
of positional arguments being unsupported. {pull}697[#697]
[float]
===== New Features
* Refactored spawning of background threads {pull}636[#636]
* Added support for aiohttp client and server {pull}659[#659]
* Added support for tornado web framework {pull}661[#661]
* Added support for starlette/fastapi {pull}694[#694]
* Added support for W3C `traceparent` and `tracestate` headers {pull}660[#660]
* Added Django 3.0 and Flask 1.1 to the support matrix {pull}667[#667]
* Added support for aiopg {pull}668[#668]
* Use Span ID as parent ID in errors if an error happens inside a span {pull}669[#669]
* Added experimental support for API Key authentication {pull}679[#679]
[float]
===== Bug fixes
* introduced workaround to avoid instrumenting twice in rare cases {pull}708[#708]
[[release-notes-5.3.3]]
==== v5.3.3 - 2020/01/14
https://github.com/elastic/apm-agent-python/compare/v5.3.2\...v5.3.3[Check the diff]
[float]
===== Bug fixes
* Fixed an issue with OpenTracing bridge and dropped spans {pull}687[#687]
* Fixed bug that would make the agent ignore the `hostname` configuration setting {pull}689[#689]
[[release-notes-5.3.2]]
==== v5.3.2 - 2019/11/25
https://github.com/elastic/apm-agent-python/compare/v5.3.1\...v5.3.2[Check the diff]
[float]
===== Bug fixes
* Added support for IPv6 address format when parsing urls {pull}649[#649]
[[release-notes-5.3.1]]
==== v5.3.1 - 2019/11/18
https://github.com/elastic/apm-agent-python/compare/v5.3.0\...v5.3.1[Check the diff]
[float]
===== New Features
* Added support for shortening dicts in local variables {pull}638[#638]
[[release-notes-5.3.0]]
==== v5.3.0 - 2019/11/14
https://github.com/elastic/apm-agent-python/compare/v5.2.3\...v5.3.0[Check the diff]
[float]
===== New Features
* Added instrumentation for mysql-connector and pymysql {pull}603[#603]
* Implemented stack_trace_limit configuration option {pull}623[#623]
* Autoinsert tracing middleware in django settings {pull}625[#625]
[float]
===== Bug fixes
* Fixed issue with transactions not being captured when errors occur in Flask {pull}635[#635]
[[release-notes-5.2.3]]
==== v5.2.3 - 2019/11/13
https://github.com/elastic/apm-agent-python/compare/v5.2.2\...v5.2.3[Check the diff]
[float]
===== Bug fixes
* Ensure that metrics with value 0 are not collected if they have the `reset_on_collect` flag set {pull}615[#615]
* Unwrap postgres cursor for newly introduced psycopg2 extensions {pull}621[#621]
* Fix pod ID for kubernetes when using the systemd cgroup driver {pull}631[#631]
[[release-notes-5.2.2]]
==== v5.2.2 - 2019/10/16
https://github.com/elastic/apm-agent-python/compare/v5.2.1\...v5.2.2[Check the diff]
[float]
===== Bug fixes
* Fixed an issue where a `cpu_total` of `0` could cause an exception {pull}610[#610], {pull}611[#611]
[[release-notes-5.2.1]]
==== v5.2.1 - 2019/10/09
https://github.com/elastic/apm-agent-python/compare/v5.2.0\...v5.2.1[Check the diff]
[float]
===== Bug fixes
* Fixed an issue with DroppedSpans and logging integration {pull}602[#602]
* Fixed an issue with processors not being applied to chained exceptions {pull}604[#604]
[[release-notes-5.2.0]]
==== v5.2.0 - 2019/10/02
https://github.com/elastic/apm-agent-python/compare/v5.1.2\...v5.2.0[Check the diff]
[float]
===== New Features
* Added automatic tagging of LogRecord objects with transaction, trace, and span IDs via a LogRecordFactory (Python 3.2+) {pull}520[#520], {pull}586[#586]
* Added `logging` filter and record factory for adding transaction, trace, and span IDs {pull}520[#520], {pull}586[#586]
* Added `structlog` processor for adding transaction, trace, and span IDs {pull}520[#520], {pull}586[#586]
* Added new public API calls for getting transaction, trace, and span IDs {pull}520[#520], {pull}586[#586]
* Added support for chained exceptions in Python 3 {pull}596[#596].
Note that chained exceptions will be captured and stored in Elasticsearch, but not yet
visualized in the APM UI. The UI component will be released in an upcoming Kibana release (7.5 or later).
* Added support for using `structlog` for agent logging {pull}591[#591]
[float]
===== Bug fixes
* Drop events immediately if a processor returns a falsy value {pull}585[#585]
[[release-notes-5.1.2]]
==== v5.1.2 - 2019/09/04
https://github.com/elastic/apm-agent-python/compare/v5.1.1\...v5.1.2[Check the diff]
[float]
===== Bugfixes
* Fixed an issue with http server_url and `'VERIFY_SERVER_CERT': False` {pull}570[#570], {pull}578[#578]
* Fixed instrumenting of psycopg2 when using their context manager interface {pull}577[#577], {pull}580[#580]
* Fixed zerorpc tests {pull}581[#581]
* Fixed to correctly check if gevent has patched threading.local {pull}579[#579]
[[release-notes-5.1.1]]
==== v5.1.1 - 2019/08/22
https://github.com/elastic/apm-agent-python/compare/v5.1.0\...v5.1.1[Check the diff]
[float]
===== Bug fixes
* Fixed an issue with empty responses from APM Server's config endpoint {pull}562[#562], {pull}563[#563]
* Fixed Windows tests by avoiding time.sleep in breakdown metrics tests {pull}537[#537], {pull}550[#550]
* Fixed container ID matching to match CloudFoundry Garden container IDs {pull}523[#523], {pull}564[#564]
* Fixed an issue in the urllib instrumentation if no port is set {pull}567[#567]
[float]
===== Other
* Added Python 3.8 RC to the test matrix {pull}565[#565]
[[release-notes-5.1.0]]
==== v5.1.0 - 2019/08/14
https://github.com/elastic/apm-agent-python/compare/v5.0.0\...v5.1.0[Check the diff]
[float]
===== Security issues
* This release fixes CVE-2019-7617
[float]
===== New Features
* Added support for global labels which will be applied to every transaction/error/metric {pull}549[#549]
* Added support for `NO_PROXY` environment variable {pull}458[#458], {pull}551[#551]
[float]
===== Bugfixes
* Fixed an issue with using callables in set_context with unsampled transactions {pull}541[#541], {pull}542[#542]
* Limited the length of error.culprit to 1024 characters {pull}491[#491], {pull}543[#543]
* Fixed an issue with the `instrument` config option {pull}546[#546], {pull}547[#547]
* Limited the amount of distinct metrics to 1000 {pull}540[#540], {pull}544[#544]
[[release-notes-5.0.0]]
==== v5.0.0 - 2019/07/31
https://github.com/elastic/apm-agent-python/compare/v4.2.2\...v5.0.0[Check the diff]
[float]
===== Breaking changes
* Implemented type/subtype/action hierachy for spans. Ensure that you run at least APM Server 6.6 {pull}377[#377]
* renamed tags to labels and changed API. The old API remains for backwards compatibility until 6.0 of the agent {pull}538[#538]
[float]
===== Other changes
* Added support for recording breakdown metrics {pull}535[#535]
* Added support for central config management {pull}511[#511]
* Added instrumentation for `urllib2` (Python 2) / `urllib.request` (Python 3) {pull}464[#464]
* Added `disable_metrics` setting {pull}399[#399]
* Updated elasticsearch instrumentation for 7.x {pull}482[#482], {pull}483[#483]
* Fixed an issue with opentracing-python 2.1 {pull}471[#471]
* Fixed an issue with certificate pinning {pull}497[#497]
* Lowered log level of transport success messages {pull}527[#527], {pull}531[#531]
[[release-notes-4.x]]
=== Python Agent version 4.x
[[release-notes-4.2.2]]
==== v4.2.2 - 2019/04/10
https://github.com/elastic/apm-agent-python/compare/v4.2.1\...v4.2.2[Check the diff]
* Fixed an issue with Celery and the prefork worker pool {pull}444[#444]
* Fixed an issue when running uwsgi without a master process {pull}446[#446]
* Fixed an issue with gevent/eventlet on Python 3.7 {pull}451[#451], {pull}454[#454]
* Introduced `IntervalTimer` and use it instead of `threading.Timer` {pull}452[#452]
* Added license header check as pre-commit hook {pull}456[#456]
[[release-notes-4.2.1]]
==== v4.2.1 - 2019/03/22
https://github.com/elastic/apm-agent-python/compare/v4.2.0\...v4.2.1[Check the diff]
* Fixed an issue with the certificate pinning feature introduced in 4.2.0 {pull}433[#433], {pull}434[#434]
* Fixed incompatibility with eventlet introduced in 4.2.0 {pull}435[#435], {pull}436[#436]
[[release-notes-4.2.0]]
==== v4.2.0 - 2019/03/20
https://github.com/elastic/apm-agent-python/compare/v4.1.0\...v4.2.0[Check the diff]
* Implemented a new transport queue, which should avoid certain deadlock scenarios {pull}411[#411]
* Implemented server certificate pinning {pull}405[#405]
* Moved context.url to context.http.url for requests/urllib3 spans {pull}393[#393], {pull}394[#394]
* Added support for using route as transaction name in Django 2.2+ {pull}86[#86], {pull}396[#396]
* Added some randomness to time between requests to APM Server {pull}426[#426]
* Fixed an issue with custom user models in Django using non-string usernames {pull}397[#397], {pull}398[#398]
* Fixed an issue with sending kubernetes metadata to the API {pull}401[#401], {pull}402[#402]
* Fixed an issue with parsing /proc/stat in RHEL/centos 6 {pull}406[#406], {pull}407[#407]
* Added copyright header to all files, and a CI check {pull}429[#429]
[[release-notes-4.1.0]]
==== v4.1.0 - 2019/01/29
https://github.com/elastic/apm-agent-python/compare/v4.0.3\...v4.1.0[Check the diff]
* Added support for collecting system and process metrics {pull}361[#361]
* Added an OpenTracing bridge {pull}388[#388]
* Added `transaction.sampled` to errors {pull}371[#371]
* Added `transaction.type` to errors {pull}391[#391]
* Added parsing of `/proc/self/cgroup` to capture container meta data {pull}352[#352]
* Added option to configure logging for Flask using a log level {pull}344[#344]
* Added `capture_headers` config option {pull}392[#392]
[[release-notes-4.0.3]]
==== v4.0.3 - 2018/12/24
https://github.com/elastic/apm-agent-python/compare/v4.0.2\...v4.0.3[Check the diff]
* Implemented de-dotting of tag names and context keys {pull}353[#353]
* wrote a quickfix for the boto3/botocore instrumentation {pull}367[#367]
* Fixed an issue with psycopg2 and encoded strings {pull}366[#366]
[[release-notes-4.0.2]]
==== v4.0.2 - 2018/12/05
https://github.com/elastic/apm-agent-python/compare/v4.0.1\...v4.0.2[Check the diff]
* Fixed another issue in the new v2 transport {pull}351[#351]
[[release-notes-4.0.1]]
==== v4.0.1 - 2018/11/16
https://github.com/elastic/apm-agent-python/compare/v4.0.0\...v4.0.1[Check the diff]
* Fixed an issue with instrumenting redis-py 3.0+
* Fixed a multithreading issue that occurs when using threaded workers {pull}335[#335]
[[release-notes-4.0.0]]
==== v4.0.0 - 2018/11/14
https://github.com/elastic/apm-agent-python/compare/v3.0.2\...v4.0.0[Check the diff]
**BREAKING** Version 4 of the agent implements a new wire protocol for communicating with
the APM Server. This format is only supported in *APM Server 6.5+*.
Further breaking changes:
* The undocumented `AsyncioHTTPTransport` has been removed.
* The `flush_interval` and `max_queue_size` settings have been removed.
* new settings introduced: `api_request_time` and `api_request_size`.
* Some settings now require a unit for duration or size. See documentation on
configuration for more information.
* The option to provide a custom date for exceptions and messages has been removed.
Other changes:
* on Python 3.7, use https://docs.python.org/3/library/contextvars.html[contextvars] instead of threadlocals for storing
current transaction and span. This is a necessary precursor for full asyncio support. {pull}291[#291]
[[release-notes-3.x]]
=== Python Agent version 3.x
[[release-notes-3.0.2]]
==== v3.0.2 - 2018/10/17
https://github.com/elastic/apm-agent-python/compare/v3.0.1\...v3.0.2[Check the diff]
* Fixed an issue with detecting names of wrapped functions that are partials {pull}294[#294]
* Fixed a bug in Flask instrumentation that could appear together with FlaskAPI {pull}286[#286]
[[release-notes-3.0.1]]
==== v3.0.1 - 2018/08/30
https://github.com/elastic/apm-agent-python/compare/v3.0.0\...v3.0.1[Check the diff]
* Added sanitization for `Set-Cookie` response headers {pull}264[#264]
* Added instrumentation for the non-standard `Connection.execute()` method for SQLite3 {pull}271[#271]
* Added "authorization" to list of sensitive keywords, to ensure that "Authorization"
HTTP headers are properly sanitized {pull}275[#275]
* Taught the Logbook handler how to handle the `stack=False` option {pull}278[#278]
* Fixed a race condition with managing the timer-send thread {pull}279[#279]
[[release-notes-3.0.0]]
==== v3.0.0 - 2018/07/20
https://github.com/elastic/apm-agent-python/compare/v2.2.1\...v3.0.0[Check the diff]
- adapted "black" code formatter for this repository {pull}262[#262]
- **BREAKING**: dropped support for Python 3.3 {pull}242[#242]
- **BREAKING**: changed order of precedence when evaluating configuration {pull}255[#255], {pull}261[#261]
- **BREAKING**: changed default value of `span_frames_min_duration` setting
from `-1` (always collect) to `5` (only collect for spans longer than 5 ms) {pull}243[#243]
- added instrumentation for pymssql {pull}241[#241]
- added instrumentation for pyodbc {pull}238[#238]
[[release-notes-2.x]]
=== Python Agent version 2.x
[[release-notes-2.2.1]]
==== v2.2.1 - 2018/06/13
https://github.com/elastic/apm-agent-python/compare/v2.2.0\...v2.2.1[Check the diff]
- fixed an issue with Django Channels {pull}232[#232], {pull}233[#233]
[[release-notes-2.2.0]]
==== v2.2.0 - 2018/06/13
https://github.com/elastic/apm-agent-python/compare/v2.1.1\...v2.2.0[Check the diff]
- introduced consistent logger name scheme for all elasticapm internal log messages {pull}212[#212]
- added instrumentation of cassandra-driver {pull}205[#205]
- added instrumentation of elasticsearch-py {pull}191[#191]
- added Flask 1.0 to the test matrix {pull}207[#207]
- fixed an issue with our minimalistic SQL parser and "fully qualified" table names {pull}206[#206]
- fixed issue with spans in Django’s `StreamingHTTPResponse` not being captured {pull}201[#201], {pull}202[#202]
- fixed issue with spans with Flask’s streaming response not being captured {pull}201[#201], {pull}202[#202]
**NOTE**: This will be the last release with support for Python 3.3.
[[release-notes-2.1.1]]
==== v2.1.1 - 2018/04/09
https://github.com/elastic/apm-agent-python/compare/v2.1.0\...v2.1.1[Check the diff]
- fixed bug in Django management command that would be triggered on Django 1.10 or 1.11 while using the `MIDDLEWARE_CLASSES` setting {pull}186[#186], {pull}187[#187]
- fix an encoding issue with log messages that are hit in rare cases {pull}188[#188], {pull}189[#189]
[[release-notes-2.1.0]]
==== v2.1.0 - 2018/03/19
https://github.com/elastic/apm-agent-python/compare/v2.0.1\...v2.1.0[Check the diff]
- made skipping of initial `elasticapm` frames for span stack traces more generic {pull}167[#167]
- added `context.process.ppid` field (supported in apm-server 6.3+) {pull}168[#168]
- added option to disable stack frame collection for very short spans {pull}142[#142]
- several bug fixes:
- fix an issue in boto3 instrumentation with nonstandard endpoint URLs {pull}178[#178]
- fix bug with OPTIONS requests and body capturing {pull}174[#174]
- fix issue when message has `%` character, but no params {pull}175[#175]
[[release-notes-2.0.1]]
==== v2.0.1 - 2018/02/15
https://github.com/elastic/apm-agent-python/compare/v2.0.0\...v2.0.1[Check the diff]
- fixed compatibility issue with aiohttp 3.0 {pull}157[#157]
- Added truncation for fields that have a `maxLength` in the JSON Schema {pull}159[#159]
[[release-notes-2.0.0]]
==== v2.0.0 - 2018/02/06
https://github.com/elastic/apm-agent-python/compare/v1.0.0\...v2.0.0[Check the diff]
- moved the library-frame detection from a processor to the stacktrace collection {pull}113[#113].
- added settings to enable/disable source code collection and local variables collection for errors and transactions {pull}117[#117]
- added `service.environment` to provide an environment name (e.g. "production", "staging") {pull}123[#123]
- added `transaction.id` to errors to better correlate errors with transactions {pull}122[#122]
- added `transaction_sample_rate` to define a rate with which transactions are sampled {pull}116[#116]
- added `error.handled` to indicate if an exception was handled or not {pull}124[#124].
- added `transaction_max_spans` setting to limit the amount of spans that are recorded per transaction {pull}127[#127]
- added configuration options to limit captured local variables to a certain length {pull}130[#130]
- added options for configuring the amount of context lines that are captured with each frame {pull}136[#136]
- added support for tracing queries formatted as http://initd.org/psycopg/docs/sql.html[`psycopg2.sql.SQL`] objects {pull}148[#148]
- switched to `time.perf_counter` as timing function on Python 3 {pull}138[#138]
- added option to disable capturing of request body {pull}151[#151]
- BREAKING: Several settings and APIs have been renamed (#111, #119, #143):
- The decorator for custom instrumentation, `elasticapm.trace`, is now `elasticapm.capture_span`
- The setting `traces_send_frequency` has been renamed to `flush_interval`. The name of the analogous environment variable changed from `ELASTIC_APM_TRACES_SEND_FREQ` to `ELASTIC_APM_FLUSH_INTERVAL`
- The `app_name` setting has been renamed to `service_name`. The name of the analogous environment variable changed from `ELASTIC_APM_APP_NAME` to `ELASTIC_APM_SERVICE_NAME`.
- `app_name` arguments to API calls in the whole code base changed to `service_name`.
- The `app_version` setting has been renamed to `service_version`. The name of the analogous environment variable changed from `ELASTIC_APM_APP_VERSION` to `ELASTIC_APM_SERVICE_VERSION`.
- `context.request.url.raw` has been renamed to `context.request.url.full` {pull}121[#121]
- BREAKING: added `elasticapm.set_custom_context` in favor of the more generic `set_custom_data` function {pull}133[#133]
- BREAKING: `include_patterns` and `exclude_patterns` now use shell globs instead of regular expressions, and are matched against the full path file path of the module, not against the module name {pull}137[#137]
- BREAKING: renamed several configuration options to align better with other language agents {pull}145[#145]:
- `disable_instrumentation` became `instrument` and inverted its meaning
- `max_event_queue_length` became `max_queue_size`
- `timeout` became `server_timeout`
[[release-notes-1.x]]
=== Python Agent version 1.x
[[release-notes-1.0.0]]
==== v1.0.0 - 2017/12/11
https://github.com/elastic/apm-agent-python/compare/v1.0.0.dev3\...v1.0.0[Check the diff]
- added `max-event-queue-length` setting. {pull}67[#67]
- changed name that the agent reports itself with to the APM server from `elasticapm-python` to `python`. This aligns the Python agent with other languages. {pull}104[#104]
- changed Celery integration to store the task state (e.g. `SUCCESS` or `FAILURE`) in `transaction.result` {pull}100[#100]
- added setting to disable SSL certificate verification {pull}108[#108]
- BREAKING: renamed `server` configuration variable to `server_url` to better align with other language agents {pull}105[#105]
- BREAKING: removed the old and unused urllib2-based HTTP transport, and renamed the urllib3 transport {pull}107[#107]
- BREAKING: several API changes to `capture_exception`, `capture_message`, and added documentation for these and other APIs {pull}112[#112]
[[release-notes-1.0.0-dev3]]
==== v1.0.0.dev3 - 2017/11/13
https://github.com/elastic/apm-agent-python/compare/v1.0.0.dev2\...v1.0.0.dev2[Check the diff]
- added a background thread to process the transactions queue every 60 seconds (configurable) {pull}68[#68]
- adapted trace context for SQL traces to new API {pull}77[#77]
- ensured that transaction data is also passed through processors {pull}84[#84]
- added `uninstrument` function to reverse instrumentation, and exposed both `instrument` and `uninstrument` as public API in the `elasticapm` namespace {pull}90[#90]
- added normalization of HTTP status codes into classes for the `transaction.result` field. A HTTP status of `200` will be turned into `HTTP 2xx`. The unchanged status code is still available in `context.response.status_code`. {pull}85[#85]
[[release-notes-1.0.0-dev2]]
==== v1.0.0.dev2 - 2017/09/29
https://github.com/elastic/apm-agent-python/compare/v1.0.0.dev1\...v1.0.0.dev2[Check the diff]
- added request context information for Flask {pull}58[#58]
- added response context information for Flask {pull}65[#65]
- BREAKING: changed the `SERVERS` list setting to a single `SERVER` string setting. With this change, we now only support sending events to a single server {pull}59[#59]
- BREAKING: removed root trace. Due to historical reason, we used to create a "root trace" which was equivalent to the transaction. This is no longer necessary. #61
[[release-notes-1.0.0-dev1]]
==== v1.0.0.dev1 - 2017/09/18
https://github.com/elastic/apm-agent-python/compare/v1.0.0.dev0\...v1.0.0.dev1[Check the diff]
- unified configuration across supported frameworks {pull}33[#33]
- added in-app frame detection {pull}36[#36]
- added tagging functionality {pull}28[#28]
- preliminary support for Django 2.0 {pull}26[#26]
- initial set of documentation
[[release-notes-1.0.0-dev0]]
==== v1.0.0.dev0 - 2017/08/17
First release of the Python agent for Elastic APM
python-elastic-apm-6.26.2/CONTRIBUTING.md 0000664 0000000 0000000 00000024353 15216207663 0017575 0 ustar 00root root 0000000 0000000 # Contributing to the Python APM Agent
The APM Agent is open source and we love to receive contributions from our community — you!
There are many ways to contribute,
from writing tutorials or blog posts,
improving the documentation,
submitting bug reports and feature requests or writing code.
You can get in touch with us through [Discuss](https://discuss.elastic.co/c/apm).
Feedback and ideas are always welcome.
Please note that this repository is covered by the [Elastic Community Code of Conduct](https://www.elastic.co/community/codeofconduct).
## Code contributions
If you have a bugfix or new feature that you would like to contribute,
please find or open an issue about it first.
Talk about what you would like to do.
It may be that somebody is already working on it,
or that there are particular issues that you should know about before implementing the change.
### Submitting your changes
Generally, we require that you test any code you are adding or modifying.
Once your changes are ready to submit for review:
1. Sign the Contributor License Agreement
Please make sure you have signed our [Contributor License Agreement](https://www.elastic.co/contributor-agreement/).
We are not asking you to assign copyright to us,
but to give us the right to distribute your code without restriction.
We ask this of all contributors in order to assure our users of the origin and continuing existence of the code.
You only need to sign the CLA once.
1. Code style
This project uses several tools to maintain a consistent code style:
- the automatic code formatter [black](https://black.readthedocs.io/en/stable/)
- sorting of imports via [isort](https://isort.readthedocs.io/en/latest/)
- [flake8](http://flake8.pycqa.org/en/latest/)
- License header check via custom script
The easiest way to make sure your pull request adheres to the code style
is to install [pre-commit](https://pre-commit.com/).
pip install pre-commit # or "brew install pre-commit" if you use Homebrew
pre-commit install
1. Test your changes
Run the test suite to make sure that nothing is broken.
See [testing](#testing) for details. (Note, only unit tests are expected
to be run before submitting a PR.)
1. Rebase your changes
Update your local repository with the most recent code from the main repo,
and rebase your branch on top of the latest main branch.
When we merge your PR, we will squash all of your commits into a single
commit on the main branch.
1. Submit a pull request
Push your local changes to your forked copy of the repository and [submit a pull request](https://help.github.com/articles/using-pull-requests) to the `main` branch.
In the pull request,
choose a title which sums up the changes that you have made,
and in the body provide more details about what your changes do.
Also mention the number of the issue where discussion has taken place,
eg "Closes #123".
1. Be patient
We might not be able to review your code as fast as we would like to,
but we'll do our best to dedicate it the attention it deserves.
Your effort is much appreciated!
### Testing
To run local unit tests, you can install the relevant
[requirements files](https://github.com/elastic/apm-agent-python/tree/main/tests/requirements)
and then run `make test` from the project root:
pip install -r tests/requirements/reqs-flask-1.1.txt
make test
Pytest will automatically discover all the tests and skip the ones for which
dependencies are not met.
If you want to go above and beyond and run the full test suite,
you need to install several databases (Elasticsearch, PostgreSQL, MySQL, Cassandra, Redis).
This can be quite a hassle, so we recommend to use our dockerized test setup.
See [Running tests](https://www.elastic.co/guide/en/apm/agent/python/main/run-tests-locally.html) for detailed instructions.
#### Pytest
This project uses [pytest](https://docs.pytest.org/en/latest/) for all of its
testing needs. Note that pytest can be a bit confusing at first, due to its
dynamic discovery features. In particular,
[fixtures](https://docs.pytest.org/en/stable/fixture.html) can be confusing
and hard to discover, due to the fact that they do not need to be imported to
be used. For example, whenever a test has `elasticapm_client` as an argument,
that is a fixture which is defined
[here](https://github.com/elastic/apm-agent-python/blob/ed4ce5fd5db3cc091a54d3328384fbce62635bbb/tests/fixtures.py#L150).
#### Adding new instrumentations to the matrix build
For tests that require external dependencies like databases, or for testing different versions of the same library,
we use a matrix build that leverages Docker.
The setup requires a little bit of boilerplate to get started.
In this example, we will create an instrumentation for the "foo" database, by instrumenting its Python driver, `foodriver`.
1. mark your tests with a pytest marker that describes the new instrumentation at the top of your tests file:
pytestmark = pytest.mark.foo
`pytestmark` can also be a list if you need to define more than one mark (e.g. to mark tests as integration tests):
pytestmark = [pytest.mark.foo, pytest.mark.integrationtest]
1. make sure to use `pytest.importorskip` to import any dependencies that are only required by your tests:
foodriver = pytest.importorskip("foodriver")
1. Create one or more requirements files in `tests/requirements` that list the dependencies that are to be installed specifically for your tests:
To only test the newest version of the library, create a file `tests/requirements/reqs-foo-newest.txt` and add something like this to it:
foodriver
-r reqs-base.txt
This tells the matrix runner to install the newest version of `foodriver`, as well as the base requirements needed to run the test suite.
To test more than one version of the library, create additional `reqs-foo-X.Y.txt` files with specific versions of your instrumented package.
1. Create a file called `foo.sh` in `tests/scripts/envs/foo.sh`.
Here you can define environment variables that are required to run your tests.
As a minimum, you'll have to set the `PYTEST_MARKER` variable to the same value you used above for the pytest marker, e.g.
export PYTEST_MARKER="-m foo"
1. Add entries in `.ci/matrix_framework.yml` (for pull requests) and `.ci/matrix_framework_full.yml` (for nightly builds).
Generally, we only test the newest version of an instrumentation with every pull request:
- foo-newest
To test other versions in the nightly build, add them to `.ci/matrix_framework_full.yml`.
1. OPTIONAL: If you need a real service to test against (e.g. an actual foo database), add an entry in `tests/docker-compose.yml` under `services`:
foo:
image: foobase:latest
You'll also have to add a `DOCKER_DEPS` environment variable to `tests/scripts/envs/foo.sh` which tells the matrix
to spin up the given Docker compose service before running your tests.
You may also need to add things like hostname configuration here.
DOCKER_DEPS="foo"
FOO_CONNECTION_URL="http://foo:4711"
1. OPTIONAL: If your instrumented package does not support all Python versions we test with, you can exclude certain combinations by adding them to `.ci/matrix_exclude.yml`:
- PYTHON_VERSION: python-3.5 # foo doesn't support Python 3.5
FRAMEWORK: foo-newest
### Workflow
All feature development and most bug fixes hit the main branch first.
Pull requests should be reviewed by someone with commit access.
Once approved, the author of the pull request,
or reviewer if the author does not have commit access,
should "Squash and merge".
### Releasing
Releases tags are signed so you need to have a PGP key set up, you can follow Github documentation on [creating a key](https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key) and
on [telling git about it](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key). Alternatively you can sign with a SSH key, remember you have to upload your key
again even if you want to use the same key you are using for authorization.
Then make sure you have SSO figured out for the key you are using to push to github, see [Github documentation](https://docs.github.com/articles/authenticating-to-a-github-organization-with-saml-single-sign-on/).
If you have commit access, the process is as follows:
1. Update the version in `elasticapm/version.py` according to the scale of the change. (major, minor or patch)
1. Update `CHANGELOG.asciidoc`. Rename the `Unreleased` section to the correct version (`vX.X.X`), and nest under the appropriate sub-heading, e.g., `Python Agent version 5.x`.
1. Update `docs/release-notes/`.
1. For Majors: [Create an issue](https://github.com/elastic/website-requests/issues/new) to request an update of the [EOL table](https://www.elastic.co/support/eol).
1. For Majors: Add the new major version to `conf.yaml` in the [elastic/docs](https://github.com/elastic/docs) repo.
1. Commit changes with message `update CHANGELOG and bump version to X.Y.Z`
where `X.Y.Z` is the version in `elasticapm/version.py`
1. Open a PR against `main` with these changes leaving the body empty
1. Once the PR is merged, fetch and checkout `upstream/main`
1. Tag the commit with `git tag -s vX.Y.Z`, for example `git tag -s v1.2.3`.
Copy the changelog for the release to the tag message, removing any leading `#`.
1. Push tag upstream with `git push upstream --tags` (and optionally to your own fork as well)
1. Open a PR from `main` to the major branch, e.g. `1.x` to update it. In order to keep history create a
branch from the `main` branch, rebase it on top of the major branch to drop duplicated commits and then
merge with the `rebase` strategy. It is crucial that `main` and the major branch have the same content.
1. After tests pass, Github Actions will automatically build and push the new release to PyPI.
1. Edit and publish the [draft Github release](https://github.com/elastic/apm-agent-python/releases)
created by Github Actions. Substitute the generated changelog with one hand written into the body of the
release.
1. Update substitutions variables in `docs/reference/lambda-support.md`.
python-elastic-apm-6.26.2/Dockerfile 0000664 0000000 0000000 00000000177 15216207663 0017334 0 ustar 00root root 0000000 0000000 FROM alpine@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b
ARG AGENT_DIR
COPY ${AGENT_DIR} /opt/python python-elastic-apm-6.26.2/Dockerfile.wolfi 0000664 0000000 0000000 00000000247 15216207663 0020451 0 ustar 00root root 0000000 0000000 FROM docker.elastic.co/wolfi/chainguard-base:latest@sha256:a257ae19c6d7040a7d4a6452e56218a92211c1d269861371befa6367becd24e4
ARG AGENT_DIR
COPY ${AGENT_DIR} /opt/python python-elastic-apm-6.26.2/LICENSE 0000664 0000000 0000000 00000003063 15216207663 0016344 0 ustar 00root root 0000000 0000000 BSD 3-Clause License
Copyright (c) 2009-2012, David Cramer and individual contributors
Copyright (c) 2013-2023, Elasticsearch BV
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
python-elastic-apm-6.26.2/MANIFEST.in 0000664 0000000 0000000 00000000202 15216207663 0017065 0 ustar 00root root 0000000 0000000 include setup.py README.rst MANIFEST.in LICENSE elasticapm/py.typed
global-exclude *~
recursive-exclude * __pycache__
prune tests
python-elastic-apm-6.26.2/Makefile 0000664 0000000 0000000 00000001700 15216207663 0016773 0 ustar 00root root 0000000 0000000 BUILD_DIR?=build
SHELL := /bin/bash
isort:
isort --vb .
flake8:
flake8
test:
# delete any __pycache__ folders to avoid hard-to-debug caching issues
find . -type f -name '*.py[co]' -delete -o -type d -name __pycache__ -delete
# pypy3 should be added to the first `if` once it supports py3.7
if [[ "$$PYTHON_VERSION" =~ ^(3.7|3.8|3.9|3.10|3.11|3.12|3.13|3.14|nightly)$$ ]] ; then \
echo "Python 3.7+, with asyncio"; \
pytest -v $(PYTEST_ARGS) --showlocals $(PYTEST_MARKER) $(PYTEST_JUNIT); \
else \
echo "Python < 3.7, without asyncio"; \
pytest -v $(PYTEST_ARGS) --showlocals $(PYTEST_MARKER) $(PYTEST_JUNIT) --ignore-glob='*/asyncio*/*'; \
fi
coverage: PYTEST_ARGS=--cov --cov-context=test --cov-config=setup.cfg --cov-branch
coverage: export COVERAGE_FILE=.coverage.docker.$(PYTHON_FULL_VERSION).$(FRAMEWORK)
coverage: test
docs:
bash ./scripts/build_docs.sh apm-agent-python ./docs ${BUILD_DIR}
.PHONY: isort flake8 test coverage docs
python-elastic-apm-6.26.2/NOTICE.md 0000664 0000000 0000000 00000010773 15216207663 0016650 0 ustar 00root root 0000000 0000000 # Notice
## Dependencies installed by package management
### wrapt
- **author:** Graham Dumpleton
- **project url:** https://github.com/GrahamDumpleton/wrapt
- **license:** BSD-2-Clause, http://opensource.org/licenses/BSD-2-Clause
Copyright (c) 2013, Graham Dumpleton
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
### urllib3
- **author:** Andrey Petrov
- **project url:** https://github.com/urllib3/urllib3
- **license:** MIT License, https://opensource.org/licenses/MIT
MIT License
Copyright (c) 2008-2019 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
### certifi
- **author:** Kenneth Reitz
- **project url:** https://github.com/certifi/python-certifi
- **license:** Mozilla Public License 2.0, https://opensource.org/licenses/MPL-2.0
This packge contains a modified version of ca-bundle.crt:
ca-bundle.crt -- Bundle of CA Root Certificates
Certificate data from Mozilla as of: Thu Nov 3 19:04:19 2011#
This is a bundle of X.509 certificates of public Certificate Authorities
(CA). These were automatically extracted from Mozilla's root certificates
file (certdata.txt). This file can be found in the mozilla source tree:
http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1#
It contains the certificates in PEM format and therefore
can be directly used with curl / libcurl / php_curl, or with
an Apache+mod_ssl webserver for SSL client authentication.
Just configure this file as the SSLCACertificateFile.#
***** BEGIN LICENSE BLOCK *****
This Source Code Form is subject to the terms of the Mozilla Public License,
v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain
one at http://mozilla.org/MPL/2.0/.
***** END LICENSE BLOCK *****
@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $
python-elastic-apm-6.26.2/README.rst 0000664 0000000 0000000 00000003144 15216207663 0017026 0 ustar 00root root 0000000 0000000 elastic-apm -- Elastic APM agent for Python
===========================================
.. image:: https://github.com/elastic/apm-agent-python/actions/workflows/test.yml/badge.svg?branch=main
:target: https://github.com/elastic/apm-agent-python/actions/workflows/test.yml
:alt: Build Status
.. image:: https://img.shields.io/pypi/v/elastic-apm.svg?style=flat
:target: https://pypi.python.org/pypi/elastic-apm/
:alt: Latest Version
.. image:: https://img.shields.io/pypi/pyversions/elastic-apm.svg?style=flat
:target: https://pypi.python.org/pypi/elastic-apm/
:alt: Supported Python versions
This is the official Python module for Elastic APM.
It provides full out-of-the-box support for many of the popular frameworks,
including Django, and Flask. Elastic APM is also easy to adapt for most
WSGI-compatible web applications via `custom integrations`_.
Your application doesn't live on the web? No problem! Elastic APM is easy to use in
any Python application.
Read the documentation_, including instructions on `running the tests locally`_.
If you're interested in contributing, `start here!`_
.. _documentation: https://www.elastic.co/guide/en/apm/agent/python/current/index.html
.. _`custom integrations`: https://www.elastic.co/blog/creating-custom-framework-integrations-with-the-elastic-apm-python-agent
.. _`running the tests locally`: https://www.elastic.co/guide/en/apm/agent/python/current/run-tests-locally.html
.. _`start here!`: https://github.com/elastic/apm-agent-python/blob/main/CONTRIBUTING.md
License
-------
BSD-3-Clause
Made with ♥� and ☕� by Elastic and our community.
python-elastic-apm-6.26.2/dev-utils/ 0000775 0000000 0000000 00000000000 15216207663 0017251 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/dev-utils/make-distribution.sh 0000775 0000000 0000000 00000003371 15216207663 0023246 0 ustar 00root root 0000000 0000000 #!/bin/bash
#
# Make a Python APM agent distribution that is used as follows:
# - "build/dist/elastic-apm-python-lambda-layer.zip" is published to AWS as a
# Lambda layer (https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html)
# - "build/dist/package/python/..." is used to build a Docker image of the APM agent
#
if [ "$TRACE" != "" ]; then
export PS4='${BASH_SOURCE}:${LINENO}: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
set -o xtrace
fi
set -o errexit
set -o pipefail
# ---- support functions
function fatal {
echo "$(basename $0): error: $*"
exit 1
}
# ---- mainline
TOP=$(cd $(dirname $0)/../ >/dev/null; pwd)
BUILD_DIR="$TOP/build/dist"
if ! command -v pip >/dev/null 2>&1; then
fatal "pip is unavailable"
fi
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
rm -f elastic-apm-python-lambda-layer.zip
rm -f requirements.txt
rm -rf package
mkdir package
cp "$TOP/dev-utils/requirements.txt" .
echo "$TOP" >> ./requirements.txt
pip install -r requirements.txt --target ./package/python
cd package
cp python/elasticapm/contrib/serverless/aws_wrapper/elasticapm-lambda.py ./python/bin/elasticapm-lambda
chmod +x ./python/bin/elasticapm-lambda
cp python/elasticapm/contrib/serverless/aws_wrapper/elasticapm_handler.py ./python/
cp "$TOP/elasticapm/contrib/serverless/aws_wrapper/NOTICE.md" ./python/
echo ""
zip -q -r ../elastic-apm-python-lambda-layer.zip .
echo "Created build/dist/elastic-apm-python-lambda-layer.zip"
cd ..
echo
echo "The lambda layer can be published as follows for dev work:"
echo " aws lambda --output json publish-layer-version --layer-name '$USER-dev-elastic-apm-python' --description '$USER dev Elastic APM Python agent lambda layer' --zip-file 'fileb://build/dist/elastic-apm-python-lambda-layer.zip'"
python-elastic-apm-6.26.2/dev-utils/make-packages.sh 0000775 0000000 0000000 00000000312 15216207663 0022275 0 ustar 00root root 0000000 0000000 #!/bin/bash
#
# Make a Python APM agent distribution
#
echo "::group::Install build"
pip install --user build
echo "::endgroup::"
echo "::group::Building packages"
python -m build
echo "::endgroup::"
python-elastic-apm-6.26.2/dev-utils/requirements.txt 0000664 0000000 0000000 00000000170 15216207663 0022533 0 ustar 00root root 0000000 0000000 # These are the pinned requirements for the lambda layer/docker image
certifi==2026.5.20
urllib3==1.26.20
wrapt==1.14.1
python-elastic-apm-6.26.2/docs/ 0000775 0000000 0000000 00000000000 15216207663 0016265 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/docs/docset.yml 0000664 0000000 0000000 00000000603 15216207663 0020270 0 ustar 00root root 0000000 0000000 project: 'APM Python agent docs'
products:
- id: apm-agent
cross_links:
- apm-agent-rum-js
- apm-aws-lambda
- beats
- docs-content
- ecs
- ecs-logging
- ecs-logging-python
- elastic-otel-python
- elasticsearch
- logstash-docs-md
toc:
- toc: reference
- toc: release-notes
subs:
ecloud: "Elastic Cloud"
apm-lambda-ext: "Elastic APM AWS Lambda extension"
python-elastic-apm-6.26.2/docs/reference/ 0000775 0000000 0000000 00000000000 15216207663 0020223 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/docs/reference/advanced-topics.md 0000664 0000000 0000000 00000000725 15216207663 0023615 0 ustar 00root root 0000000 0000000 ---
mapped_pages:
- https://www.elastic.co/guide/en/apm/agent/python/current/advanced-topics.html
applies_to:
stack:
serverless:
observability:
product:
apm_agent_python: ga
---
# Advanced topics [advanced-topics]
* [Instrumenting custom code](/reference/instrumenting-custom-code.md)
* [Sanitizing data](/reference/sanitizing-data.md)
* [How the Agent works](/reference/how-agent-works.md)
* [Run Tests Locally](/reference/run-tests-locally.md)
python-elastic-apm-6.26.2/docs/reference/aiohttp-server-support.md 0000664 0000000 0000000 00000006571 15216207663 0025244 0 ustar 00root root 0000000 0000000 ---
mapped_pages:
- https://www.elastic.co/guide/en/apm/agent/python/current/aiohttp-server-support.html
applies_to:
stack:
serverless:
observability:
product:
apm_agent_python: ga
---
# Aiohttp Server support [aiohttp-server-support]
Getting Elastic APM set up for your Aiohttp Server project is easy, and there are various ways you can tweak it to fit to your needs.
## Installation [aiohttp-server-installation]
Install the Elastic APM agent using pip:
```bash
$ pip install elastic-apm
```
or add `elastic-apm` to your project’s `requirements.txt` file.
## Setup [aiohttp-server-setup]
To set up the agent, you need to initialize it with appropriate settings.
The settings are configured either via environment variables, the application’s settings, or as initialization arguments.
You can find a list of all available settings in the [Configuration](/reference/configuration.md) page.
To initialize the agent for your application using environment variables:
```python
from aiohttp import web
from elasticapm.contrib.aiohttp import ElasticAPM
app = web.Application()
apm = ElasticAPM(app)
```
To configure the agent using `ELASTIC_APM` in your application’s settings:
```python
from aiohttp import web
from elasticapm.contrib.aiohttp import ElasticAPM
app = web.Application()
app['ELASTIC_APM'] = {
'SERVICE_NAME': '',
'SECRET_TOKEN': '',
}
apm = ElasticAPM(app)
```
## Usage [aiohttp-server-usage]
Once you have configured the agent, it will automatically track transactions and capture uncaught exceptions within aiohttp.
Capture an arbitrary exception by calling [`capture_exception`](/reference/api-reference.md#client-api-capture-exception):
```python
try:
1 / 0
except ZeroDivisionError:
apm.client.capture_exception()
```
Log a generic message with [`capture_message`](/reference/api-reference.md#client-api-capture-message):
```python
apm.client.capture_message('hello, world!')
```
## Performance metrics [aiohttp-server-performance-metrics]
If you’ve followed the instructions above, the agent has already installed our middleware. This will measure response times, as well as detailed performance data for all supported technologies.
::::{note}
due to the fact that `asyncio` drivers are usually separate from their synchronous counterparts, specific instrumentation is needed for all drivers. The support for asynchronous drivers is currently quite limited.
::::
### Ignoring specific routes [aiohttp-server-ignoring-specific-views]
You can use the [`TRANSACTIONS_IGNORE_PATTERNS`](/reference/configuration.md#config-transactions-ignore-patterns) configuration option to ignore specific routes. The list given should be a list of regular expressions which are matched against the transaction name:
```python
app['ELASTIC_APM'] = {
# ...
'TRANSACTIONS_IGNORE_PATTERNS': ['^OPTIONS ', '/api/']
# ...
}
```
This would ignore any requests using the `OPTIONS` method and any requests containing `/api/`.
## Supported aiohttp and Python versions [supported-aiohttp-and-python-versions]
A list of supported [aiohttp](/reference/supported-technologies.md#supported-aiohttp) and [Python](/reference/supported-technologies.md#supported-python) versions can be found on our [Supported Technologies](/reference/supported-technologies.md) page.
::::{note}
Elastic APM only supports `asyncio` when using Python 3.7+
::::
python-elastic-apm-6.26.2/docs/reference/api-reference.md 0000664 0000000 0000000 00000044132 15216207663 0023256 0 ustar 00root root 0000000 0000000 ---
mapped_pages:
- https://www.elastic.co/guide/en/apm/agent/python/current/api.html
applies_to:
stack:
serverless:
observability:
product:
apm_agent_python: ga
---
# API reference [api]
The Elastic APM Python agent has several public APIs. Most of the public API functionality is not needed when using one of our [supported frameworks](/reference/supported-technologies.md#framework-support), but they allow customized usage.
## Client API [client-api]
The public Client API consists of several methods on the `Client` class. This API can be used to track exceptions and log messages, as well as to mark the beginning and end of transactions.
### Instantiation [client-api-init]
```{applies_to}
apm_agent_python: ga 1.0.0
```
To create a `Client` instance, import it and call its constructor:
```python
from elasticapm import Client
client = Client({'SERVICE_NAME': 'example'}, **defaults)
```
* `config`: A dictionary, with key/value configuration. For the possible configuration keys, see [Configuration](/reference/configuration.md).
* `**defaults`: default values for configuration. These can be omitted in most cases, and take the least precedence.
::::{note}
framework integrations like [Django](/reference/django-support.md) and [Flask](/reference/flask-support.md) instantiate the client automatically.
::::
#### `elasticapm.get_client()` [api-get-client]
```{applies_to}
apm_agent_python: ga 6.1.0
```
Retrieves the `Client` singleton. This is useful for many framework integrations, where the client is instantiated automatically.
```python
client = elasticapm.get_client()
client.capture_message('foo')
```
### Errors [error-api]
#### `Client.capture_exception()` [client-api-capture-exception]
```{applies_to}
apm_agent_python: ga 1.0.0
```
`handled` added in v2.0.0.
Captures an exception object:
```python
try:
x = int("five")
except ValueError:
client.capture_exception()
```
* `exc_info`: A `(type, value, traceback)` tuple as returned by [`sys.exc_info()`](https://docs.python.org/3/library/sys.html#sys.exc_info). If not provided, it will be captured automatically.
* `date`: A `datetime.datetime` object representing the occurrence time of the error. If left empty, it defaults to `datetime.datetime.utcnow()`.
* `context`: A dictionary with contextual information. This dictionary must follow the [Context](docs-content://solutions/observability/apm/elastic-apm-events-intake-api.md#apm-api-error) schema definition.
* `custom`: A dictionary of custom data you want to attach to the event.
* `handled`: A boolean to indicate if this exception was handled or not.
Returns the id of the error as a string.
#### `Client.capture_message()` [client-api-capture-message]
```{applies_to}
apm_agent_python: ga 1.0.0
```
Captures a message with optional added contextual data. Example:
```python
client.capture_message('Billing process succeeded.')
```
* `message`: The message as a string.
* `param_message`: Alternatively, a parameterized message as a dictionary. The dictionary contains two values: `message`, and `params`. This allows the APM Server to group messages together that share the same parameterized message. Example:
```python
client.capture_message(param_message={
'message': 'Billing process for %s succeeded. Amount: %s',
'params': (customer.id, order.total_amount),
})
```
* `stack`: If set to `True` (the default), a stacktrace from the call site will be captured.
* `exc_info`: A `(type, value, traceback)` tuple as returned by [`sys.exc_info()`](https://docs.python.org/3/library/sys.html#sys.exc_info). If not provided, it will be captured automatically, if `capture_message()` was called in an `except` block.
* `date`: A `datetime.datetime` object representing the occurrence time of the error. If left empty, it defaults to `datetime.datetime.utcnow()`.
* `context`: A dictionary with contextual information. This dictionary must follow the [Context](docs-content://solutions/observability/apm/elastic-apm-events-intake-api.md#apm-api-error) schema definition.
* `custom`: A dictionary of custom data you want to attach to the event.
Returns the id of the message as a string.
::::{note}
Either the `message` or the `param_message` argument is required.
::::
### Transactions [transaction-api]
#### `Client.begin_transaction()` [client-api-begin-transaction]
```{applies_to}
apm_agent_python: ga 1.0.0
```
`trace_parent` support added in v5.6.0.
Begin tracking a transaction. Should be called e.g. at the beginning of a request or when starting a background task. Example:
```python
client.begin_transaction('processors')
```
* `transaction_type`: (**required**) A string describing the type of the transaction, e.g. `'request'` or `'celery'`.
* `trace_parent`: (**optional**) A `TraceParent` object. See [TraceParent generation](#traceparent-api).
* `links`: (**optional**) A list of `TraceParent` objects to which this transaction is causally linked.
#### `Client.end_transaction()` [client-api-end-transaction]
```{applies_to}
apm_agent_python: ga 1.0.0
```
End tracking the transaction. Should be called e.g. at the end of a request or when ending a background task. Example:
```python
client.end_transaction('myapp.billing_process', processor.status)
```
* `name`: (**optional**) A string describing the name of the transaction, e.g. `process_order`. This is typically the name of the view/controller that handles the request, or the route name.
* `result`: (**optional**) A string describing the result of the transaction. This is typically the HTTP status code, or e.g. `'success'` for a background task.
::::{note}
if `name` and `result` are not set in the `end_transaction()` call, they have to be set beforehand by calling [`elasticapm.set_transaction_name()`](#api-set-transaction-name) and [`elasticapm.set_transaction_result()`](#api-set-transaction-result) during the transaction.
::::
### `TraceParent` [traceparent-api]
Transactions can be started with a `TraceParent` object. This creates a transaction that is a child of the `TraceParent`, which is essential for distributed tracing.
#### `elasticapm.trace_parent_from_string()` [api-traceparent-from-string]
```{applies_to}
apm_agent_python: ga 5.6.0
```
Create a `TraceParent` object from the string representation generated by `TraceParent.to_string()`:
```python
parent = elasticapm.trace_parent_from_string('00-03d67dcdd62b7c0f7a675424347eee3a-5f0e87be26015733-01')
client.begin_transaction('processors', trace_parent=parent)
```
* `traceparent_string`: (**required**) A string representation of a `TraceParent` object.
#### `elasticapm.trace_parent_from_headers()` [api-traceparent-from-headers]
```{applies_to}
apm_agent_python: ga 5.6.0
```
Create a `TraceParent` object from HTTP headers (usually generated by another Elastic APM agent):
```python
parent = elasticapm.trace_parent_from_headers(headers_dict)
client.begin_transaction('processors', trace_parent=parent)
```
* `headers`: (**required**) HTTP headers formed as a dictionary.
#### `elasticapm.get_trace_parent_header()` [api-traceparent-get-header]
```{applies_to}
apm_agent_python: ga 5.10.0
```
Return the string representation of the current transaction `TraceParent` object:
```python
elasticapm.get_trace_parent_header()
```
## Other APIs [api-other]
### `elasticapm.instrument()` [api-elasticapm-instrument]
```{applies_to}
apm_agent_python: ga 1.0.0
```
Instruments libraries automatically. This includes a wide range of standard library and 3rd party modules. A list of instrumented modules can be found in `elasticapm.instrumentation.register`. This function should be called as early as possible in the startup of your application. For [supported frameworks](/reference/supported-technologies.md#framework-support), this is called automatically. Example:
```python
import elasticapm
elasticapm.instrument()
```
### `elasticapm.set_transaction_name()` [api-set-transaction-name]
```{applies_to}
apm_agent_python: ga 1.0.0
```
Set the name of the current transaction. For supported frameworks, the transaction name is determined automatically, and can be overridden using this function. Example:
```python
import elasticapm
elasticapm.set_transaction_name('myapp.billing_process')
```
* `name`: (**required**) A string describing name of the transaction
* `override`: if `True` (the default), overrides any previously set transaction name. If `False`, only sets the name if the transaction name hasn’t already been set.
### `elasticapm.set_transaction_result()` [api-set-transaction-result]
```{applies_to}
apm_agent_python: ga 2.2.0
```
Set the result of the current transaction. For supported frameworks, the transaction result is determined automatically, and can be overridden using this function. Example:
```python
import elasticapm
elasticapm.set_transaction_result('SUCCESS')
```
* `result`: (**required**) A string describing the result of the transaction, e.g. `HTTP 2xx` or `SUCCESS`
* `override`: if `True` (the default), overrides any previously set result. If `False`, only sets the result if the result hasn’t already been set.
### `elasticapm.set_transaction_outcome()` [api-set-transaction-outcome]
```{applies_to}
apm_agent_python: ga 5.9.0
```
Sets the outcome of the transaction. The value can either be `"success"`, `"failure"` or `"unknown"`. This should only be called at the end of a transaction after the outcome is determined.
The `outcome` is used for error rate calculations. `success` denotes that a transaction has concluded successful, while `failure` indicates that the transaction failed to finish successfully. If the `outcome` is set to `unknown`, the transaction will not be included in error rate calculations.
For supported web frameworks, the transaction outcome is set automatically if it has not been set yet, based on the HTTP status code. A status code below `500` is considered a `success`, while any value of `500` or higher is counted as a `failure`.
If your transaction results in an HTTP response, you can alternatively provide the HTTP status code.
::::{note}
While the `outcome` and `result` field look very similar, they serve different purposes. Other than the `result` field, which canhold an arbitrary string value, `outcome` is limited to three different values, `"success"`, `"failure"` and `"unknown"`. This allows the APM app to perform error rate calculations on these values.
::::
Example:
```python
import elasticapm
elasticapm.set_transaction_outcome("success")
# Using an HTTP status code
elasticapm.set_transaction_outcome(http_status_code=200)
# Using predefined constants:
from elasticapm.conf.constants import OUTCOME
elasticapm.set_transaction_outcome(OUTCOME.SUCCESS)
elasticapm.set_transaction_outcome(OUTCOME.FAILURE)
elasticapm.set_transaction_outcome(OUTCOME.UNKNOWN)
```
* `outcome`: One of `"success"`, `"failure"` or `"unknown"`. Can be omitted if `http_status_code` is provided.
* `http_status_code`: if the transaction represents an HTTP response, its status code can be provided to determine the `outcome` automatically.
* `override`: if `True` (the default), any previously set `outcome` will be overridden. If `False`, the outcome will only be set if it was not set before.
### `elasticapm.get_transaction_id()` [api-get-transaction-id]
```{applies_to}
apm_agent_python: ga 5.2.0
```
Get the id of the current transaction. Example:
```python
import elasticapm
transaction_id = elasticapm.get_transaction_id()
```
### `elasticapm.get_trace_id()` [api-get-trace-id]
```{applies_to}
apm_agent_python: ga 5.2.0
```
Get the `trace_id` of the current transaction’s trace. Example:
```python
import elasticapm
trace_id = elasticapm.get_trace_id()
```
### `elasticapm.get_span_id()` [api-get-span-id]
```{applies_to}
apm_agent_python: ga 5.2.0
```
Get the id of the current span. Example:
```python
import elasticapm
span_id = elasticapm.get_span_id()
```
### `elasticapm.set_custom_context()` [api-set-custom-context]
```{applies_to}
apm_agent_python: ga 2.0.0
```
Attach custom contextual data to the current transaction and errors. Supported frameworks will automatically attach information about the HTTP request and the logged in user. You can attach further data using this function.
::::{tip}
Before using custom context, ensure you understand the different types of [metadata](docs-content://solutions/observability/apm/metadata.md) that are available.
::::
Example:
```python
import elasticapm
elasticapm.set_custom_context({'billing_amount': product.price * item_count})
```
* `data`: (**required**) A dictionary with the data to be attached. This should be a flat key/value `dict` object.
::::{note}
`.`, `*`, and `"` are invalid characters for key names and will be replaced with `_`.
::::
Errors that happen after this call will also have the custom context attached to them. You can call this function multiple times, new context data will be merged with existing data, following the `update()` semantics of Python dictionaries.
### `elasticapm.set_user_context()` [api-set-user-context]
```{applies_to}
apm_agent_python: ga 2.0.0
```
Attach information about the currently logged in user to the current transaction and errors. Example:
```python
import elasticapm
elasticapm.set_user_context(username=user.username, email=user.email, user_id=user.id)
```
* `username`: The username of the logged in user
* `email`: The email of the logged in user
* `user_id`: The unique identifier of the logged in user, e.g. the primary key value
Errors that happen after this call will also have the user context attached to them. You can call this function multiple times, new user data will be merged with existing data, following the `update()` semantics of Python dictionaries.
### `elasticapm.capture_span` [api-capture-span]
```{applies_to}
apm_agent_python: ga 4.1.0
```
Capture a custom span. This can be used either as a function decorator or as a context manager (in a `with` statement). When used as a decorator, the name of the span will be set to the name of the function. When used as a context manager, a name has to be provided.
```python
import elasticapm
@elasticapm.capture_span()
def coffee_maker(strength):
fetch_water()
with elasticapm.capture_span('near-to-machine', labels={"type": "arabica"}):
insert_filter()
for i in range(strength):
pour_coffee()
start_drip()
fresh_pots()
```
* `name`: The name of the span. Defaults to the function name if used as a decorator.
* `span_type`: (**optional**) The type of the span, usually in a dot-separated hierarchy of `type`, `subtype`, and `action`, e.g. `db.mysql.query`. Alternatively, type, subtype and action can be provided as three separate arguments, see `span_subtype` and `span_action`.
* `skip_frames`: (**optional**) The number of stack frames to skip when collecting stack traces. Defaults to `0`.
* `leaf`: (**optional**) if `True`, all spans nested below this span will be ignored. Defaults to `False`.
* `labels`: (**optional**) a dictionary of labels. Keys must be strings, values can be strings, booleans, or numerical (`int`, `float`, `decimal.Decimal`). Defaults to `None`.
* `span_subtype`: (**optional**) subtype of the span, e.g. name of the database. Defaults to `None`.
* `span_action`: (**optional**) action of the span, e.g. `query`. Defaults to `None`.
* `links`: (**optional**) A list of `TraceParent` objects to which this span is causally linked.
### `elasticapm.async_capture_span` [api-async-capture-span]
```{applies_to}
apm_agent_python: ga 5.4.0
```
Capture a custom async-aware span. This can be used either as a function decorator or as a context manager (in an `async with` statement). When used as a decorator, the name of the span will be set to the name of the function. When used as a context manager, a name has to be provided.
```python
import elasticapm
@elasticapm.async_capture_span()
async def coffee_maker(strength):
await fetch_water()
async with elasticapm.async_capture_span('near-to-machine', labels={"type": "arabica"}):
await insert_filter()
async for i in range(strength):
await pour_coffee()
start_drip()
fresh_pots()
```
* `name`: The name of the span. Defaults to the function name if used as a decorator.
* `span_type`: (**optional**) The type of the span, usually in a dot-separated hierarchy of `type`, `subtype`, and `action`, e.g. `db.mysql.query`. Alternatively, type, subtype and action can be provided as three separate arguments, see `span_subtype` and `span_action`.
* `skip_frames`: (**optional**) The number of stack frames to skip when collecting stack traces. Defaults to `0`.
* `leaf`: (**optional**) if `True`, all spans nested below this span will be ignored. Defaults to `False`.
* `labels`: (**optional**) a dictionary of labels. Keys must be strings, values can be strings, booleans, or numerical (`int`, `float`, `decimal.Decimal`). Defaults to `None`.
* `span_subtype`: (**optional**) subtype of the span, e.g. name of the database. Defaults to `None`.
* `span_action`: (**optional**) action of the span, e.g. `query`. Defaults to `None`.
* `links`: (**optional**) A list of `TraceParent` objects to which this span is causally linked.
::::{note}
`asyncio` is only supported for Python 3.7+.
::::
### `elasticapm.label()` [api-label]
```{applies_to}
apm_agent_python: ga 5.0.0
```
Attach labels to the the current transaction and errors.
::::{tip}
Before using custom labels, ensure you understand the different types of [metadata](docs-content://solutions/observability/apm/metadata.md) that are available.
::::
Example:
```python
import elasticapm
elasticapm.label(ecommerce=True, dollar_value=47.12)
```
Errors that happen after this call will also have the labels attached to them. You can call this function multiple times, new labels will be merged with existing labels, following the `update()` semantics of Python dictionaries.
Keys must be strings, values can be strings, booleans, or numerical (`int`, `float`, `decimal.Decimal`) `.`, `*`, and `"` are invalid characters for label names and will be replaced with `_`.
::::{warning}
Avoid defining too many user-specified labels. Defining too many unique fields in an index is a condition that can lead to a [mapping explosion](docs-content://manage-data/data-store/mapping.md#mapping-limit-settings).
::::
python-elastic-apm-6.26.2/docs/reference/asgi-middleware.md 0000664 0000000 0000000 00000004140 15216207663 0023602 0 ustar 00root root 0000000 0000000 ---
mapped_pages:
- https://www.elastic.co/guide/en/apm/agent/python/current/asgi-middleware.html
applies_to:
stack:
serverless:
observability:
product:
apm_agent_python: preview
---
# ASGI Middleware [asgi-middleware]
::::{warning}
This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.
::::
Incorporating Elastic APM into your ASGI-based project only requires a few easy steps.
::::{note}
Several ASGI frameworks are supported natively. Please check [Supported Technologies](/reference/supported-technologies.md) for more information
::::
## Installation [asgi-installation]
Install the Elastic APM agent using pip:
```bash
$ pip install elastic-apm
```
or add `elastic-apm` to your project’s `requirements.txt` file.
## Setup [asgi-setup]
To set up the agent, you need to initialize it with appropriate settings.
The settings are configured either via environment variables, or as initialization arguments.
You can find a list of all available settings in the [Configuration](/reference/configuration.md) page.
To set up the APM agent, wrap your ASGI app with the `ASGITracingMiddleware`:
```python
from elasticapm.contrib.asgi import ASGITracingMiddleware
app = MyGenericASGIApp() # depending on framework
app = ASGITracingMiddleware(app)
```
Make sure to call [`elasticapm.set_transaction_name()`](/reference/api-reference.md#api-set-transaction-name) with an appropriate transaction name in all your routes.
::::{note}
Currently, the agent doesn’t support automatic capturing of exceptions. You can follow progress on this issue on [Github](https://github.com/elastic/apm-agent-python/issues/1548).
::::
## Supported Python versions [supported-python-versions]
A list of supported [Python](/reference/supported-technologies.md#supported-python) versions can be found on our [Supported Technologies](/reference/supported-technologies.md) page.
::::{note}
Elastic APM only supports `asyncio` when using Python 3.7+
::::
python-elastic-apm-6.26.2/docs/reference/azure-functions-support.md 0000664 0000000 0000000 00000007111 15216207663 0025413 0 ustar 00root root 0000000 0000000 ---
mapped_pages:
- https://www.elastic.co/guide/en/apm/agent/python/current/azure-functions-support.html
applies_to:
stack:
serverless:
observability:
product:
apm_agent_python: ga
---
# Monitoring Azure Functions [azure-functions-support]
## Prerequisites [_prerequisites_2]
You need an APM Server to which you can send APM data. Follow the [APM Quick start](docs-content://solutions/observability/apm/get-started-fleet-managed-apm-server.md) if you have not set one up yet. For the best-possible performance, we recommend setting up APM on {{ecloud}} in the same Azure region as your Azure Functions app.
::::{note}
Currently, only HTTP and timer triggers are supported. Other trigger types may be captured as well, but the amount of captured contextual data may differ.
::::
## Step 1: Enable Worker Extensions [_step_1_enable_worker_extensions]
Elastic APM uses [Worker Extensions](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-python?tabs=asgi%2Capplication-level&pivots=python-mode-configuration#python-worker-extensions) to instrument Azure Functions. This feature is not enabled by default, and must be enabled in your Azure Functions App. Please follow the instructions in the [Azure docs](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-python?tabs=asgi%2Capplication-level&pivots=python-mode-configuration#using-extensions).
Once you have enabled Worker Extensions, these two lines of code will enable Elastic APM’s extension:
```python
from elasticapm.contrib.serverless.azure import ElasticAPMExtension
ElasticAPMExtension.configure()
```
Put them somewhere at the top of your Python file, before the function definitions.
## Step 2: Install the APM Python Agent [_step_2_install_the_apm_python_agent]
You need to add `elastic-apm` as a dependency for your Functions app. Simply add `elastic-apm` to your `requirements.txt` file. We recommend pinning the version to the current newest version of the agent, and periodically updating the version.
## Step 3: Configure APM on Azure Functions [_step_3_configure_apm_on_azure_functions]
The APM Python agent is configured through [App Settings](https://learn.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings?tabs=portal#settings). These are then picked up by the agent as environment variables.
For the minimal configuration, you will need the [`ELASTIC_APM_SERVER_URL`](/reference/configuration.md#config-server-url) to set the destination for APM data and a [`ELASTIC_APM_SECRET_TOKEN`](/reference/configuration.md#config-secret-token). If you prefer to use an [APM API key](docs-content://solutions/observability/apm/api-keys.md) instead of the APM secret token, use the [`ELASTIC_APM_API_KEY`](/reference/configuration.md#config-api-key) environment variable instead of `ELASTIC_APM_SECRET_TOKEN` in the following example configuration.
```bash
$ az functionapp config appsettings set --settings ELASTIC_APM_SERVER_URL=https://example.apm.northeurope.azure.elastic-cloud.com:443
$ az functionapp config appsettings set --settings ELASTIC_APM_SECRET_TOKEN=verysecurerandomstring
```
You can optionally [fine-tune the Python agent](/reference/configuration.md).
That’s it; Once the agent is installed and working, spans will be captured for [supported technologies](/reference/supported-technologies.md). You can also use [`capture_span`](/reference/api-reference.md#api-capture-span) to capture custom spans, and you can retrieve the `Client` object for capturing exceptions/messages using [`get_client`](/reference/api-reference.md#api-get-client).
python-elastic-apm-6.26.2/docs/reference/configuration.md 0000664 0000000 0000000 00000127673 15216207663 0023434 0 ustar 00root root 0000000 0000000 ---
mapped_pages:
- https://www.elastic.co/guide/en/apm/agent/python/current/configuration.html
applies_to:
stack:
serverless:
observability:
product:
apm_agent_python: ga
---
# Configuration [configuration]
To adapt the Elastic APM agent to your needs, configure it using environment variables or framework-specific configuration.
You can either configure the agent by setting environment variables:
```bash
ELASTIC_APM_SERVICE_NAME=foo python manage.py runserver
```
or with inline configuration:
```python
apm_client = Client(service_name="foo")
```
or by using framework specific configuration e.g. in your Django `settings.py` file:
```python
ELASTIC_APM = {
"SERVICE_NAME": "foo",
}
```
The precedence is as follows:
* [Central configuration](#config-central_config) (supported options are marked with [ ](#dynamic-configuration))
* Environment variables
* Inline configuration
* Framework-specific configuration
* Default value
## Dynamic configuration [dynamic-configuration]
Configuration options marked with the  badge can be changed at runtime when set from a supported source.
The Python Agent supports [Central configuration](docs-content://solutions/observability/apm/apm-agent-central-configuration.md), which allows you to fine-tune certain configurations from in the APM app. This feature is enabled in the Agent by default with [`central_config`](#config-central_config).
## Django [django-configuration]
To configure Django, add an `ELASTIC_APM` dictionary to your `settings.py`:
```python
ELASTIC_APM = {
'SERVICE_NAME': 'my-app',
'SECRET_TOKEN': 'changeme',
}
```
## Flask [flask-configuration]
To configure Flask, add an `ELASTIC_APM` dictionary to your `app.config`:
```python
app.config['ELASTIC_APM'] = {
'SERVICE_NAME': 'my-app',
'SECRET_TOKEN': 'changeme',
}
apm = ElasticAPM(app)
```
## Core options [core-options]
### `service_name` [config-service-name]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_SERVICE_NAME` | `SERVICE_NAME` | `unknown-python-service` | `my-app` |
The name of your service. This is used to keep all the errors and transactions of your service together and is the primary filter in the Elastic APM user interface.
While a default is provided, it is essential that you override this default with something more descriptive and unique across your infrastructure.
::::{note}
The service name must conform to this regular expression: `^[a-zA-Z0-9 _-]+$`. In other words, the service name must only contain characters from the ASCII alphabet, numbers, dashes, underscores, and spaces. It cannot be an empty string or whitespace-only.
::::
### `server_url` [config-server-url]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SERVER_URL` | `SERVER_URL` | `'http://127.0.0.1:8200'` |
The URL for your APM Server. The URL must be fully qualified, including protocol (`http` or `https`) and port. Note: Do not set this if you are using APM in an AWS lambda function. APM Agents are designed to proxy their calls to the APM Server through the lambda extension. Instead, set `ELASTIC_APM_LAMBDA_APM_SERVER`. For more info, see [AWS Lambda](lambda-support.md).
## `enabled` [config-enabled]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_ENABLED` | `ENABLED` | `true` |
Enable or disable the agent. When set to false, the agent will not collect any data or start any background threads.
## `recording` [config-recording]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_RECORDING` | `RECORDING` | `true` |
Enable or disable recording of events. If set to false, then the Python agent does not send any events to the Elastic APM server, and instrumentation overhead is minimized. The agent will continue to poll the server for configuration changes.
## Logging Options [logging-options]
### `log_level` [config-log_level]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_LOG_LEVEL` | `LOG_LEVEL` | |
The `logging.logLevel` at which the `elasticapm` logger will log. The available options are:
* `"off"` (sets `logging.logLevel` to 1000)
* `"critical"`
* `"error"`
* `"warning"`
* `"info"`
* `"debug"`
* `"trace"` (sets `logging.log_level` to 5)
Options are case-insensitive
Note that this option doesn’t do anything with logging handlers. In order for any logs to be visible, you must either configure a handler ([`logging.basicConfig`](https://docs.python.org/3/library/logging.html#logging.basicConfig) will do this for you) or set [`log_file`](#config-log_file). This will also override any log level your app has set for the `elasticapm` logger.
### `log_file` [config-log_file]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_LOG_FILE` | `LOG_FILE` | `""` | `"/var/log/elasticapm/log.txt"` |
This enables the agent to log to a file. This is disabled by default. The agent will log at the `logging.logLevel` configured with [`log_level`](#config-log_level). Use [`log_file_size`](#config-log_file_size) to configure the maximum size of the log file. This log file will automatically rotate.
Note that setting [`log_level`](#config-log_level) is required for this setting to do anything.
If [`ecs_logging`](https://github.com/elastic/ecs-logging-python) is installed, the logs will automatically be formatted as ecs-compatible json.
### `log_file_size` [config-log_file_size]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_LOG_FILE_SIZE` | `LOG_FILE_SIZE` | `"50mb"` | `"100mb"` |
The size of the log file if [`log_file`](#config-log_file) is set.
The agent always keeps one backup file when rotating, so the maximum space that the log files will consume is twice the value of this setting.
### `log_ecs_reformatting` [config-log_ecs_reformatting]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_LOG_ECS_REFORMATTING` | `LOG_ECS_REFORMATTING` | `"off"` |
::::{warning}
This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.
::::
Valid options:
* `"off"`
* `"override"`
If [`ecs_logging`](https://github.com/elastic/ecs-logging-python) is installed, setting this to `"override"` will cause the agent to automatically attempt to enable ecs-formatted logging.
For base `logging` from the standard library, the agent will get the root logger, find any attached handlers, and for each, set the formatter to `ecs_logging.StdlibFormatter()`.
If `structlog` is installed, the agent will override any configured processors with `ecs_logging.StructlogFormatter()`.
Note that this is a very blunt instrument that could have unintended side effects. If problems arise, please apply these formatters manually and leave this setting as `"off"`. See the [`ecs_logging` docs](ecs-logging-python://reference/installation.md) for more information about using these formatters.
Also note that this setting does not facilitate shipping logs to Elasticsearch. We recommend [Filebeat](https://www.elastic.co/beats/filebeat) for that purpose.
## Other options [other-options]
### `transport_class` [config-transport-class]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_TRANSPORT_CLASS` | `TRANSPORT_CLASS` | `elasticapm.transport.http.Transport` |
The transport class to use when sending events to the APM Server.
### `service_node_name` [config-service-node-name]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_SERVICE_NODE_NAME` | `SERVICE_NODE_NAME` | `None` | `"redis1"` |
The name of the given service node. This is optional and if omitted, the APM Server will fall back on `system.container.id` if available, and `host.name` if necessary.
This option allows you to set the node name manually to ensure it is unique and meaningful.
### `environment` [config-environment]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_ENVIRONMENT` | `ENVIRONMENT` | `None` | `"production"` |
The name of the environment this service is deployed in, e.g. "production" or "staging".
Environments allow you to easily filter data on a global level in the APM app. It’s important to be consistent when naming environments across agents. See [environment selector](docs-content://solutions/observability/apm/filter-data.md#apm-filter-your-data-service-environment-filter) in the APM app for more information.
::::{note}
This feature is fully supported in the APM app in Kibana versions >= 7.2. You must use the query bar to filter for a specific environment in versions prior to 7.2.
::::
### `cloud_provider` [config-cloud-provider]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_CLOUD_PROVIDER` | `CLOUD_PROVIDER` | `"auto"` | `"aws"` |
This config value allows you to specify which cloud provider should be assumed for metadata collection. By default, the agent will attempt to detect the cloud provider or, if that fails, will use trial and error to collect the metadata.
Valid options are `"auto"`, `"aws"`, `"gcp"`, and `"azure"`. If this config value is set to `"none"`, then no cloud metadata will be collected.
### `secret_token` [config-secret-token]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_SECRET_TOKEN` | `SECRET_TOKEN` | `None` | A random string |
This string is used to ensure that only your agents can send data to your APM Server. Both the agents and the APM Server have to be configured with the same secret token. An example to generate a secure secret token is:
```bash
python -c "import secrets; print(secrets.token_urlsafe(32))"
```
::::{warning}
Secret tokens only provide any security if your APM Server uses TLS.
::::
### `api_key` [config-api-key]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_API_KEY` | `API_KEY` | `None` | A base64-encoded string |
This base64-encoded string is used to ensure that only your agents can send data to your APM Server. The API key can be created in the [Applications UI](docs-content://solutions/observability/apm/api-keys.md#apm-create-an-api-key).
::::{warning}
API keys only provide any real security if your APM Server uses TLS.
::::
### `service_version` [config-service-version]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_SERVICE_VERSION` | `SERVICE_VERSION` | `None` | A string indicating the version of the deployed service |
A version string for the currently deployed version of the service. If youre deploys are not versioned, the recommended value for this field is the commit identifier of the deployed revision, e.g. the output of `git rev-parse HEAD`.
### `framework_name` [config-framework-name]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_FRAMEWORK_NAME` | `FRAMEWORK_NAME` | Depending on framework |
The name of the used framework. For Django and Flask, this defaults to `django` and `flask` respectively, otherwise, the default is `None`.
### `framework_version` [config-framework-version]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_FRAMEWORK_VERSION` | `FRAMEWORK_VERSION` | Depending on framework |
The version number of the used framework. For Django and Flask, this defaults to the used version of the framework, otherwise, the default is `None`.
### `filter_exception_types` [config-filter-exception-types]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_FILTER_EXCEPTION_TYPES` | `FILTER_EXCEPTION_TYPES` | `[]` | `['OperationalError', 'mymodule.SomeoneElsesProblemError']` |
| multiple values separated by commas, without spaces | | | |
A list of exception types to be filtered. Exceptions of these types will not be sent to the APM Server.
### `transaction_ignore_urls` [config-transaction-ignore-urls]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_TRANSACTION_IGNORE_URLS` | `TRANSACTION_IGNORE_URLS` | `[]` | `['/api/ping', '/static/*']` |
| multiple values separated by commas, without spaces | | | |
A list of URLs for which the agent should not capture any transaction data.
Optionally, `*` can be used to match multiple URLs at once.
### `transactions_ignore_patterns` [config-transactions-ignore-patterns]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_TRANSACTIONS_IGNORE_PATTERNS` | `TRANSACTIONS_IGNORE_PATTERNS` | `[]` | `['^OPTIONS ', 'myviews.Healthcheck']` |
| multiple values separated by commas, without spaces | | | |
A list of regular expressions. Transactions with a name that matches any of the configured patterns will be ignored and not sent to the APM Server.
::::{note}
as the the name of the transaction can only be determined at the end of the transaction, the agent might still cause overhead for transactions ignored through this setting. If agent overhead is a concern, we recommend [`transaction_ignore_urls`](#config-transaction-ignore-urls) instead.
::::
### `server_timeout` [config-server-timeout]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SERVER_TIMEOUT` | `SERVER_TIMEOUT` | `"5s"` |
A timeout for requests to the APM Server. The setting has to be provided in **[duration format](#config-format-duration)**. If a request to the APM Server takes longer than the configured timeout, the request is cancelled and the event (exception or transaction) is discarded. Set to `None` to disable timeouts.
::::{warning}
If timeouts are disabled or set to a high value, your app could experience memory issues if the APM Server times out.
::::
### `hostname` [config-hostname]
| Environment | Django/Flask | Default | Example |
| --- | --- | --- | --- |
| `ELASTIC_APM_HOSTNAME` | `HOSTNAME` | `socket.gethostname()` | `app-server01.example.com` |
The host name to use when sending error and transaction data to the APM Server.
### `auto_log_stacks` [config-auto-log-stacks]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_AUTO_LOG_STACKS` | `AUTO_LOG_STACKS` | `True` |
| set to `"true"` / `"false"` | | |
If set to `True` (the default), the agent will add a stack trace to each log event, indicating where the log message has been issued.
This setting can be overridden on an individual basis by setting the `extra`-key `stack`:
```python
logger.info('something happened', extra={'stack': False})
```
### `collect_local_variables` [config-collect-local-variables]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_COLLECT_LOCAL_VARIABLES` | `COLLECT_LOCAL_VARIABLES` | `errors` |
Possible values: `errors`, `transactions`, `all`, `off`
The Elastic APM Python agent can collect local variables for stack frames. By default, this is only done for errors.
::::{note}
Collecting local variables has a non-trivial overhead. Collecting local variables for transactions in production environments can have adverse effects for the performance of your service.
::::
### `local_var_max_length` [config-local-var-max-length]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_LOCAL_VAR_MAX_LENGTH` | `LOCAL_VAR_MAX_LENGTH` | `200` |
When collecting local variables, they will be converted to strings. This setting allows you to limit the length of the resulting string.
### `local_var_list_max_length` [config-local-list-var-max-length]
| | | |
| --- | --- | --- |
| Environment | Django/Flask | Default |
| `ELASTIC_APM_LOCAL_VAR_LIST_MAX_LENGTH` | `LOCAL_VAR_LIST_MAX_LENGTH` | `10` |
This setting allows you to limit the length of lists in local variables.
### `local_var_dict_max_length` [config-local-dict-var-max-length]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_LOCAL_VAR_DICT_MAX_LENGTH` | `LOCAL_VAR_DICT_MAX_LENGTH` | `10` |
This setting allows you to limit the length of dicts in local variables.
### `source_lines_error_app_frames` [config-source-lines-error-app-frames]
### `source_lines_error_library_frames` [config-source-lines-error-library-frames]
### `source_lines_span_app_frames` [config-source-lines-span-app-frames]
### `source_lines_span_library_frames` [config-source-lines-span-library-frames]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SOURCE_LINES_ERROR_APP_FRAMES` | `SOURCE_LINES_ERROR_APP_FRAMES` | `5` |
| `ELASTIC_APM_SOURCE_LINES_ERROR_LIBRARY_FRAMES` | `SOURCE_LINES_ERROR_LIBRARY_FRAMES` | `5` |
| `ELASTIC_APM_SOURCE_LINES_SPAN_APP_FRAMES` | `SOURCE_LINES_SPAN_APP_FRAMES` | `0` |
| `ELASTIC_APM_SOURCE_LINES_SPAN_LIBRARY_FRAMES` | `SOURCE_LINES_SPAN_LIBRARY_FRAMES` | `0` |
By default, the APM agent collects source code snippets for errors. This setting allows you to modify the number of lines of source code that are being collected.
We differ between errors and spans, as well as library frames and app frames.
::::{warning}
Especially for spans, collecting source code can have a large impact on storage use in your Elasticsearch cluster.
::::
### `capture_body` [config-capture-body]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_CAPTURE_BODY` | `CAPTURE_BODY` | `off` |
For transactions that are HTTP requests, the Python agent can optionally capture the request body (e.g. `POST` variables).
Possible values: `errors`, `transactions`, `all`, `off`.
If the request has a body and this setting is disabled, the body will be shown as `[REDACTED]`.
For requests with a content type of `multipart/form-data`, any uploaded files will be referenced in a special `_files` key. It contains the name of the field and the name of the uploaded file, if provided.
::::{warning}
Request bodies often contain sensitive values like passwords and credit card numbers. If your service handles data like this, we advise to only enable this feature with care.
::::
### `capture_headers` [config-capture-headers]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_CAPTURE_HEADERS` | `CAPTURE_HEADERS` | `true` |
For transactions and errors that happen due to HTTP requests, the Python agent can optionally capture the request and response headers.
Possible values: `true`, `false`
::::{warning}
Request headers often contain sensitive values like session IDs and cookies. See [sanitizing data](sanitizing-data.md) for more information on how to filter out sensitive data.
::::
### `transaction_max_spans` [config-transaction-max-spans]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_TRANSACTION_MAX_SPANS` | `TRANSACTION_MAX_SPANS` | `500` |
This limits the amount of spans that are recorded per transaction. This is helpful in cases where a transaction creates a very high amount of spans (e.g. thousands of SQL queries). Setting an upper limit will prevent edge cases from overloading the agent and the APM Server.
### `stack_trace_limit` [config-stack-trace-limit]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_STACK_TRACE_LIMIT` | `STACK_TRACE_LIMIT` | `50` |
This limits the number of frames captured for each stack trace.
Setting the limit to `0` will disable stack trace collection, while any positive integer value will be used as the maximum number of frames to collect. To disable the limit and always capture all frames, set the value to `-1`.
### `span_stack_trace_min_duration` [config-span-stack-trace-min-duration]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SPAN_STACK_TRACE_MIN_DURATION` | `SPAN_STACK_TRACE_MIN_DURATION` | `"5ms"` |
By default, the APM agent collects a stack trace with every recorded span that has a duration equal to or longer than this configured threshold. While stack traces are very helpful to find the exact place in your code from which a span originates, collecting this stack trace does have some overhead. Tune this threshold to ensure that you only collect stack traces for spans that could be problematic.
To collect traces for all spans, regardless of their length, set the value to `0`.
To disable stack trace collection for spans completely, set the value to `-1`.
Except for the special values `-1` and `0`, this setting should be provided in **[duration format](#config-format-duration)**.
### `span_frames_min_duration` [config-span-frames-min-duration]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SPAN_FRAMES_MIN_DURATION` | `SPAN_FRAMES_MIN_DURATION` | `"5ms"` |
::::{note}
This config value is being deprecated. Use [`span_stack_trace_min_duration`](#config-span-stack-trace-min-duration) instead.
::::
### `span_compression_enabled` [config-span-compression-enabled]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SPAN_COMPRESSION_ENABLED` | `SPAN_COMPRESSION_ENABLED` | `True` |
Enable/disable span compression.
If enabled, the agent will compress very short, repeated spans into a single span, which is beneficial for storage and processing requirements. Some information is lost in this process, e.g. exact durations of each compressed span.
### `span_compression_exact_match_max_duration` [config-span-compression-exact-match-max_duration]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SPAN_COMPRESSION_EXACT_MATCH_MAX_DURATION` | `SPAN_COMPRESSION_EXACT_MATCH_MAX_DURATION` | `"50ms"` |
Consecutive spans that are exact match and that are under this threshold will be compressed into a single composite span. This reduces the collection, processing, and storage overhead, and removes clutter from the UI. The tradeoff is that the DB statements of all the compressed spans will not be collected.
Two spans are considered exact matches if the following attributes are identical: * span name * span type * span subtype * destination resource (e.g. the Database name)
### `span_compression_same_kind_max_duration` [config-span-compression-same-kind-max-duration]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SPAN_COMPRESSION_SAME_KIND_MAX_DURATION` | `SPAN_COMPRESSION_SAME_KIND_MAX_DURATION` | `"0ms"` (disabled) |
Consecutive spans to the same destination that are under this threshold will be compressed into a single composite span. This reduces the collection, processing, and storage overhead, and removes clutter from the UI. The tradeoff is that metadata such as database statements of all the compressed spans will not be collected.
Two spans are considered to be of the same kind if the following attributes are identical: * span type * span subtype * destination resource (e.g. the Database name)
### `exit_span_min_duration` [config-exit-span-min-duration]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_EXIT_SPAN_MIN_DURATION` | `EXIT_SPAN_MIN_DURATION` | `"0ms"` |
Exit spans are spans that represent a call to an external service, like a database. If such calls are very short, they are usually not relevant and can be ignored.
This feature is disabled by default.
::::{note}
if a span propagates distributed tracing IDs, it will not be ignored, even if it is shorter than the configured threshold. This is to ensure that no broken traces are recorded.
::::
### `api_request_size` [config-api-request-size]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_API_REQUEST_SIZE` | `API_REQUEST_SIZE` | `"768kb"` |
The maximum queue length of the request buffer before sending the request to the APM Server. A lower value will increase the load on your APM Server, while a higher value can increase the memory pressure of your app. A higher value also impacts the time until data is indexed and searchable in Elasticsearch.
This setting is useful to limit memory consumption if you experience a sudden spike of traffic. It has to be provided in **[size format](#config-format-size)**.
::::{note}
Due to internal buffering of gzip, the actual request size can be a few kilobytes larger than the given limit. By default, the APM Server limits request payload size to `1 MByte`.
::::
### `api_request_time` [config-api-request-time]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_API_REQUEST_TIME` | `API_REQUEST_TIME` | `"10s"` |
The maximum queue time of the request buffer before sending the request to the APM Server. A lower value will increase the load on your APM Server, while a higher value can increase the memory pressure of your app. A higher value also impacts the time until data is indexed and searchable in Elasticsearch.
This setting is useful to limit memory consumption if you experience a sudden spike of traffic. It has to be provided in **[duration format](#config-format-duration)**.
::::{note}
The actual time will vary between 90-110% of the given value, to avoid stampedes of instances that start at the same time.
::::
### `processors` [config-processors]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_PROCESSORS` | `PROCESSORS` | `['elasticapm.processors.sanitize_stacktrace_locals', 'elasticapm.processors.sanitize_http_request_cookies', 'elasticapm.processors.sanitize_http_headers', 'elasticapm.processors.sanitize_http_wsgi_env', 'elasticapm.processors.sanitize_http_request_body']` |
A list of processors to process transactions and errors. For more information, see [Sanitizing Data](sanitizing-data.md).
::::{warning}
We recommend always including the default set of validators if you customize this setting.
::::
### `sanitize_field_names` [config-sanitize-field-names]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SANITIZE_FIELD_NAMES` | `SANITIZE_FIELD_NAMES` | `["password", "passwd", "pwd", "secret", "*key", "*token*", "*session*", "*credit*", "*card*", "*auth*", "*principal*", "set-cookie"]` |
A list of glob-matched field names to match and mask when using processors. For more information, see [Sanitizing Data](sanitizing-data.md).
::::{warning}
We recommend always including the default set of field name matches if you customize this setting.
::::
### `transaction_sample_rate` [config-transaction-sample-rate]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_TRANSACTION_SAMPLE_RATE` | `TRANSACTION_SAMPLE_RATE` | `1.0` |
By default, the agent samples every transaction (e.g. request to your service). To reduce overhead and storage requirements, set the sample rate to a value between `0.0` and `1.0`. We still record overall time and the result for unsampled transactions, but no context information, labels, or spans.
::::{note}
This setting will be automatically rounded to 4 decimals of precision.
::::
### `include_paths` [config-include-paths]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_INCLUDE_PATHS` | `INCLUDE_PATHS` | `[]` |
| multiple values separated by commas, without spaces | | |
A set of paths, optionally using shell globs (see [`fnmatch`](https://docs.python.org/3/library/fnmatch.html) for a description of the syntax). These are matched against the absolute filename of every frame, and if a pattern matches, the frame is considered to be an "in-app frame".
`include_paths` **takes precedence** over `exclude_paths`.
### `exclude_paths` [config-exclude-paths]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_EXCLUDE_PATHS` | `EXCLUDE_PATHS` | Varies on Python version and implementation |
| multiple values separated by commas, without spaces | | |
A set of paths, optionally using shell globs (see [`fnmatch`](https://docs.python.org/3/library/fnmatch.html) for a description of the syntax). These are matched against the absolute filename of every frame, and if a pattern matches, the frame is considered to be a "library frame".
`include_paths` **takes precedence** over `exclude_paths`.
The default value varies based on your Python version and implementation, e.g.:
* PyPy3: `['\*/lib-python/3/*', '\*/site-packages/*']`
* CPython 2.7: `['\*/lib/python2.7/*', '\*/lib64/python2.7/*']`
### `debug` [config-debug]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_DEBUG` | `DEBUG` | `False` |
If your app is in debug mode (e.g. in Django with `settings.DEBUG = True` or in Flask with `app.debug = True`), the agent won’t send any data to the APM Server. You can override it by changing this setting to `True`.
### `disable_send` [config-disable-send]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_DISABLE_SEND` | `DISABLE_SEND` | `False` |
If set to `True`, the agent won’t send any events to the APM Server, independent of any debug state.
### `instrument` [config-instrument]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_INSTRUMENT` | `INSTRUMENT` | `True` |
If set to `False`, the agent won’t instrument any code. This disables most of the tracing functionality, but can be useful to debug possible instrumentation issues.
### `verify_server_cert` [config-verify-server-cert]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_VERIFY_SERVER_CERT` | `VERIFY_SERVER_CERT` | `True` |
By default, the agent verifies the SSL certificate if an HTTPS connection to the APM Server is used. Verification can be disabled by changing this setting to `False`. This setting is ignored when [`server_cert`](#config-server-cert) is set.
### `server_cert` [config-server-cert]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SERVER_CERT` | `SERVER_CERT` | `None` |
If you have configured your APM Server with a self-signed TLS certificate, or you just wish to pin the server certificate, you can specify the path to the PEM-encoded certificate via the `ELASTIC_APM_SERVER_CERT` configuration.
::::{note}
If this option is set, the agent only verifies that the certificate provided by the APM Server is identical to the one configured here. Validity of the certificate is not checked.
::::
### `server_ca_cert_file` [config-server-ca-cert-file]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SERVER_CA_CERT_FILE` | `SERVER_CA_CERT_FILE` | `None` |
By default, the agent will validate the TLS/SSL certificate of the APM Server using the well-known CAs curated by Mozilla, and provided by the [`certifi`](https://pypi.org/project/certifi/) package.
You can set this option to the path of a file containing a CA certificate that will be used instead.
Specifying this option is required when using self-signed certificates, unless server certificate validation is disabled.
### `use_certifi` [config-use-certifi]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_USE_CERTIFI` | `USE_CERTIFI` | `True` |
By default, the Python Agent uses the [`certifi`](https://pypi.org/project/certifi/) certificate store. To use Python’s default mechanism for finding certificates, set this option to `False`.
### `metrics_interval` [config-metrics_interval]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_METRICS_INTERVAL` | `METRICS_INTERVAL` | `30s` |
The interval in which the agent collects metrics. A shorter interval increases the granularity of metrics, but also increases the overhead of the agent, as well as storage requirements.
It has to be provided in **[duration format](#config-format-duration)**.
### `disable_metrics` [config-disable_metrics]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_DISABLE_METRICS` | `DISABLE_METRICS` | `None` |
A comma-separated list of dotted metrics names that should not be sent to the APM Server. You can use `*` to match multiple metrics; for example, to disable all CPU-related metrics, as well as the "total system memory" metric, set `disable_metrics` to:
```
"*.cpu.*,system.memory.total"
```
::::{note}
This setting only disables the **sending** of the given metrics, not collection.
::::
### `breakdown_metrics` [config-breakdown_metrics]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_BREAKDOWN_METRICS` | `BREAKDOWN_METRICS` | `True` |
Enable or disable the tracking and collection of breakdown metrics. Setting this to `False` disables the tracking of breakdown metrics, which can reduce the overhead of the agent.
::::{note}
This feature requires APM Server and Kibana >= 7.3.
::::
### `prometheus_metrics` (Beta) [config-prometheus_metrics]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_PROMETHEUS_METRICS` | `PROMETHEUS_METRICS` | `False` |
Enable/disable the tracking and collection of metrics from `prometheus_client`.
See [Prometheus metric set (beta)](metrics.md#prometheus-metricset) for more information.
::::{note}
This feature is currently in beta status.
::::
### `prometheus_metrics_prefix` (Beta) [config-prometheus_metrics_prefix]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_PROMETHEUS_METRICS_PREFIX` | `PROMETHEUS_METRICS_PREFIX` | `prometheus.metrics.` |
A prefix to prepend to Prometheus metrics names.
See [Prometheus metric set (beta)](metrics.md#prometheus-metricset) for more information.
::::{note}
This feature is currently in beta status.
::::
### `metrics_sets` [config-metrics_sets]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_METRICS_SETS` | `METRICS_SETS` | ["elasticapm.metrics.sets.cpu.CPUMetricSet"] |
List of import paths for the MetricSets that should be used to collect metrics.
See [Custom Metrics](metrics.md#custom-metrics) for more information.
### `central_config` [config-central_config]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_CENTRAL_CONFIG` | `CENTRAL_CONFIG` | `True` |
When enabled, the agent will make periodic requests to the APM Server to fetch updated configuration.
See [Dynamic configuration](#dynamic-configuration) for more information.
::::{note}
This feature requires APM Server and Kibana >= 7.3.
::::
### `global_labels` [config-global_labels]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_GLOBAL_LABELS` | `GLOBAL_LABELS` | `None` |
Labels added to all events, with the format `key=value[,key=value[,...]]`. Any labels set by application via the API will override global labels with the same keys.
::::{note}
This feature requires APM Server >= 7.2.
::::
### `disable_log_record_factory` [config-generic-disable-log-record-factory]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_DISABLE_LOG_RECORD_FACTORY` | `DISABLE_LOG_RECORD_FACTORY` | `False` |
By default in python 3, the agent installs a [LogRecord factory](logs.md#logging) that automatically adds tracing fields to your log records. Disable this behavior by setting this to `True`.
### `use_elastic_traceparent_header` [config-use-elastic-traceparent-header]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_USE_ELASTIC_TRACEPARENT_HEADER` | `USE_ELASTIC_TRACEPARENT_HEADER` | `True` |
To enable [distributed tracing](docs-content://solutions/observability/apm/traces.md), the agent sets a number of HTTP headers to outgoing requests made with [instrumented HTTP libraries](supported-technologies.md#automatic-instrumentation-http). These headers (`traceparent` and `tracestate`) are defined in the [W3C Trace Context](https://www.w3.org/TR/trace-context-1/) specification.
Additionally, when this setting is set to `True`, the agent will set `elasticapm-traceparent` for backwards compatibility.
### `trace_continuation_strategy` [config-trace-continuation-strategy]
[ ](#dynamic-configuration)
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_TRACE_CONTINUATION_STRATEGY` | `TRACE_CONTINUATION_STRATEGY` | `continue` |
This option allows some control on how the APM agent handles W3C trace-context headers on incoming requests. By default, the `traceparent` and `tracestate` headers are used per W3C spec for distributed tracing. However, in certain cases it can be helpful to **not** use the incoming `traceparent` header. Some example use cases:
* An Elastic-monitored service is receiving requests with `traceparent` headers from **unmonitored** services.
* An Elastic-monitored service is publicly exposed, and does not want tracing data (trace-ids, sampling decisions) to possibly be spoofed by user requests.
Valid values are:
* `'continue'`: The default behavior. An incoming `traceparent` value is used to continue the trace and determine the sampling decision.
* `'restart'`: Always ignores the `traceparent` header of incoming requests. A new trace-id will be generated and the sampling decision will be made based on [`transaction_sample_rate`](#config-transaction-sample-rate). A **span link** will be made to the incoming traceparent.
* `'restart_external'`: If an incoming request includes the `es` vendor flag in `tracestate`, then any *traceparent* will be considered internal and will be handled as described for `'continue'` above. Otherwise, any `'traceparent'` is considered external and will be handled as described for `'restart'` above.
Starting with Elastic Observability 8.2, span links will be visible in trace views.
### `use_elastic_excepthook` [config-use-elastic-excepthook]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_USE_ELASTIC_EXCEPTHOOK` | `USE_ELASTIC_EXCEPTHOOK` | `False` |
If set to `True`, the agent will intercept the default `sys.excepthook`, which allows the agent to collect all uncaught exceptions.
### `include_process_args` [config-include-process-args]
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_INCLUDE_PROCESS_ARGS` | `INCLUDE_PROCESS_ARGS` | `False` |
Whether each transaction should have the process arguments attached. Disabled by default to save disk space.
### `skip_server_info` [config-skip-server-info]
```{applies_to}
apm_agent_python: preview 6.25.0
```
| Environment | Django/Flask | Default |
| --- | --- | --- |
| `ELASTIC_APM_SKIP_SERVER_INFO` | `SKIP_SERVER_INFO` | `False` |
Whether we should skip the server info check to save some latency on constrained environments like AWS Lambda. Disabled by default.
::::{warning}
This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.
::::
::::{warning}
This requires sending data to an APM Server newer than 8.7.0 in order to work properly.
::::
## Django-specific configuration [config-django-specific]
### `django_transaction_name_from_route` [config-django-transaction-name-from-route]
| Environment | Django | Default |
| --- | --- | --- |
| `ELASTIC_APM_DJANGO_TRANSACTION_NAME_FROM_ROUTE` | `DJANGO_TRANSACTION_NAME_FROM_ROUTE` | `False` |
By default, we use the function or class name of the view as the transaction name. Starting with Django 2.2, Django makes the route (e.g. `users//`) available on the `request.resolver_match` object. If you want to use the route instead of the view name as the transaction name, set this config option to `true`.
::::{note}
in versions previous to Django 2.2, changing this setting will have no effect.
::::
### `django_autoinsert_middleware` [config-django-autoinsert-middleware]
| Environment | Django | Default |
| --- | --- | --- |
| `ELASTIC_APM_DJANGO_AUTOINSERT_MIDDLEWARE` | `DJANGO_AUTOINSERT_MIDDLEWARE` | `True` |
To trace Django requests, the agent uses a middleware, `elasticapm.contrib.django.middleware.TracingMiddleware`. By default, this middleware is inserted automatically as the first item in `settings.MIDDLEWARES`. To disable the automatic insertion of the middleware, change this setting to `False`.
## Generic Environment variables [config-generic-environment]
Some environment variables that are not specific to the APM agent can be used to configure the agent.
### `HTTP_PROXY` and `HTTPS_PROXY` [config-generic-http-proxy]
By using `HTTP_PROXY` and `HTTPS_PROXY`, the agent can be instructed to use a proxy to connect to the APM Server. If both are set, `HTTPS_PROXY` takes precedence.
::::{note}
The environment variables are case-insensitive.
::::
### `NO_PROXY` [config-generic-no-proxy]
To instruct the agent to **not** use a proxy, you can use the `NO_PROXY` environment variable. You can either set it to a comma-separated list of hosts for which no proxy should be used (e.g. `localhost,example.com`) or use `*` to match any host.
This is useful if `HTTP_PROXY` / `HTTPS_PROXY` is set for other reasons than agent / APM Server communication.
### `SSL_CERT_FILE` and `SSL_CERT_DIR` [config-ssl-cert-file]
To tell the agent to use a different SSL certificate, you can use these environment variables. See also [OpenSSL docs](https://www.openssl.org/docs/manmaster/man7/openssl-env.html#SSL_CERT_DIR-SSL_CERT_FILE).
Please note that these variables may apply to other SSL/TLS communication in your service, not just related to the APM agent.
::::{note}
These environment variables only take effect if [`use_certifi`](#config-use-certifi) is set to `False`.
::::
## Configuration formats [config-formats]
Some options require a unit, either duration or size. These need to be provided in a specific format.
### Duration format [config-format-duration]
The *duration* format is used for options like timeouts. The unit is provided as a suffix directly after the number–without any separation by whitespace.
**Example**: `5ms`
**Supported units**
* `us` (microseconds)
* `ms` (milliseconds)
* `s` (seconds)
* `m` (minutes)
### Size format [config-format-size]
The *size* format is used for options like maximum buffer sizes. The unit is provided as suffix directly after the number, without and separation by whitespace.
**Example**: `10kb`
**Supported units**:
* `b` (bytes)
* `kb` (kilobytes)
* `mb` (megabytes)
* `gb` (gigabytes)
::::{note}
We use the power-of-two sizing convention, e.g. `1 kilobyte == 1024 bytes`
::::
python-elastic-apm-6.26.2/docs/reference/django-support.md 0000664 0000000 0000000 00000026171 15216207663 0023530 0 ustar 00root root 0000000 0000000 ---
mapped_pages:
- https://www.elastic.co/guide/en/apm/agent/python/current/django-support.html
applies_to:
stack:
serverless:
observability:
product:
apm_agent_python: ga
---
# Django support [django-support]
Getting Elastic APM set up for your Django project is easy, and there are various ways you can tweak it to fit to your needs.
## Installation [django-installation]
Install the Elastic APM agent using pip:
```bash
$ pip install elastic-apm
```
or add it to your project’s `requirements.txt` file.
::::{note}
For apm-server 6.2+, make sure you use version 2.0 or higher of `elastic-apm`.
::::
::::{note}
If you use Django with uwsgi, make sure to [enable threads](http://uwsgi-docs.readthedocs.org/en/latest/Options.html#enable-threads) (enabled by default since 2.0.27) and [py-call-uwsgi-fork-hooks](https://uwsgi-docs.readthedocs.io/en/latest/Options.html#py-call-uwsgi-fork-hooks).
::::
## Setup [django-setup]
Set up the Elastic APM agent in Django with these two steps:
1. Add `elasticapm.contrib.django` to `INSTALLED_APPS` in your settings:
```python
INSTALLED_APPS = (
# ...
'elasticapm.contrib.django',
)
```
1. Choose a service name, and set the secret token if needed.
```python
ELASTIC_APM = {
'SERVICE_NAME': '',
'SECRET_TOKEN': '',
}
```
or as environment variables:
```shell
ELASTIC_APM_SERVICE_NAME=
ELASTIC_APM_SECRET_TOKEN=
```
You now have basic error logging set up, and everything resulting in a 500 HTTP status code will be reported to the APM Server.
You can find a list of all available settings in the [Configuration](/reference/configuration.md) page.
::::{note}
The agent only captures and sends data if you have `DEBUG = False` in your settings. To force the agent to capture data in Django debug mode, set the [debug](/reference/configuration.md#config-debug) configuration option, e.g.:
```python
ELASTIC_APM = {
'SERVICE_NAME': '',
'DEBUG': True,
}
```
::::
## Performance metrics [django-performance-metrics]
In order to collect performance metrics, the agent automatically inserts a middleware at the top of your middleware list (`settings.MIDDLEWARE` in current versions of Django, `settings.MIDDLEWARE_CLASSES` in some older versions). To disable the automatic insertion of the middleware, see [django_autoinsert_middleware](/reference/configuration.md#config-django-autoinsert-middleware).
::::{note}
For automatic insertion to work, your list of middlewares (`settings.MIDDLEWARE` or `settings.MIDDLEWARE_CLASSES`) must be of type `list` or `tuple`.
::::
In addition to broad request metrics (what will appear in the APM app as transactions), the agent also collects fine grained metrics on template rendering, database queries, HTTP requests, etc. You can find more information on what we instrument in the [Automatic Instrumentation](/reference/supported-technologies.md#automatic-instrumentation) section.
### Instrumenting custom Python code [django-instrumenting-custom-python-code]
To gain further insights into the performance of your code, please see [instrumenting custom code](/reference/instrumenting-custom-code.md).
### Ignoring specific views [django-ignoring-specific-views]
You can use the `TRANSACTIONS_IGNORE_PATTERNS` configuration option to ignore specific views. The list given should be a list of regular expressions which are matched against the transaction name as seen in the Elastic APM user interface:
```python
ELASTIC_APM['TRANSACTIONS_IGNORE_PATTERNS'] = ['^OPTIONS ', 'views.api.v2']
```
This example ignores any requests using the `OPTIONS` method and any requests containing `views.api.v2`.
### Using the route as transaction name [django-transaction-name-route]
By default, we use the function or class name of the view as the transaction name. Starting with Django 2.2, Django makes the route (e.g. `users//`) available on the `request.resolver_match` object. If you want to use the route instead of the view name as the transaction name, you can set the [`django_transaction_name_from_route`](/reference/configuration.md#config-django-transaction-name-from-route) config option to `true`.
```python
ELASTIC_APM['DJANGO_TRANSACTION_NAME_FROM_ROUTE'] = True
```
::::{note}
in versions previous to Django 2.2, changing this setting will have no effect.
::::
### Integrating with the RUM Agent [django-integrating-with-the-rum-agent]
To correlate performance measurement in the browser with measurements in your Django app, you can help the RUM (Real User Monitoring) agent by configuring it with the Trace ID and Span ID of the backend request. We provide a handy template context processor which adds all the necessary bits into the context of your templates.
To enable this feature, first add the `rum_tracing` context processor to your `TEMPLATES` setting. You most likely already have a list of `context_processors`, in which case you can simply append ours to the list.
```python
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'OPTIONS': {
'context_processors': [
# ...
'elasticapm.contrib.django.context_processors.rum_tracing',
],
},
},
]
```
Then, update the call to initialize the RUM agent (which probably happens in your base template) like this:
```javascript
elasticApm.init({
serviceName: "my-frontend-service",
pageLoadTraceId: "{{ apm.trace_id }}",
pageLoadSpanId: "{{ apm.span_id }}",
pageLoadSampled: {{ apm.is_sampled_js }}
})
```
See the [JavaScript RUM agent documentation](apm-agent-rum-js://reference/index.md) for more information.
## Enabling and disabling the agent [django-enabling-and-disabling-the-agent]
The easiest way to disable the agent is to set Django’s `DEBUG` option to `True` in your development configuration. No errors or metrics will be logged to Elastic APM.
However, if during debugging you would like to force logging of errors to Elastic APM, then you can set `DEBUG` to `True` inside of the Elastic APM configuration dictionary, like this:
```python
ELASTIC_APM = {
# ...
'DEBUG': True,
}
```
## Integrating with Python logging [django-logging]
To easily send Python `logging` messages as "error" objects to Elasticsearch, we provide a `LoggingHandler` which you can use in your logging setup. The log messages will be enriched with a stack trace, data from the request, and more.
::::{note}
the intended use case for this handler is to send high priority log messages (e.g. log messages with level `ERROR`) to Elasticsearch. For normal log shipping, we recommend using [filebeat](beats://reference/filebeat/index.md).
::::
If you are new to how the `logging` module works together with Django, read more [in the Django documentation](https://docs.djangoproject.com/en/2.1/topics/logging/).
An example of how your `LOGGING` setting could look:
```python
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
},
'handlers': {
'elasticapm': {
'level': 'WARNING',
'class': 'elasticapm.contrib.django.handlers.LoggingHandler',
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose'
}
},
'loggers': {
'django.db.backends': {
'level': 'ERROR',
'handlers': ['console'],
'propagate': False,
},
'mysite': {
'level': 'WARNING',
'handlers': ['elasticapm'],
'propagate': False,
},
# Log errors from the Elastic APM module to the console (recommended)
'elasticapm.errors': {
'level': 'ERROR',
'handlers': ['console'],
'propagate': False,
},
},
}
```
With this configuration, logging can be done like this in any module in the `myapp` django app:
You can now use the logger in any module in the `myapp` Django app, for instance `myapp/views.py`:
```python
import logging
logger = logging.getLogger('mysite')
try:
instance = MyModel.objects.get(pk=42)
except MyModel.DoesNotExist:
logger.error(
'Could not find instance, doing something else',
exc_info=True
)
```
Note that `exc_info=True` adds the exception information to the data that gets sent to Elastic APM. Without it, only the message is sent.
### Extra data [django-extra-data]
If you want to send more data than what you get with the agent by default, logging can be done like so:
```python
import logging
logger = logging.getLogger('mysite')
try:
instance = MyModel.objects.get(pk=42)
except MyModel.DoesNotExist:
logger.error(
'There was some crazy error',
exc_info=True,
extra={
'datetime': str(datetime.now()),
}
)
```
## Celery integration [django-celery-integration]
For a general guide on how to set up Django with Celery, head over to Celery’s [Django documentation](http://celery.readthedocs.org/en/latest/django/first-steps-with-django.html#django-first-steps).
Elastic APM will automatically log errors from your celery tasks, record performance data and keep the trace.id when the task is launched from an already started Elastic transaction.
## Logging "HTTP 404 Not Found" errors [django-logging-http-404-not-found-errors]
By default, Elastic APM does not log HTTP 404 errors. If you wish to log these errors, add `'elasticapm.contrib.django.middleware.Catch404Middleware'` to `MIDDLEWARE` in your settings:
```python
MIDDLEWARE = (
# ...
'elasticapm.contrib.django.middleware.Catch404Middleware',
# ...
)
```
Note that this middleware respects Django’s [`IGNORABLE_404_URLS`](https://docs.djangoproject.com/en/1.11/ref/settings/#ignorable-404-urls) setting.
## Disable the agent during tests [django-disable-agent-during-tests]
To prevent the agent from sending any data to the APM Server during tests, set the `ELASTIC_APM_DISABLE_SEND` environment variable to `true`, e.g.:
```python
ELASTIC_APM_DISABLE_SEND=true python manage.py test
```
## Troubleshooting [django-troubleshooting]
Elastic APM comes with a Django command that helps troubleshooting your setup. To check your configuration, run
```bash
python manage.py elasticapm check
```
To send a test exception using the current settings, run
```bash
python manage.py elasticapm test
```
If the command succeeds in sending a test exception, it will print a success message:
```bash
python manage.py elasticapm test
Trying to send a test error using these settings:
SERVICE_NAME:
SECRET_TOKEN:
SERVER: http://127.0.0.1:8200
Success! We tracked the error successfully! You should be able to see it in a few seconds.
```
## Supported Django and Python versions [supported-django-and-python-versions]
A list of supported [Django](/reference/supported-technologies.md#supported-django) and [Python](/reference/supported-technologies.md#supported-python) versions can be found on our [Supported Technologies](/reference/supported-technologies.md) page.
python-elastic-apm-6.26.2/docs/reference/flask-support.md 0000664 0000000 0000000 00000015242 15216207663 0023363 0 ustar 00root root 0000000 0000000 ---
mapped_pages:
- https://www.elastic.co/guide/en/apm/agent/python/current/flask-support.html
applies_to:
stack:
serverless:
observability:
product:
apm_agent_python: ga
---
# Flask support [flask-support]
Getting Elastic APM set up for your Flask project is easy, and there are various ways you can tweak it to fit to your needs.
## Installation [flask-installation]
Install the Elastic APM agent using pip:
```bash
$ pip install "elastic-apm[flask]"
```
or add `elastic-apm[flask]` to your project’s `requirements.txt` file.
::::{note}
For apm-server 6.2+, make sure you use version 2.0 or higher of `elastic-apm`.
::::
::::{note}
If you use Flask with uwsgi, make sure to [enable threads](http://uwsgi-docs.readthedocs.org/en/latest/Options.html#enable-threads) (enabled by default since 2.0.27) and [py-call-uwsgi-fork-hooks](https://uwsgi-docs.readthedocs.io/en/latest/Options.html#py-call-uwsgi-fork-hooks).
::::
::::{note}
If you see an error log that mentions `psutil not found`, you can install `psutil` using `pip install psutil`, or add `psutil` to your `requirements.txt` file.
::::
## Setup [flask-setup]
To set up the agent, you need to initialize it with appropriate settings.
The settings are configured either via environment variables, the application’s settings, or as initialization arguments.
You can find a list of all available settings in the [Configuration](/reference/configuration.md) page.
To initialize the agent for your application using environment variables:
```python
from elasticapm.contrib.flask import ElasticAPM
app = Flask(__name__)
apm = ElasticAPM(app)
```
To configure the agent using `ELASTIC_APM` in your application’s settings:
```python
from elasticapm.contrib.flask import ElasticAPM
app.config['ELASTIC_APM'] = {
'SERVICE_NAME': '',
'SECRET_TOKEN': '',
}
apm = ElasticAPM(app)
```
The final option is to initialize the agent with the settings as arguments:
```python
from elasticapm.contrib.flask import ElasticAPM
apm = ElasticAPM(app, service_name='', secret_token='')
```
### Debug mode [flask-debug-mode]
::::{note}
Please note that errors and transactions will only be sent to the APM Server if your app is **not** in [Flask debug mode](https://flask.palletsprojects.com/en/3.0.x/quickstart/#debug-mode).
::::
To force the agent to send data while the app is in debug mode, set the value of `DEBUG` in the `ELASTIC_APM` dictionary to `True`:
```python
app.config['ELASTIC_APM'] = {
'SERVICE_NAME': '',
'SECRET_TOKEN': '',
'DEBUG': True
}
```
### Building applications on the fly? [flask-building-applications-on-the-fly]
You can use the agent’s `init_app` hook for adding the application on the fly:
```python
from elasticapm.contrib.flask import ElasticAPM
apm = ElasticAPM()
def create_app():
app = Flask(__name__)
apm.init_app(app, service_name='', secret_token='')
return app
```
## Usage [flask-usage]
Once you have configured the agent, it will automatically track transactions and capture uncaught exceptions within Flask. If you want to send additional events, a couple of shortcuts are provided on the ElasticAPM Flask middleware object by raising an exception or logging a generic message.
Capture an arbitrary exception by calling `capture_exception`:
```python
try:
1 / 0
except ZeroDivisionError:
apm.capture_exception()
```
Log a generic message with `capture_message`:
```python
apm.capture_message('hello, world!')
```
## Shipping Logs to Elasticsearch [flask-logging]
This feature has been deprecated and will be removed in a future version.
Please see our [Logging](/reference/logs.md) documentation for other supported ways to ship logs to Elasticsearch.
Note that you can always send exceptions and messages to the APM Server with [`capture_exception`](/reference/api-reference.md#client-api-capture-exception) and and [`capture_message`](/reference/api-reference.md#client-api-capture-message).
```python
from elasticapm import get_client
@app.route('/')
def bar():
try:
1 / 0
except ZeroDivisionError:
get_client().capture_exception()
```
### Extra data [flask-extra-data]
In addition to what the agents log by default, you can send extra information:
```python
@app.route('/')
def bar():
try:
1 / 0
except ZeroDivisionError:
app.logger.error('Math is hard',
exc_info=True,
extra={
'good_at_math': False,
}
)
)
```
### Celery tasks [flask-celery-tasks]
The Elastic APM agent will automatically send errors and performance data from your Celery tasks to the APM Server.
## Performance metrics [flask-performance-metrics]
If you’ve followed the instructions above, the agent has already hooked into the right signals and should be reporting performance metrics.
### Ignoring specific routes [flask-ignoring-specific-views]
You can use the [`TRANSACTIONS_IGNORE_PATTERNS`](/reference/configuration.md#config-transactions-ignore-patterns) configuration option to ignore specific routes. The list given should be a list of regular expressions which are matched against the transaction name:
```python
app.config['ELASTIC_APM'] = {
...
'TRANSACTIONS_IGNORE_PATTERNS': ['^OPTIONS ', '/api/']
...
}
```
This would ignore any requests using the `OPTIONS` method and any requests containing `/api/`.
### Integrating with the RUM Agent [flask-integrating-with-the-rum-agent]
To correlate performance measurement in the browser with measurements in your Flask app, you can help the RUM (Real User Monitoring) agent by configuring it with the Trace ID and Span ID of the backend request. We provide a handy template context processor which adds all the necessary bits into the context of your templates.
The context processor is installed automatically when you initialize `ElasticAPM`. All that is left to do is to update the call to initialize the RUM agent (which probably happens in your base template) like this:
```javascript
elasticApm.init({
serviceName: "my-frontend-service",
pageLoadTraceId: "{{ apm["trace_id"] }}",
pageLoadSpanId: "{{ apm["span_id"]() }}",
pageLoadSampled: {{ apm["is_sampled_js"] }}
})
```
See the [JavaScript RUM agent documentation](apm-agent-rum-js://reference/index.md) for more information.
## Supported Flask and Python versions [supported-flask-and-python-versions]
A list of supported [Flask](/reference/supported-technologies.md#supported-flask) and [Python](/reference/supported-technologies.md#supported-python) versions can be found on our [Supported Technologies](/reference/supported-technologies.md) page.
python-elastic-apm-6.26.2/docs/reference/how-agent-works.md 0000664 0000000 0000000 00000006776 15216207663 0023621 0 ustar 00root root 0000000 0000000 ---
mapped_pages:
- https://www.elastic.co/guide/en/apm/agent/python/current/how-the-agent-works.html
applies_to:
stack:
serverless:
observability:
product:
apm_agent_python: ga
---
# How the Agent works [how-the-agent-works]
To gather APM events (called transactions and spans), errors and metrics, the Python agent instruments your application in a few different ways. These events, are then sent to the APM Server. The APM Server converts them to a format suitable for Elasticsearch, and sends them to an Elasticsearch cluster. You can then use the APM app in Kibana to gain insight into latency issues and error culprits within your application.
Broadly, we differentiate between three different approaches to collect the necessary data: framework integration, instrumentation, and background collection.
## Framework integration [how-it-works-framework-integration]
To collect data about incoming requests and background tasks, we integrate with frameworks like [Django](/reference/django-support.md), [Flask](/reference/flask-support.md) and Celery. Whenever possible, framework integrations make use of hooks and signals provided by the framework. Examples of this are:
* `request_started`, `request_finished`, and `got_request_exception` signals from `django.core.signals`
* `request_started`, `request_finished`, and `got_request_exception` signals from `flask.signals`
* `task_prerun`, `task_postrun`, and `task_failure` signals from `celery.signals`
Framework integrations require some limited code changes in your app. E.g. for Django, you need to add `elasticapm.contrib.django` to `INSTALLED_APPS`.
## What if you are not using a framework [how-it-works-no-framework]
If you’re not using a supported framework, for example, a simple Python script, you can still leverage the agent’s [automatic instrumentation](/reference/supported-technologies.md#automatic-instrumentation). Check out our docs on [instrumenting custom code](/reference/instrumenting-custom-code.md).
## Instrumentation [how-it-works-instrumentation]
To collect data from database drivers, HTTP libraries etc., we instrument certain functions and methods in these libraries. Our instrumentation wraps these callables and collects additional data, like
* time spent in the call
* the executed query for database drivers
* the fetched URL for HTTP libraries
We use a 3rd party library, [`wrapt`](https://github.com/GrahamDumpleton/wrapt), to wrap the callables. You can read more on how `wrapt` works in Graham Dumpleton’s excellent series of [blog posts](https://grahamdumpleton.me/posts/?search=wrapt).
Instrumentations are set up automatically and do not require any code changes. See [Automatic Instrumentation](/reference/supported-technologies.md#automatic-instrumentation) to learn more about which libraries we support.
## Background collection [how-it-works-background-collection]
In addition to APM and error data, the Python agent also collects system and application metrics in regular intervals. This collection happens in a background thread that is started by the agent.
In addition to the metrics collection background thread, the agent starts two additional threads per process:
* a thread to regularly fetch remote configuration from the APM Server
* a thread to process the collected data and send it to the APM Server via HTTP.
Note that every process that instantiates the agent will have these three threads. This means that when you e.g. use gunicorn or uwsgi workers, each worker will have three threads started by the Python agent.
python-elastic-apm-6.26.2/docs/reference/images/ 0000775 0000000 0000000 00000000000 15216207663 0021470 5 ustar 00root root 0000000 0000000 python-elastic-apm-6.26.2/docs/reference/images/choose-a-layer.png 0000664 0000000 0000000 00000411123 15216207663 0025010 0 ustar 00root root 0000000 0000000 ‰PNG
IHDR : š ‡�€¬
ßiCCPICC Profile H‰•—PSé€Ï½©„„–)¡7A:¤×
ÒATB ”B@ņÊâ
®,+º*¢`YŠØ¶E±÷Y”u±`CÍ^àv÷Í{oÞ™ùïùæÜóŸòÏýgÎ …rÅâLT K$•Dú°ââX¤ç€uPG py9bïððPÀd\ÿ]ÞßdDß²‰õïïÿ«¨ñ9<