Introducing AWS X-Ray support for Python web frameworks used in Serverless applications

This is a guest post by Chan Chiem Jeffery Saeteurn. Jeffery is a Software Development Engineer on the AWS X-Ray SDK Team. He has fond interests in IoT, distributed systems, and crafting software to automate everyday tasks.

Announcing AWS X-Ray SDK for Python support for instrumenting web frameworks deployed in serverless applications! Serverless is an application model that enables you to shift more of your operational responsibilities to AWS. As a result, you can focus only on your applications and services, instead of the infrastructure management tasks such as server provisioning, patching, operating system maintenance, and capacity provisioning. With serverless, you can deploy your web application to AWS Lambda and have customers interact with it through a Lambda-invoking endpoint, such as Amazon API Gateway.

Now you can deploy your Python web application using the serverless model and have AWS X-Ray automatically instrument your web frameworks so that you can track the internal requests. You can see an end-to-end view of all the downstream calls made starting from Amazon API Gateway, to Lambda, and all through the downstream calls that your web application makes.

Currently supported frameworks

The currently supported frameworks for this architecture are Flask and Django.

Prerequisites

In this post, we show an example of creating a serverless application and deploying it to Lambda, where it will be invoked via Amazon API Gateway. We’ll use Zappa to automatically deploy our application to Lambda and configure our API Gateway endpoint.

You need to have the following installed:

Setting up your serverless application

Be sure your AWS CLI is configured with the account and AWS Region that you want your application to be deployed in. Zappa uses this for deployment.

Developing Your Application

First, use your terminal to create a directory to store your application, and then change to the new directory. For this example, we named our project serverless_application.

mkdir serverless_application
cd serverless_application

Next, create a virtual environment inside your new directory, and then use the following command to activate it.

# Create our virtual environment
virtualenv serverless_env

# Activate it
source serverless_env/bin/activate

Install X-Ray, Zappa, Flask, and Requests into your environment.

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

Add some code to your directory. In this example, we’ll write a simple application based on Flask’s Hello World example.

Within the serverless_application directory, create a file named my_app.py. Using your editor of choice, add the following code.

# 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

This application instruments the requests module, patches the Flask application’s middleware, and opens the endpoint ‘/’. When a request is received, the application sends an outgoing request to https://aws.amazon.com and returns the text Hello, World: https://aws.amazon.com.

Creating a Zappa Environment and Deploying it

Go back to your terminal and initialize Zappa from within the new virtual environment.

zappa init

Follow the instructions to configure the Zappa deployment. In this example, use the default settings.

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

Next, we need to enable X-Ray. To do so, open the file named zappa_settings.json in your favorite text editor. It should look something like this.

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

Add “xray_tracing”: true as an entry to your configuration (don’t forget to add a comma to the end of the previous line). The result should be similar to the following.

{
    "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
    }
}

The application is now configured. Next, you need to deploy your application. This automatically configures the API Gateway endpoint and uploads your code to Lambda.

zappa deploy

If everything is deployed correctly, the CLI displays the endpoint URL to access your application. You should see the following result.

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

Next, we need to enable X-Ray tracing for API Gateway.

  1. Open the API Gateway console.
  2. Find your newly generated API (it should look something like serverless-exam-dev).
  3. Choose Stages.
  4. Choose the name of your deployment stage (the default is dev).
  5. On the Logs/Tracing tab, select the Enable X-Ray Tracing box.
  6. Choose Save Changes.

Now use your favorite browser to access your endpoint: https://**.execute-api.us-west-2.amazonaws.com/dev
It should display the text “Hello, World: https://aws.amazon.com/”.

Viewing the Trace

Open the X-Ray console and view your traces. You should see the trace made from the endpoint access, which contains a segment generated by API Gateway, a segment generated by your Lambda function, and a segment generated by the Lambda container. You should also see a subsegment named My First Serverless App under the Lambda function’s segment, followed by another subsegment named https://aws.amazon.com. You might also see another subsegment named initialization. Sometimes Lambda generates this during initialization. The following is an example.

Here is an example of the service graph.

This shows the downstream path starting from API Gateway, through the Lambda function, and to the outgoing request made to https://aws.amazon.com.

The following screenshot is the same call, but made on a local machine running Flask.

In this example, you can see that the Flask middleware generates a node, but the serverless application doesn’t. This is the intended behavior. In Lambda, the container acts as the middleware that instruments the downstream calls.

You can add more features to your application by adding AWS clients using Boto3 to work with services such as AWS DynamoDB and Amazon S3 and instrument them with X-Ray. Web framework support in serverless applications allows you to deploy applications and seamlessly integrate X-Ray into your normal workflow.

Cleaning Up Your Application

To clean up your application and remove it from Lambda, API Gateway, and Amazon S3, run the following command inside your project directory.

zappa undeploy dev

You can also delete your project directory.

rm -r ../serverless_application && cd ..

Give it a try!

Let us know what you think about this feature on GitHub!