

# Working with Python
<a name="xray-python"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

 There are two ways to instrument your Python application to send traces to X-Ray: 
+ [AWS Distro for OpenTelemetry Python](xray-python-opentel-sdk.md) – An AWS distribution that provides a set of open source libraries for sending correlated metrics and traces to multiple AWS monitoring solutions, including Amazon CloudWatch, AWS X-Ray, and Amazon OpenSearch Service, via the [AWS Distro for OpenTelemetry Collector](https://aws-otel.github.io/docs/getting-started/collector).
+ [AWS X-Ray SDK for Python](xray-sdk-python.md) – A set of libraries for generating and sending traces to X-Ray via the [X-Ray daemon](xray-daemon.md).

 For more information, see [Choosing between the AWS Distro for OpenTelemetry and X-Ray SDKs](xray-instrumenting-your-app.md#xray-instrumenting-choosing). 

# AWS Distro for OpenTelemetry Python
<a name="xray-python-opentel-sdk"></a>

With the AWS Distro for OpenTelemetry (ADOT) Python, you can instrument your applications once and send correlated metrics and traces to multiple AWS monitoring solutions including Amazon CloudWatch, AWS X-Ray, and Amazon OpenSearch Service. Using X-Ray with ADOT requires two components: an *OpenTelemetry SDK* enabled for use with X-Ray, and the *AWS Distro for OpenTelemetry Collector* enabled for use with X-Ray. ADOT Python includes auto-instrumentation support, enabling your application to send traces without code changes.

To get started, see the [AWS Distro for OpenTelemetry Python documentation](https://aws-otel.github.io/docs/getting-started/python-sdk).

For more information about using the AWS Distro for OpenTelemetry with AWS X-Ray and other AWS services, see [AWS Distro for OpenTelemetry](https://aws-otel.github.io/) or the [AWS Distro for OpenTelemetry Documentation](https://aws-otel.github.io/docs/introduction).

For more information about language support and usage, see [AWS Observability on GitHub](https://github.com/aws-observability).

# AWS X-Ray SDK for Python
<a name="xray-sdk-python"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

The X-Ray SDK for Python is a library for Python web applications that provides classes and methods for generating and sending trace data to the X-Ray daemon. Trace data includes information about incoming HTTP requests served by the application, and calls that the application makes to downstream services using the AWS SDK, HTTP clients, or an SQL database connector. You can also create segments manually and add debug information in annotations and metadata.

You can download the SDK with `pip`.

```
$ pip install aws-xray-sdk
```

**Note**  
The X-Ray SDK for Python is an open source project. You can follow the project and submit issues and pull requests on GitHub: [github.com/aws/aws-xray-sdk-python](https://github.com/aws/aws-xray-sdk-python)

If you use Django or Flask, start by [adding the SDK middleware to your application](xray-sdk-python-middleware.md) to trace incoming requests. The middleware creates a [segment](xray-concepts.md#xray-concepts-segments) for each traced request, and completes the segment when the response is sent. While the segment is open, you can use the SDK client's methods to add information to the segment and create subsegments to trace downstream calls. The SDK also automatically records exceptions that your application throws while the segment is open. For other applications, you can [create segments manually](xray-sdk-python-middleware.md#xray-sdk-python-middleware-manual).

For Lambda functions called by an instrumented application or service, Lambda reads the [tracing header](xray-concepts.md#xray-concepts-tracingheader) and traces sampled requests automatically. For other functions, you can [configure Lambda](xray-services-lambda.md) to sample and trace incoming requests. In either case, Lambda creates the segment and provides it to the X-Ray SDK.

**Note**  
On Lambda, the X-Ray SDK is optional. If you don't use it in your function, your service map will still include a node for the Lambda service, and one for each Lambda function. By adding the SDK, you can instrument your function code to add subsegments to the function segment recorded by Lambda. See [AWS Lambda and AWS X-Ray](xray-services-lambda.md) for more information.

See [Worker](scorekeep-lambda.md#scorekeep-lambda-worker) for a example Python function instrumented in Lambda.

Next, use the X-Ray SDK for Python to instrument downstream calls by [patching your application's libraries](xray-sdk-python-patching.md). The SDK supports the following libraries.

**Supported Libraries**
+ `[botocore](https://pypi.python.org/pypi/botocore)`, `[boto3](https://pypi.python.org/pypi/boto3)` – Instrument AWS SDK for Python (Boto) clients.
+ `[pynamodb](https://pypi.python.org/pypi/pynamodb/)` – Instrument PynamoDB's version of the Amazon DynamoDB client.
+ `[aiobotocore](https://pypi.python.org/pypi/aiobotocore)`, `[aioboto3](https://pypi.python.org/pypi/aioboto3)` – Instrument [asyncio](https://docs.python.org/3/library/asyncio.html)-integrated versions of SDK for Python clients.
+ `[requests](https://pypi.python.org/pypi/requests)`, `[aiohttp](https://pypi.python.org/pypi/aiohttp)` – Instrument high-level HTTP clients.
+ `[httplib](https://docs.python.org/2/library/httplib.html)`, [https://docs.python.org/3/library/http.client.html](https://docs.python.org/3/library/http.client.html) – Instrument low-level HTTP clients and the higher level libraries that use them.
+ `[sqlite3](https://docs.python.org/3/library/sqlite3.html)` – Instrument SQLite clients.
+ `[mysql-connector-python](https://pypi.python.org/pypi/mysql-connector-python)` – Instrument MySQL clients.
+ `[pg8000](https://pypi.org/project/pg8000/)` – Instrument Pure-Python PostgreSQL interface.
+ `[psycopg2](https://pypi.org/project/psycopg2/)` – Instrument PostgreSQL database adapter.
+ `[pymongo](https://pypi.org/project/pymongo/)` – Instrument MongoDB clients.
+ `[pymysql](https://pypi.org/project/PyMySQL/)` – Instrument PyMySQL based clients for MySQL and MariaDB.

Whenever your application makes calls to AWS, an SQL database, or other HTTP services, the SDK records information about the call in a subsegment. AWS services and the resources that you access within the services appear as downstream nodes on the trace map to help you identify errors and throttling issues on individual connections.

After you start using the SDK, customize its behavior by [configuring the recorder and middleware](xray-sdk-python-configuration.md). You can add plugins to record data about the compute resources running your application, customize sampling behavior by defining sampling rules, and set the log level to see more or less information from the SDK in your application logs.

Record additional information about requests and the work that your application does in [annotations and metadata](xray-sdk-python-segment.md). Annotations are simple key-value pairs that are indexed for use with [filter expressions](xray-console-filters.md), so that you can search for traces that contain specific data. Metadata entries are less restrictive and can record entire objects and arrays — anything that can be serialized into JSON.

**Annotations and Metadata**  
Annotations and metadata are arbitrary text that you add to segments with the X-Ray SDK. Annotations are indexed for use with filter expressions. Metadata are not indexed, but can be viewed in the raw segment with the X-Ray console or API. Anyone that you grant read access to X-Ray can view this data.

When you have a lot of instrumented clients in your code, a single request segment can contain a large number of subsegments, one for each call made with an instrumented client. You can organize and group subsegments by wrapping client calls in [custom subsegments](xray-sdk-python-subsegments.md). You can create a custom subsegment for an entire function or any section of code. You can then you can record metadata and annotations on the subsegment instead of writing everything on the parent segment.

For reference documentation for the SDK's classes and methods, see the [AWS X-Ray SDK for Python API Reference](https://docs.aws.amazon.com/xray-sdk-for-python/latest/reference).

## Requirements
<a name="xray-sdk-python-requirements"></a>

The X-Ray SDK for Python supports the following language and library versions.
+ **Python** – 2.7, 3.4, and newer
+ **Django** – 1.10 and newer
+ **Flask** – 0.10 and newer
+ **aiohttp** – 2.3.0 and newer
+ **AWS SDK for Python (Boto)** – 1.4.0 and newer
+ **botocore** – 1.5.0 and newer
+ **enum** – 0.4.7 and newer, for Python versions 3.4.0 and older
+ **jsonpickle** – 1.0.0 and newer
+ **setuptools** – 40.6.3 and newer
+ **wrapt** – 1.11.0 and newer

## Dependency management
<a name="xray-sdk-python-dependencies"></a>

The X-Ray SDK for Python is available from `pip`.
+ **Package** – `aws-xray-sdk`

Add the SDK as a dependency in your `requirements.txt` file.

**Example requirements.txt**  

```
aws-xray-sdk==2.4.2
boto3==1.4.4
botocore==1.5.55
Django==1.11.3
```

If you use Elastic Beanstalk to deploy your application, Elastic Beanstalk installs all of the packages in `requirements.txt` automatically.

# Configuring the X-Ray SDK for Python
<a name="xray-sdk-python-configuration"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

The X-Ray SDK for Python has a class named `xray_recorder` that provides the global recorder. You can configure the global recorder to customize the middleware that creates segments for incoming HTTP calls.

**Topics**
+ [Service plugins](#xray-sdk-python-configuration-plugins)
+ [Sampling rules](#xray-sdk-python-configuration-sampling)
+ [Logging](#xray-sdk-python-configuration-logging)
+ [Recorder configuration in code](#xray-sdk-python-middleware-configuration-code)
+ [Recorder configuration with Django](#xray-sdk-python-middleware-configuration-django)
+ [Environment variables](#xray-sdk-python-configuration-envvars)

## Service plugins
<a name="xray-sdk-python-configuration-plugins"></a>

Use `plugins` to record information about the service hosting your application.

**Plugins**
+ Amazon EC2 – `EC2Plugin` adds the instance ID, Availability Zone, and the CloudWatch Logs Group.
+ Elastic Beanstalk – `ElasticBeanstalkPlugin` adds the environment name, version label, and deployment ID.
+ Amazon ECS – `ECSPlugin` adds the container ID.

![\[Segment - Scorekeep overview showing Elastic Beanstalk and EC2 deployment details.\]](http://docs.aws.amazon.com/xray/latest/devguide/images/scorekeep-PUTrules-segment-resources-python09.png)


To use a plugin, call `configure` on the `xray_recorder`.

```
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all

xray_recorder.configure(service='My app')
plugins = ('ElasticBeanstalkPlugin', 'EC2Plugin')
xray_recorder.configure(plugins=plugins)
patch_all()
```

**Note**  
Since `plugins` are passed in as a tuple, be sure to include a trailing `,` when specifying a single plugin. For example, `plugins = ('EC2Plugin',)` 

You can also use [environment variables](#xray-sdk-python-configuration-envvars), which take precedence over values set in code, to configure the recorder.

Configure plugins before [patching libraries](xray-sdk-python-patching.md) to record downstream calls.

The SDK also uses plugin settings to set the `origin` field on the segment. This indicates the type of AWS resource that runs your application. When you use multiple plugins, the SDK uses the following resolution order to determine the origin: ElasticBeanstalk > EKS > ECS > EC2.

## Sampling rules
<a name="xray-sdk-python-configuration-sampling"></a>

The SDK uses the sampling rules you define in the X-Ray console to determine which requests to record. The default rule traces the first request each second, and five percent of any additional requests across all services sending traces to X-Ray. [Create additional rules in the X-Ray console](xray-console-sampling.md) to customize the amount of data recorded for each of your applications.

The SDK applies custom rules in the order in which they are defined. If a request matches multiple custom rules, the SDK applies only the first rule.

**Note**  
If the SDK can't reach X-Ray to get sampling rules, it reverts to a default local rule of the first request each second, and five percent of any additional requests per host. This can occur if the host doesn't have permission to call sampling APIs, or can't connect to the X-Ray daemon, which acts as a TCP proxy for API calls made by the SDK.

You can also configure the SDK to load sampling rules from a JSON document. The SDK can use local rules as a backup for cases where X-Ray sampling is unavailable, or use local rules exclusively.

**Example sampling-rules.json**  

```
{
  "version": 2,
  "rules": [
    {
      "description": "Player moves.",
      "host": "*",
      "http_method": "*",
      "url_path": "/api/move/*",
      "fixed_target": 0,
      "rate": 0.05
    }
  ],
  "default": {
    "fixed_target": 1,
    "rate": 0.1
  }
}
```

This example defines one custom rule and a default rule. The custom rule applies a five-percent sampling rate with no minimum number of requests to trace for paths under `/api/move/`. The default rule traces the first request each second and 10 percent of additional requests.

The disadvantage of defining rules locally is that the fixed target is applied by each instance of the recorder independently, instead of being managed by the X-Ray service. As you deploy more hosts, the fixed rate is multiplied, making it harder to control the amount of data recorded.

On AWS Lambda, you cannot modify the sampling rate. If your function is called by an instrumented service, calls that generated requests that were sampled by that service will be recorded by Lambda. If active tracing is enabled and no tracing header is present, Lambda makes the sampling decision.

To configure backup sampling rules, call `xray_recorder.configure`, as shown in the following example, where *rules* is either a dictionary of rules or the absolute path to a JSON file containing sampling rules.

```
xray_recorder.configure(sampling_rules=rules)
```

To use only local rules, configure the recorder with a `LocalSampler`.

```
from aws_xray_sdk.core.sampling.local.sampler import LocalSampler
xray_recorder.configure(sampler=LocalSampler())
```

You can also configure the global recorder to disable sampling and instrument all incoming requests.

**Example main.py – Disable sampling**  

```
xray_recorder.configure(sampling=False)
```

## Logging
<a name="xray-sdk-python-configuration-logging"></a>

The SDK uses Python’s built-in `logging` module with a default `WARNING` logging level. Get a reference to the logger for the `aws_xray_sdk` class and call `setLevel` on it to configure the different log level for the library and the rest of your application.

**Example app.py – Logging**  

```
logging.basicConfig(level='WARNING')
logging.getLogger('aws_xray_sdk').setLevel(logging.ERROR)
```

Use debug logs to identify issues, such as unclosed subsegments, when you [generate subsegments manually](xray-sdk-python-subsegments.md).

## Recorder configuration in code
<a name="xray-sdk-python-middleware-configuration-code"></a>

Additional settings are available from the `configure` method on `xray_recorder`.
+ `context_missing` – Set to `LOG_ERROR` to avoid throwing exceptions when your instrumented code attempts to record data when no segment is open.
+ `daemon_address` – Set the host and port of the X-Ray daemon listener.
+ `service` – Set a service name that the SDK uses for segments.
+ `plugins` – Record information about your application's AWS resources.
+ `sampling` – Set to `False` to disable sampling.
+ `sampling_rules` – Set the path of the JSON file containing your [sampling rules](#xray-sdk-python-configuration-sampling).

**Example main.py – Disable context missing exceptions**  

```
from aws_xray_sdk.core import xray_recorder

xray_recorder.configure(context_missing='LOG_ERROR')
```

## Recorder configuration with Django
<a name="xray-sdk-python-middleware-configuration-django"></a>

If you use the Django framework, you can use the Django `settings.py` file to configure options on the global recorder.
+ `AUTO_INSTRUMENT` (Django only) – Record subsegments for built-in database and template rendering operations.
+ `AWS_XRAY_CONTEXT_MISSING` – Set to `LOG_ERROR` to avoid throwing exceptions when your instrumented code attempts to record data when no segment is open.
+ `AWS_XRAY_DAEMON_ADDRESS` – Set the host and port of the X-Ray daemon listener.
+ `AWS_XRAY_TRACING_NAME` – Set a service name that the SDK uses for segments.
+ `PLUGINS` – Record information about your application's AWS resources.
+ `SAMPLING` – Set to `False` to disable sampling.
+ `SAMPLING_RULES` – Set the path of the JSON file containing your [sampling rules](#xray-sdk-python-configuration-sampling).

To enable recorder configuration in `settings.py`, add the Django middleware to the list of installed apps.

**Example settings.py – Installed apps**  

```
INSTALLED_APPS = [
    ...
    'django.contrib.sessions',
    'aws_xray_sdk.ext.django',
]
```

Configure the available settings in a dict named `XRAY_RECORDER`.

**Example settings.py – Installed apps**  

```
XRAY_RECORDER = {
    'AUTO_INSTRUMENT': True,
    'AWS_XRAY_CONTEXT_MISSING': 'LOG_ERROR',
    'AWS_XRAY_DAEMON_ADDRESS': '127.0.0.1:5000',
    'AWS_XRAY_TRACING_NAME': 'My application',
    'PLUGINS': ('ElasticBeanstalkPlugin', 'EC2Plugin', 'ECSPlugin'),
    'SAMPLING': False,
}
```

## Environment variables
<a name="xray-sdk-python-configuration-envvars"></a>

You can use environment variables to configure the X-Ray SDK for Python. The SDK supports the following variables: 
+ `AWS_XRAY_TRACING_NAME` – Set a service name that the SDK uses for segments. Overrides the service name that you set programmatically.
+ `AWS_XRAY_SDK_ENABLED` – When set to `false`, disables the SDK. By default, the SDK is enabled unless the environment variable is set to false. 
  + When disabled, the global recorder automatically generates dummy segments and subsegments that are not sent to the daemon, and automatic patching is disabled. Middlewares are written as a wrapper over the global recorder. All segment and subsegment generation through the middleware also become dummy segment and dummy subsegments.
  + Set the value of `AWS_XRAY_SDK_ENABLED` through the environment variable or through direct interaction with the `global_sdk_config` object from the `aws_xray_sdk` library. Settings to the environment variable override these interactions.
+ `AWS_XRAY_DAEMON_ADDRESS` – Set the host and port of the X-Ray daemon listener. By default, the SDK uses `127.0.0.1:2000` for both trace data (UDP) and sampling (TCP). Use this variable if you have configured the daemon to [listen on a different port](xray-daemon-configuration.md) or if it is running on a different host.

**Format**
  + **Same port** – `address:port`
  + **Different ports** – `tcp:address:port udp:address:port`
+ `AWS_XRAY_CONTEXT_MISSING` – Set to `RUNTIME_ERROR` to throw exceptions when your instrumented code attempts to record data when no segment is open.

**Valid Values**
  + `RUNTIME_ERROR` – Throw a runtime exception.
  + `LOG_ERROR` – Log an error and continue (default).
  + `IGNORE_ERROR` – Ignore error and continue.

  Errors related to missing segments or subsegments can occur when you attempt to use an instrumented client in startup code that runs when no request is open, or in code that spawns a new thread.

Environment variables override values set in code.

# Tracing incoming requests with the X-Ray SDK for Python middleware
<a name="xray-sdk-python-middleware"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

When you add the middleware to your application and configure a segment name, the X-Ray SDK for Python creates a segment for each sampled request. This segment includes timing, method, and disposition of the HTTP request. Additional instrumentation creates subsegments on this segment.

The X-Ray SDK for Python supports the following middleware to instrument incoming HTTP requests: 
+ Django
+ Flask
+ Bottle

**Note**  
For AWS Lambda functions, Lambda creates a segment for each sampled request. See [AWS Lambda and AWS X-Ray](xray-services-lambda.md) for more information.

See [Worker](scorekeep-lambda.md#scorekeep-lambda-worker) for a example Python function instrumented in Lambda.

For scripts or Python applications on other frameworks, you can [create segments manually](#xray-sdk-python-middleware-manual).

Each segment has a name that identifies your application in the service map. The segment can be named statically, or you can configure the SDK to name it dynamically based on the host header in the incoming request. Dynamic naming lets you group traces based on the domain name in the request, and apply a default name if the name doesn't match an expected pattern (for example, if the host header is forged).

**Forwarded Requests**  
If a load balancer or other intermediary forwards a request to your application, X-Ray takes the client IP from the `X-Forwarded-For` header in the request instead of from the source IP in the IP packet. The client IP that is recorded for a forwarded request can be forged, so it should not be trusted.

When a request is forwarded, the SDK sets an additional field in the segment to indicate this. If the segment contains the field `x_forwarded_for` set to `true`, the client IP was taken from the `X-Forwarded-For` header in the HTTP request.

The middleware creates a segment for each incoming request with an `http` block that contains the following information:
+ **HTTP method** – GET, POST, PUT, DELETE, etc.
+ **Client address** – The IP address of the client that sent the request.
+ **Response code** – The HTTP response code for the completed request.
+ **Timing** – The start time (when the request was received) and end time (when the response was sent).
+ **User agent** — The `user-agent` from the request.
+ **Content length** — The `content-length` from the response.

**Topics**
+ [Adding the middleware to your application (Django)](#xray-sdk-python-adding-middleware-django)
+ [Adding the middleware to your application (flask)](#xray-sdk-python-adding-middleware-flask)
+ [Adding the middleware to your application (Bottle)](#xray-sdk-python-adding-middleware-bottle)
+ [Instrumenting Python code manually](#xray-sdk-python-middleware-manual)
+ [Configuring a segment naming strategy](#xray-sdk-python-middleware-naming)

## Adding the middleware to your application (Django)
<a name="xray-sdk-python-adding-middleware-django"></a>

Add the middleware to the `MIDDLEWARE` list in your `settings.py` file. The X-Ray middleware should be the first line in your `settings.py` file to ensure that requests that fail in other middleware are recorded.

**Example settings.py - X-Ray SDK for Python middleware**  

```
MIDDLEWARE = [
    'aws_xray_sdk.ext.django.middleware.XRayMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware'
]
```

Add the X-Ray SDK Django app to the `INSTALLED_APPS` list in your `settings.py` file. This will allow the X-Ray recorder to be configured during your app's startup.

**Example settings.py - X-Ray SDK for Python Django app**  

```
INSTALLED_APPS = [
    'aws_xray_sdk.ext.django',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
```

Configure a segment name in your [`settings.py` file](xray-sdk-python-configuration.md#xray-sdk-python-middleware-configuration-django).

**Example settings.py – Segment name**  

```
XRAY_RECORDER = {
    'AWS_XRAY_TRACING_NAME': 'My application',
    'PLUGINS': ('EC2Plugin',),
}
```

This tells the X-Ray recorder to trace requests served by your Django application with the default sampling rate. You can [configure the recorder your Django settings file](xray-sdk-python-configuration.md#xray-sdk-python-middleware-configuration-django) to apply custom sampling rules or change other settings.

**Note**  
Since `plugins` are passed in as a tuple, be sure to include a trailing `,` when specifying a single plugin. For example, `plugins = ('EC2Plugin',)` 

## Adding the middleware to your application (flask)
<a name="xray-sdk-python-adding-middleware-flask"></a>

To instrument your Flask application, first configure a segment name on the `xray_recorder`. Then, use the `XRayMiddleware` function to patch your Flask application in code.

**Example app.py**  

```
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.ext.flask.middleware import XRayMiddleware

app = Flask(__name__)

xray_recorder.configure(service='My application')
XRayMiddleware(app, xray_recorder)
```

This tells the X-Ray recorder to trace requests served by your Flask application with the default sampling rate. You can [configure the recorder in code](xray-sdk-python-configuration.md#xray-sdk-python-middleware-configuration-code) to apply custom sampling rules or change other settings.

## Adding the middleware to your application (Bottle)
<a name="xray-sdk-python-adding-middleware-bottle"></a>

To instrument your Bottle application, first configure a segment name on the `xray_recorder`. Then, use the `XRayMiddleware` function to patch your Bottle application in code.

**Example app.py**  

```
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.ext.bottle.middleware import XRayMiddleware
 
app = Bottle()
 
xray_recorder.configure(service='fallback_name', dynamic_naming='My application')
app.install(XRayMiddleware(xray_recorder))
```

This tells the X-Ray recorder to trace requests served by your Bottle application with the default sampling rate. You can [configure the recorder in code](xray-sdk-python-configuration.md#xray-sdk-python-middleware-configuration-code) to apply custom sampling rules or change other settings.

## Instrumenting Python code manually
<a name="xray-sdk-python-middleware-manual"></a>

If you don't use Django or Flask, you can create segments manually. You can create a segment for each incoming request, or create segments around patched HTTP or AWS SDK clients to provide context for the recorder to add subsegments.

**Example main.py – Manual instrumentation**  

```
from aws_xray_sdk.core import xray_recorder

# Start a segment
segment = xray_recorder.begin_segment('segment_name')
# Start a subsegment
subsegment = xray_recorder.begin_subsegment('subsegment_name')

# Add metadata and annotations
segment.put_metadata('key', dict, 'namespace')
subsegment.put_annotation('key', 'value')

# Close the subsegment and segment
xray_recorder.end_subsegment()
xray_recorder.end_segment()
```

## Configuring a segment naming strategy
<a name="xray-sdk-python-middleware-naming"></a>

AWS X-Ray uses a *service name* to identify your application and distinguish it from the other applications, databases, external APIs, and AWS resources that your application uses. When the X-Ray SDK generates segments for incoming requests, it records your application's service name in the segment's [name field](xray-api-segmentdocuments.md#api-segmentdocuments-fields).

The X-Ray SDK can name segments after the hostname in the HTTP request header. However, this header can be forged, which could result in unexpected nodes in your service map. To prevent the SDK from naming segments incorrectly due to requests with forged host headers, you must specify a default name for incoming requests.

If your application serves requests for multiple domains, you can configure the SDK to use a dynamic naming strategy to reflect this in segment names. A dynamic naming strategy allows the SDK to use the hostname for requests that match an expected pattern, and apply the default name to requests that don't.

For example, you might have a single application serving requests to three subdomains– `www.example.com`, `api.example.com`, and `static.example.com`. You can use a dynamic naming strategy with the pattern `*.example.com` to identify segments for each subdomain with a different name, resulting in three service nodes on the service map. If your application receives requests with a hostname that doesn't match the pattern, you will see a fourth node on the service map with a fallback name that you specify.

To use the same name for all request segments, specify the name of your application when you configure the recorder, as shown in the [previous sections](#xray-sdk-python-adding-middleware-django).

A dynamic naming strategy defines a pattern that hostnames should match, and a default name to use if the hostname in the HTTP request doesn't match the pattern. To name segments dynamically in Django, add the `DYNAMIC_NAMING` setting to your [settings.py](xray-sdk-python-configuration.md#xray-sdk-python-middleware-configuration-django) file.

**Example settings.py – Dynamic naming**  

```
XRAY_RECORDER = {
    'AUTO_INSTRUMENT': True,
    'AWS_XRAY_TRACING_NAME': 'My application',
    'DYNAMIC_NAMING': '*.example.com',
    'PLUGINS': ('ElasticBeanstalkPlugin', 'EC2Plugin')
}
```

You can use '\$1' in the pattern to match any string, or '?' to match any single character. For Flask, [configure the recorder in code](xray-sdk-python-configuration.md#xray-sdk-python-middleware-configuration-code).

**Example main.py – Segment name**  

```
from aws_xray_sdk.core import xray_recorder
xray_recorder.configure(service='My application')
xray_recorder.configure(dynamic_naming='*.example.com')
```

**Note**  
You can override the default service name that you define in code with the `AWS_XRAY_TRACING_NAME` [environment variable](xray-sdk-python-configuration.md#xray-sdk-python-configuration-envvars).

# Patching libraries to instrument downstream calls
<a name="xray-sdk-python-patching"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

To instrument downstream calls, use the X-Ray SDK for Python to patch the libraries that your application uses. The X-Ray SDK for Python can patch the following libraries.

**Supported Libraries**
+ `[botocore](https://pypi.python.org/pypi/botocore)`, `[boto3](https://pypi.python.org/pypi/boto3)` – Instrument AWS SDK for Python (Boto) clients.
+ `[pynamodb](https://pypi.python.org/pypi/pynamodb/)` – Instrument PynamoDB's version of the Amazon DynamoDB client.
+ `[aiobotocore](https://pypi.python.org/pypi/aiobotocore)`, `[aioboto3](https://pypi.python.org/pypi/aioboto3)` – Instrument [asyncio](https://docs.python.org/3/library/asyncio.html)-integrated versions of SDK for Python clients.
+ `[requests](https://pypi.python.org/pypi/requests)`, `[aiohttp](https://pypi.python.org/pypi/aiohttp)` – Instrument high-level HTTP clients.
+ `[httplib](https://docs.python.org/2/library/httplib.html)`, [https://docs.python.org/3/library/http.client.html](https://docs.python.org/3/library/http.client.html) – Instrument low-level HTTP clients and the higher level libraries that use them.
+ `[sqlite3](https://docs.python.org/3/library/sqlite3.html)` – Instrument SQLite clients.
+ `[mysql-connector-python](https://pypi.python.org/pypi/mysql-connector-python)` – Instrument MySQL clients.
+ `[pg8000](https://pypi.org/project/pg8000/)` – Instrument Pure-Python PostgreSQL interface.
+ `[psycopg2](https://pypi.org/project/psycopg2/)` – Instrument PostgreSQL database adapter.
+ `[pymongo](https://pypi.org/project/pymongo/)` – Instrument MongoDB clients.
+ `[pymysql](https://pypi.org/project/PyMySQL/)` – Instrument PyMySQL based clients for MySQL and MariaDB.

When you use a patched library, the X-Ray SDK for Python creates a subsegment for the call and records information from the request and response. A segment must be available for the SDK to create the subsegment, either from the SDK middleware or from AWS Lambda.

**Note**  
If you use SQLAlchemy ORM, you can instrument your SQL queries by importing the SDK's version of SQLAlchemy's session and query classes. See [Use SQLAlchemy ORM](https://github.com/aws/aws-xray-sdk-python/blob/master/README.md#use-sqlalchemy-orm) for instructions.

To patch all available libraries, use the `patch_all` function in `aws_xray_sdk.core`. Some libraries, such as `httplib` and `urllib`, may need to enable double patching by calling `patch_all(double_patch=True)`.

**Example main.py – Patch all supported libraries**  

```
import boto3
import botocore
import requests
import sqlite3

from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all

patch_all()
```

To patch a single library, call `patch` with a tuple of the library name. In order to achieve this, you will need to provide a single element list.

**Example main.py – Patch specific libraries**  

```
import boto3
import botocore
import requests
import mysql-connector-python

from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch

libraries = (['botocore'])
patch(libraries)
```

**Note**  
In some cases, the key that you use to patch a library does not match the library name. Some keys serve as aliases for one or more libraries.  
`httplib` – `[httplib](https://docs.python.org/2/library/httplib.html)` and [https://docs.python.org/3/library/http.client.html](https://docs.python.org/3/library/http.client.html)
`mysql` – `[mysql-connector-python](https://pypi.python.org/pypi/mysql-connector-python)`

## Tracing context for asynchronous work
<a name="xray-sdk-python-patching-async"></a>

For `asyncio` integrated libraries, or to [create subsegments for asynchronous functions](xray-sdk-python-subsegments.md), you must also configure the X-Ray SDK for Python with an async context. Import the `AsyncContext` class and pass an instance of it to the X-Ray recorder.

**Note**  
Web framework support libraries, such as AIOHTTP, are not handled through the `aws_xray_sdk.core.patcher` module. They will not appear in the `patcher` catalog of supported libraries.

**Example main.py – Patch aioboto3**  

```
import asyncio
import aioboto3
import requests

from aws_xray_sdk.core.async_context import AsyncContext
from aws_xray_sdk.core import xray_recorder
xray_recorder.configure(service='my_service', context=AsyncContext())
from aws_xray_sdk.core import patch

libraries = (['aioboto3'])
patch(libraries)
```

# Tracing AWS SDK calls with the X-Ray SDK for Python
<a name="xray-sdk-python-awssdkclients"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

When your application makes calls to AWS services to store data, write to a queue, or send notifications, the X-Ray SDK for Python tracks the calls downstream in [subsegments](xray-sdk-python-subsegments.md). Traced AWS services and resources that you access within those services (for example, an Amazon S3 bucket or Amazon SQS queue), appear as downstream nodes on the trace map in the X-Ray console.

The X-Ray SDK for Python automatically instruments all AWS SDK clients when you [patch the `botocore` library](xray-sdk-python-patching.md). You cannot instrument individual clients.

For all services, you can see the name of the API called in the X-Ray console. For a subset of services, the X-Ray SDK adds information to the segment to provide more granularity in the service map.

For example, when you make a call with an instrumented DynamoDB client, the SDK adds the table name to the segment for calls that target a table. In the console, each table appears as a separate node in the service map, with a generic DynamoDB node for calls that don't target a table.

**Example Subsegment for a call to DynamoDB to save an item**  

```
{
  "id": "24756640c0d0978a",
  "start_time": 1.480305974194E9,
  "end_time": 1.4803059742E9,
  "name": "DynamoDB",
  "namespace": "aws",
  "http": {
    "response": {
      "content_length": 60,
      "status": 200
    }
  },
  "aws": {
    "table_name": "scorekeep-user",
    "operation": "UpdateItem",
    "request_id": "UBQNSO5AEM8T4FDA4RQDEB94OVTDRVV4K4HIRGVJF66Q9ASUAAJG",
  }
}
```

When you access named resources, calls to the following services create additional nodes in the service map. Calls that don't target specific resources create a generic node for the service.
+ **Amazon DynamoDB** – Table name
+ **Amazon Simple Storage Service** – Bucket and key name
+ **Amazon Simple Queue Service** – Queue name

# Tracing calls to downstream HTTP web services using the X-Ray SDK for Python
<a name="xray-sdk-python-httpclients"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

When your application makes calls to microservices or public HTTP APIs, you can use the X-Ray SDK for Python to instrument those calls and add the API to the service graph as a downstream service.

To instrument HTTP clients, [patch the library](xray-sdk-python-patching.md) that you use to make outgoing calls. If you use `requests` or Python's built in HTTP client, that's all you need to do. For `aiohttp`, also configure the recorder with an [async context](xray-sdk-python-patching.md#xray-sdk-python-patching-async).

If you use `aiohttp` 3's client API, you also need to configure the `ClientSession`'s with an instance of the tracing configuration provided by the SDK.

**Example [`aiohttp` 3 client API](https://github.com/aws/aws-xray-sdk-python#trace-aiohttp-client-requests)**  

```
from aws_xray_sdk.ext.aiohttp.client import aws_xray_trace_config

async def foo():
    trace_config = aws_xray_trace_config()
    async with ClientSession(loop=loop, trace_configs=[trace_config]) as session:
        async with session.get(url) as resp
            await resp.read()
```

When you instrument a call to a downstream web API, the X-Ray SDK for Python records a subsegment that contains information about the HTTP request and response. X-Ray uses the subsegment to generate an inferred segment for the remote API.

**Example Subsegment for a downstream HTTP call**  

```
{
  "id": "004f72be19cddc2a",
  "start_time": 1484786387.131,
  "end_time": 1484786387.501,
  "name": "names.example.com",
  "namespace": "remote",
  "http": {
    "request": {
      "method": "GET",
      "url": "https://names.example.com/"
    },
    "response": {
      "content_length": -1,
      "status": 200
    }
  }
}
```

**Example Inferred segment for a downstream HTTP call**  

```
{
  "id": "168416dc2ea97781",
  "name": "names.example.com",
  "trace_id": "1-62be1272-1b71c4274f39f122afa64eab",
  "start_time": 1484786387.131,
  "end_time": 1484786387.501,
  "parent_id": "004f72be19cddc2a",
  "http": {
    "request": {
      "method": "GET",
      "url": "https://names.example.com/"
    },
    "response": {
      "content_length": -1,
      "status": 200
    }
  },
  "inferred": true
}
```

# Generating custom subsegments with the X-Ray SDK for Python
<a name="xray-sdk-python-subsegments"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

Subsegments extend a trace's [segment](xray-concepts.md#xray-concepts-segments) with details about work done in order to serve a request. Each time you make a call with an instrumented client, the X-Ray SDK records the information generated in a subsegment. You can create additional subsegments to group other subsegments, to measure the performance of a section of code, or to record annotations and metadata.

To manage subsegments, use the `begin_subsegment` and `end_subsegment` methods.

**Example main.py – Custom subsegment**  

```
from aws_xray_sdk.core import xray_recorder

subsegment = xray_recorder.begin_subsegment('annotations')
subsegment.put_annotation('id', 12345)
xray_recorder.end_subsegment()
```

To create a subsegment for a synchronous function, use the `@xray_recorder.capture` decorator. You can pass a name for the subsegment to the capture function or leave it out to use the function name.

**Example main.py – Function subsegment**  

```
from aws_xray_sdk.core import xray_recorder

@xray_recorder.capture('## create_user')
def create_user():
...
```

For an asynchronous function, use the `@xray_recorder.capture_async` decorator, and pass an async context to the recorder.

**Example main.py – Asynchronous function subsegment**  

```
from aws_xray_sdk.core.async_context import AsyncContext
from aws_xray_sdk.core import xray_recorder
xray_recorder.configure(service='my_service', context=AsyncContext())

@xray_recorder.capture_async('## create_user')
async def create_user():
    ...

async def main():
    await myfunc()
```

When you create a subsegment within a segment or another subsegment, the X-Ray SDK for Python generates an ID for it and records the start time and end time.

**Example Subsegment with metadata**  

```
"subsegments": [{
  "id": "6f1605cd8a07cb70",
  "start_time": 1.480305974194E9,
  "end_time": 1.4803059742E9,
  "name": "Custom subsegment for UserModel.saveUser function",
  "metadata": {
    "debug": {
      "test": "Metadata string from UserModel.saveUser"
    }
  },
```

# Add annotations and metadata to segments with the X-Ray SDK for Python
<a name="xray-sdk-python-segment"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

You can record additional information about requests, the environment, or your application with annotations and metadata. You can add annotations and metadata to the segments that the X-Ray SDK creates, or to custom subsegments that you create.

**Annotations** are key-value pairs with string, number, or Boolean values. Annotations are indexed for use with [filter expressions](xray-console-filters.md). Use annotations to record data that you want to use to group traces in the console, or when calling the [https://docs.aws.amazon.com/xray/latest/api/API_GetTraceSummaries.html](https://docs.aws.amazon.com/xray/latest/api/API_GetTraceSummaries.html) API.

**Metadata** are key-value pairs that can have values of any type, including objects and lists, but are not indexed for use with filter expressions. Use metadata to record additional data that you want stored in the trace but don't need to use with search.

In addition to annotations and metadata, you can also [record user ID strings](#xray-sdk-python-segment-userid) on segments. User IDs are recorded in a separate field on segments and are indexed for use with search.

**Topics**
+ [Recording annotations with the X-Ray SDK for Python](#xray-sdk-python-segment-annotations)
+ [Recording metadata with the X-Ray SDK for Python](#xray-sdk-python-segment-metadata)
+ [Recording user IDs with the X-Ray SDK for Python](#xray-sdk-python-segment-userid)

## Recording annotations with the X-Ray SDK for Python
<a name="xray-sdk-python-segment-annotations"></a>

Use annotations to record information on segments or subsegments that you want indexed for search.

**Annotation Requirements**
+ **Keys** – The key for an X-Ray annotation can have up to 500 alphanumeric characters. You cannot use spaces or symbols other than a dot or period ( . )
+ **Values** – The value for an X-Ray annotation can have up to 1,000 Unicode characters.
+ The number of **Annotations** – You can use up to 50 annotations per trace.

**To record annotations**

1. Get a reference to the current segment or subsegment from `xray_recorder`.

   ```
   from aws_xray_sdk.core import xray_recorder
   ...
   document = xray_recorder.current_segment()
   ```

   or

   ```
   from aws_xray_sdk.core import xray_recorder
   ...
   document = xray_recorder.current_subsegment()
   ```

1. Call `put_annotation` with a String key, and a Boolean, Number, or String value.

   ```
   document.put_annotation("mykey", "my value");
   ```

   The following example shows how to call `putAnnotation` with a String key that includes a dot, and a Boolean, Number, or String value.

   ```
   document.putAnnotation("testkey.test", "my value");
   ```

Alternatively, you can use the `put_annotation` method on the `xray_recorder`. This method records annotations on the current subsegment or, if no subsegment is open, on the segment.

```
xray_recorder.put_annotation("mykey", "my value");
```

The SDK records annotations as key-value pairs in an `annotations` object in the segment document. Calling `put_annotation` twice with the same key overwrites previously recorded values on the same segment or subsegment.

To find traces that have annotations with specific values, use the `annotation[key]` keyword in a [filter expression](xray-console-filters.md).

## Recording metadata with the X-Ray SDK for Python
<a name="xray-sdk-python-segment-metadata"></a>

**Warning**  
Don't add objects with circular references as metadata values in the X-Ray SDK for Python. These objects can't be serialized into JSON and may create infinite loops in the SDK. Also, avoid adding large, complex objects as metadata to prevent performance issues.

Use metadata to record information on segments or subsegments that you don't need indexed for search. Metadata values can be strings, numbers, Booleans, or any object that can be serialized into a JSON object or array.

**To record metadata**

1. Get a reference to the current segment or subsegment from `xray_recorder`.

   ```
   from aws_xray_sdk.core import xray_recorder
   ...
   document = xray_recorder.current_segment()
   ```

   or

   ```
   from aws_xray_sdk.core import xray_recorder
   ...
   document = xray_recorder.current_subsegment()
   ```

1. Call `put_metadata` with a String key; a Boolean, Number, String, or Object value; and a String namespace.

   ```
   document.put_metadata("my key", "my value", "my namespace");
   ```

   or

   Call `put_metadata` with just a key and value.

   ```
   document.put_metadata("my key", "my value");
   ```

Alternatively, you can use the `put_metadata` method on the `xray_recorder`. This method records metadata on the current subsegment or, if no subsegment is open, on the segment.

```
xray_recorder.put_metadata("my key", "my value");
```

If you don't specify a namespace, the SDK uses `default`. Calling `put_metadata` twice with the same key overwrites previously recorded values on the same segment or subsegment.

## Recording user IDs with the X-Ray SDK for Python
<a name="xray-sdk-python-segment-userid"></a>

Record user IDs on request segments to identify the user who sent the request.

**To record user IDs**

1. Get a reference to the current segment from `xray_recorder`.

   ```
   from aws_xray_sdk.core import xray_recorder
   ...
   document = xray_recorder.current_segment()
   ```

1. Call `setUser` with a String ID of the user who sent the request.

   ```
   document.set_user("U12345");
   ```

You can call `set_user` in your controllers to record the user ID as soon as your application starts processing a request.

To find traces for a user ID, use the `user` keyword in a [filter expression](xray-console-filters.md).

# Instrumenting web frameworks deployed to serverless environments
<a name="xray-sdk-python-serverless"></a>

**Note**  
X-Ray SDK/Daemon Maintenance Notice – On February 25th, 2026, the AWS X-Ray SDKs/Daemon will enter maintenance mode, where AWS will limit X-Ray SDK and Daemon releases to address security issues only. For more information on the support timeline, see [X-Ray SDK and Daemon Support timeline](xray-sdk-daemon-timeline.md). We recommend to migrate to OpenTelemetry. For more information on migrating to OpenTelemetry, see [Migrating from X-Ray instrumentation to OpenTelemetry instrumentation ](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-migration.html).

The AWS X-Ray SDK for Python supports instrumenting web frameworks deployed in serverless applications. Serverless is the native architecture of the cloud that enables you to shift more of your operational responsibilities to AWS, increasing your agility and innovation.

Serverless architecture is a software application model that enables you to build and run applications and services without thinking about servers. It eliminates infrastructure management tasks such as server or cluster provisioning, patching, operating system maintenance, and capacity provisioning. You can build serverless solutions for nearly any type of application or backend service, and everything required to run and scale your application with high availability is handled for you.

This tutorial shows you how to automatically instrument AWS X-Ray on a web framework, such as Flask or Django, that is deployed to a serverless environment. X-Ray instrumentation of the application enables you to view all downstream calls that are made, starting from Amazon API Gateway through your AWS Lambda function, and the outgoing calls your application makes. 

The X-Ray SDK for Python supports the following Python application frameworks:
+ Flask version 0.8, or later
+ Django version 1.0, or later

This tutorial develops an example serverless application that is deployed to Lambda and invoked by API Gateway. This tutorial uses Zappa to automatically deploy the application to Lambda and to configure the API Gateway endpoint.

## Prerequisites
<a name="xray-sdk-python-serverless-prereqs"></a>
+ [Zappa](https://github.com/Miserlou/Zappa)
+ [Python](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-python.html) – Version 2.7 or 3.6.
+ [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) – Verify that your AWS CLI is configured with the account and AWS Region in which you will deploy your application. 
+ [Pip](https://pypi.org/project/pip/)
+ [Virtualenv](https://virtualenv.pypa.io/en/latest/)

## Step 1: Create an environment
<a name="xray-sdk-python-serverless-environment"></a>

In this step, you create a virtual environment using `virtualenv` to host an application.

1. Using the AWS CLI, create a directory for the application. Then change to the new directory. 

   ```
   mkdir serverless_application
   cd serverless_application
   ```

1. Next, create a virtual environment within your new directory. Use the following command to activate it. 

   ```
   # Create our virtual environment
   virtualenv serverless_env
   
   # Activate it
   source serverless_env/bin/activate
   ```

1. Install X-Ray, Flask, Zappa, and the Requests library to your environment.

   ```
   # Install X-Ray, Flask, Zappa, and Requests into your environment
   pip install aws-xray-sdk flask zappa requests
   ```

1. Add application code to the `serverless_application` directory. For this example, we can build off of Flasks's [Hello World](https://flask.palletsprojects.com/en/3.0.x/quickstart/) example. 

   In the `serverless_application` directory, create a file named `my_app.py`. Then use a text editor to add the following commands. This application instruments the Requests library, patches the Flask application's middleware, and opens the endpoint `'/'`.

   ```
   # Import the X-Ray modules
   from aws_xray_sdk.ext.flask.middleware import XRayMiddleware
   from aws_xray_sdk.core import patcher, xray_recorder
   from flask import Flask
   import requests
   
   # Patch the requests module to enable automatic instrumentation
   patcher.patch(('requests',))
   
   app = Flask(__name__)
   
   # Configure the X-Ray recorder to generate segments with our service name
   xray_recorder.configure(service='My First Serverless App')
   
   # Instrument the Flask application
   XRayMiddleware(app, xray_recorder)
    
   @app.route('/')
   def hello_world():
       resp = requests.get("https://aws.amazon.com")
       return 'Hello, World: %s' % resp.url
   ```

## Step 2: Create and deploy a zappa environment
<a name="xray-sdk-python-serverless-zappa"></a>

In this step you will use Zappa to automatically configure an API Gateway endpoint and then deploy to Lambda.

1. Initialize Zappa from within the `serverless_application` directory. For this example, we used the default settings, but if you have customization preferences, Zappa displays configuration instructions.

   ```
   zappa init
   ```

   ```
   What do you want to call this environment (default 'dev'): dev
   ...
   What do you want to call your bucket? (default 'zappa-*******'): zappa-*******
   ...
   ...
   It looks like this is a Flask application.
   What's the modular path to your app's function?
   This will likely be something like 'your_module.app'.
   We discovered: my_app.app
   Where is your app's function? (default 'my_app.app'): my_app.app
   ...
   Would you like to deploy this application globally? (default 'n') [y/n/(p)rimary]: n
   ```

1. Enable X-Ray. Open the `zappa_settings.json` file and verify that it looks similar to the example.

   ```
   {
       "dev": {
           "app_function": "my_app.app",
           "aws_region": "us-west-2",
           "profile_name": "default",
           "project_name": "serverless-exam",
           "runtime": "python2.7",
           "s3_bucket": "zappa-*********"
       }
   }
   ```

1. Add `"xray_tracing": true` as an entry to the configuration file.

   ```
   {
       "dev": {
           "app_function": "my_app.app",
           "aws_region": "us-west-2",
           "profile_name": "default",
           "project_name": "serverless-exam",
           "runtime": "python2.7",
           "s3_bucket": "zappa-*********",
           "xray_tracing": true
       }
   }
   ```

1. Deploy the application. This automatically configures the API Gateway endpoint and uploads your code to Lambda.

   ```
   zappa deploy
   ```

   ```
   ...
   Deploying API Gateway..
   Deployment complete!: https://**********.execute-api.us-west-2.amazonaws.com/dev
   ```

## Step 3: Enable X-Ray tracing for API Gateway
<a name="xray-sdk-python-serverless-xray"></a>

In this step you will interact with the API Gateway console to enable X-Ray tracing.

1. Sign in to the AWS Management Console and open the API Gateway console at [https://console.aws.amazon.com/apigateway/](https://console.aws.amazon.com/apigateway/). 

1. Find your newly generated API. It should look something like `serverless-exam-dev`.

1. Choose **Stages**.

1. Choose the name of your deployment stage. The default is `dev`.

1. On the **Logs/Tracing** tab, select the **Enable X-Ray Tracing** box.

1. Choose **Save Changes**.

1. Access the endpoint in your browser. If you used the example `Hello World` application, it should display the following.

   ```
   "Hello, World: https://aws.amazon.com/"
   ```

## Step 4: View the created trace
<a name="xray-sdk-python-serverless-trace"></a>

In this step you will interact with the X-Ray console to view the trace created by the example application. For a more detailed walkthrough on trace analysis, see [Viewing the Service Map](https://docs.aws.amazon.com/xray/latest/devguide/xray-console.html#xray-console-servicemap).

1. Sign in to the AWS Management Console and open the X-Ray console at [https://console.aws.amazon.com/xray/home](https://console.aws.amazon.com/xray/home).

1. View segments generated by API Gateway, the Lambda function, and the Lambda container.

1. Under the Lambda function segment, view a subsegment named `My First Serverless App`. It's followed by a second subsegment named `https://aws.amazon.com`.

1. During initialization, Lambda might also generate a third subsegment named `initialization`.

![\[Trace segment view.\]](http://docs.aws.amazon.com/xray/latest/devguide/images/serverless-traceView.png)


![\[Service graph view.\]](http://docs.aws.amazon.com/xray/latest/devguide/images/serverless-serviceView.png)


## Step 5: Clean up
<a name="xray-sdk-python-serverless-cleanup"></a>

Always terminate resources you are no longer using to avoid the accumulation of unexpected costs. As this tutorial demonstrates, tools such as Zappa streamline serverless redeployment.

To remove your application from Lambda, API Gateway, and Amazon S3, run the following command in your project directory by using the AWS CLI. 

```
zappa undeploy dev
```

## Next steps
<a name="xray-sdk-python-serverless-next"></a>

Add more features to your application by adding AWS clients and instrumenting them with X-Ray. Learn more about serverless computing options at [Serverless on AWS](https://aws.amazon.com/serverless).