AWS XRAY with FASTAPI
Tags: aws, devops, webdev, python
Published: 2023-04-12 05:09:26

Hi Guys, I think you stumble upon the article after a very long search of 
```How to integrate AWS Xray with application written with FASTAPI python? ```

So you are not alone I have searched for a very long time and this is what I found which works for me, there are something which I don't understand it's just there😅.

First, let's take a quick look at what AWS X-Ray is. AWS X-Ray is a distributed tracing system that allows you to visualize the entire lifecycle of a request across all of your microservices. With X-Ray, you can quickly identify performance bottlenecks, troubleshoot errors, and understand the dependencies between your services.
If You wanna read more about aws xray here the [link](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html)


##**Let's Start.**

First you need to know where you are going to deploy the application EC2, EBS, or EKS. I have deployed it on EKS so I'll use that over here, but all of them will work with little bit of changes.

### **Installation of ADOT Collector**
For those who are wondering what's this? AWS Distro for OpenTelemetry, and for those who were thinking that they can get away without installing it you were wrong as I am🥲, I thought it too but can't so here the [link you can follow to install](https://aws-otel.github.io/docs/getting-started/collector) it for [EKS](https://aws-otel.github.io/docs/getting-started/adot-eks-add-on/installation).

After you have decided and installed the collector with your prefer way of installing (I prefer Daemonset) remember the service name we have to mention it in application.


###**Integration**
There are some python packages that you need to install

```opentelemetry-api==1.15.0
opentelemetry-distro==0.36b0
opentelemetry-exporter-otlp==1.15.0
opentelemetry-exporter-otlp-proto-grpc==1.15.0
opentelemetry-exporter-otlp-proto-http==1.15.0
opentelemetry-instrumentation==0.36b0
opentelemetry-instrumentation-asgi==0.36b0
opentelemetry-instrumentation-aws-lambda==0.36b0
opentelemetry-instrumentation-boto3sqs==0.36b0
opentelemetry-instrumentation-botocore==0.36b0
opentelemetry-instrumentation-dbapi==0.36b0
opentelemetry-instrumentation-fastapi==0.36b0
opentelemetry-instrumentation-grpc==0.36b0
opentelemetry-instrumentation-logging==0.36b0
opentelemetry-instrumentation-pymongo==0.36b0
opentelemetry-instrumentation-requests==0.36b0
opentelemetry-instrumentation-sqlalchemy==0.36b0
opentelemetry-instrumentation-sqlite3==0.36b0
opentelemetry-instrumentation-starlette==0.36b0
opentelemetry-instrumentation-urllib==0.36b0
opentelemetry-instrumentation-urllib3==0.36b0
opentelemetry-instrumentation-wsgi==0.36b0
opentelemetry-propagator-aws-xray==1.0.1
opentelemetry-proto==1.15.0
opentelemetry-sdk==1.15.0
opentelemetry-sdk-extension-aws==2.0.1
opentelemetry-semantic-conventions==0.36b0
opentelemetry-util-http==0.36b0
```

I know it's never ending list trust me, but without these my application wasn't even starting so I don't know about these but it works I hope it works for you too.


**Main Code**
```
# OpenTelemetry Configuration
# Basic packages for your application
# Add imports for OTel components into the application
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor


# Import the AWS X-Ray for OTel Python IDs Generator into the application.
from opentelemetry.sdk.extension.aws.trace import AwsXRayIdGenerator

# Sends generated traces in the OTLP format to an ADOT Collector running on port 4317
otlp_exporter = OTLPSpanExporter(endpoint="http://xray-collector-collector.amazon-cloudwatch:4317")
# Processes traces in batches as opposed to immediately one after the other
span_processor = BatchSpanProcessor(otlp_exporter)
# Configures the Global Tracer Provider
trace.set_tracer_provider(TracerProvider(active_span_processor=span_processor, id_generator=AwsXRayIdGenerator()))



# Using the AWS resource Detectors
import opentelemetry.trace as trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.extension.aws.resource.ec2 import (
    AwsEc2ResourceDetector,
)
from opentelemetry.sdk.resources import get_aggregated_resources

trace.set_tracer_provider(
    TracerProvider(
        resource=get_aggregated_resources(
            [
                AwsEc2ResourceDetector(),
            ]
        ),
    )
)

app = FastAPI()

@app.get("/test")
def test():
    return {"message": "Hello This is testing"}
```

You might be thinking why I copy pasted the whole code, it's coz when I was searching I couldn't make any sense of the code so I thought why not just pour it all.

Make sure you set your own endpoint url in the **otlp_exporter** 
otherwise it won't send any traces.


### **Dockerfile**

```
# Pull base image
FROM python:3.8

# Set enviroment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV PYTHONPATH=/code
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"


# Added OpenTelemetry Collector attributes

ENV OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST=".*"
ENV OTEL_RESOURCE_ATTRIBUTES='service.name=aws-xray-test'


# Set work directory
WORKDIR /code

# Install dependencies
COPY requirements.txt /code/

RUN pip install -r requirements.txt  --no-cache-dir

# Copy project
COPY . /code/

ENTRYPOINT ["opentelemetry-instrument","/opt/venv/bin/python", "-m", "uvicorn", "main:app"]
CMD ["--reload", "--host", "0.0.0.0", "--port", "8000"]
``` 

**NOTE: see the Entrypoint and the ENV make sure you set them**


And My Wonderful reader if you made it till here than I hope your Integration is successful

###**Conclusion**
In conclusion, integrating AWS X-Ray with your FastAPI application is a simple and effective way to gain visibility into the performance and behavior of your application. With X-Ray, you can quickly identify performance bottlenecks, troubleshoot errors, and understand the dependencies between your services. So why not give it a try today?

Plus If you face any issue with above steps plz reach out to me
here's my [linkedin](https://www.linkedin.com/in/ashutoshsingh5786/)