AWS X-Ray in Distributed Microservices — Part 1: Setup

Dmitry Nefedov
5 min readOct 20, 2020

--

AWS X-Ray is an AWS managed service that helps to visualize, analyze and debug distributed applications.

You do need some code changes to use AWS X-Ray; however, with tiny changes, you could enable a lot of visibility and traceability in your application.

In this blog, I’ll show how easy is to start using AWS X-Ray and how it could help in a couple of tricky scenarios.

Concepts

A very brief overview of AWS X-Ray concepts.

Service graph

Service graph or map is a visual representation for your application. Each resource is shown as a node in a graph.

Service graph

Segment

Is a representation of a logical compute resource in the application.

Segment for layer 3 Lambda

Subsegment

A further break down of the data with more granular timing information and details about the call.

Subsegments for l3 Lambda segment

Traces

Each trace id represents a path that a particular request uses to go through an application

List of traces
Specific trace for a request

Setup

AWS X-ray can trace different types of requests:

  • API Gateway requests
  • http(s) calls from the application
  • AWS SDK calls
  • DB queries
  • Custom segments/subsegments

I’ve found that the first four are the easiest to implement and give a lot of useful information about the distributed application. In many scenarios adding those is enough to have sufficient visibility on how an application is used.

Using the first four types, AWS X-Ray shows the architecture and propagation of requests within microservices.

As you will see, with just a few lines of code we can cover most of the actions done by a regular cloud-based web application.

AWS X-Ray wrappers

AWS X-Ray uses wrappers to instrument the calls and supports multiple languages: Go, Java, Node.js, Python, Ruby, .NET.

I will be using Node.js in the examples below, but all X-Ray wrappers give similar results and experiences regardless of programming language.

AWS X-Ray daemon

AWS X-Ray Daemon is required to get raw segment data and send it to AWS X-Ray API.

AWS Lambda and AWS Elastic Beanstalk have built-in integration with X-ray and do not require a separate daemon to run.

API Gateway

AWS X-Ray tracing for API GW could be enabled with CloudFormation; however, it only supports new API Gateways and cannot be added to an existing one. If you have existing API GW with CFN template, adding TracingEnabled would cause a failure (unless you’re happy to remove and recreate an API GW).
However, AWS Console and AWS CLI could be used for it with no issues.

aws apigateway update-stage --rest-api-id ${REST_API_ID} --stage-name ${STAGE} --patch-operations op=replace,path=/tracingEnabled,value=true

Make sure a role you’re using has the following permissions

Statement:
- Action:
- 'iam:CreateServiceLinkedRole'
Resource: !Sub 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/*'
Effect: Allow

http(s) calls from the application

AWS X-Ray could be used to trace any outcoming HTTP(s) calls. It uses a wrapper that gets a data from the call request/response and adds a tracing header with a Parent ID to the call.

To start tracing it, your application needs two main parts:

  • permissions
  • aws x-ray sdk
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess"

e.g. NodeJS

const AWSXRay = require('aws-xray-sdk'); AWSXRay.captureHTTPsGlobal(require('http')); AWSXRay.captureHTTPsGlobal(require('https'));

And that's it! Place those 3 lines of code in your handler.js and all your nested classes would be traced for outgoing http(s) calls: rest, soap etc.

If you’re using restful microservices than adding just HTTP(s) calls capture would give you quite a good picture of what your distributed system is doing and how requests get propagated. Yes, by adding 3 lines of code and the permission.

AWS SDK calls

To trace AWS SDK calls with X-Ray just use x-ray wrapper and the same permission as above.

ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess"

And a wrapper

const AWS = AWSXRay.captureAWS(require('aws-sdk'));

That's all that is needed for a NodeJS application to trace AWS SDK calls with AWS X-Ray. This covers all the interaction with DynamoDB, SQS, SNS, S3, etc

DB queries

To capture Postgres or MySQL queries use the same policy

ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess"

and a corresponding wrapper to create a connection

const AWSXRay = require('aws-xray-sdk’);
const pg = AWSXRay.capturePostgres(require('pg'));
...const AWSXRay = require('aws-xray-sdk’);
const mysql = AWSXRay.captureMySQL(require('mysql'));

Custom subsegment.

You can create your own segments and subsegments to wrap some pieces of code and get a visual representation of it on a service map. This could be useful for some transformation or sorting withing an application to keep an eye on performance an errors.

AWSXRay.captureAsyncFunc('send', function(subsegment) {
sendRequest(host, function() {
console.log('rendering!');
res.render('index');
subsegment.close();
});
});

Conclusion

A number of times I’ve heard concerns that AWS X-Ray requires significant code changes and is not that easy to setup.

Hopefully, in this article, I was able to show how quick and simple is to get a lot of value by using AWS X-Ray in a common cloud application to cover scenarios like current architecture, outgoing HTTP calls, DB queries, and AWS SDK usage.

Use cases and my experience of using AWS X-Ray in production applications are expressed in “AWS X-Ray in Distributed Microservices — Part 2: Use cases”

--

--