For X-Ray beginners. I know somehow, but this is an article that I confirmed while trying various things, specifically what can be done and how to implement it.
As an environment, a web application is implemented with Spring Boot + Maven. Gradle should be the same except for the dependency resolution.
First, create a container image with appropriate EC2. This time, let's make it based on the AWS sample.
$ git clone https://github.com/aws-samples/aws-xray-fargate
Try running the command in buildspec.yml.
$ aws ecr get-login --no-include-email --region ap-northeast-1
After getting the login information with, execute. ap-northeast-1
specifies the region you are using.
$ docker build -t xray:latest .
Let's check the normality of the created container image. Refer to the following. The meaning of each docker run option is also described, so please read it.
[Official] Run the X-Ray daemon locally
$ docker run \
--attach STDOUT \
-v ~/.aws/:/root/.aws/:ro \
--net=host \
-e AWS_REGION=ap-northeast-1 \
--name xray \
-p 2000:2000/udp \
xray -o
Also, add the IAM policy of AWSXRayDaemonWriteAccess
to the EC2 role.
Refer to the following developer guide and send the X-Ray log to the daemon on the application side.
[Official] AWS X-Ray SDK for Java
It seems easy just to respond to incoming requests. Implement the `` `WebConfig.javaclass as follows.
ApigwTest``` is the name of the web application created in the sample.
WebConfig.java
package com.example;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import javax.servlet.Filter;
import com.amazonaws.xray.javax.servlet.AWSXRayServletFilter;
@Configuration
public class WebConfig {
@Bean
public Filter TracingFilter() {
return new AWSXRayServletFilter("ApigwTest");
}
}
Since X-Ray needs to use AWS SDK, write the following in pom.xml to resolve the dependency.
pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-bom</artifactId>
<version>2.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-core</artifactId>
</dependency>
</dependencies>
By the way, when you start this app and access it, you will be able to trace like this.
In addition, put the following code in the `` `WebConfig``` class created in ↑ so that you can get the information of the node that received the reception request.
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.AWSXRayRecorderBuilder;
import com.amazonaws.xray.plugins.EC2Plugin;
import com.amazonaws.xray.plugins.ECSPlugin;
static {
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin()).withPlugin(new ECSPlugin());
AWSXRay.setGlobalRecorder(builder.build());
}
If you do this on EC2, the service map will show that it is an EC2 instance, as shown below.
Furthermore, if you want to get information on downstream Web services as an HTTP client, try putting something like this in the controller.
import com.amazonaws.xray.proxies.apache.http.HttpClientBuilder;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.impl.client.CloseableHttpClient;
import java.io.IOException;
(Omission)
public int HttpClient(String URL) throws IOException {
int statusCode = 500;
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(URL);
CloseableHttpResponse clientResponse = httpclient.execute(httpGet);
try {
statusCode = clientResponse.getStatusLine().getStatusCode();
} finally {
clientResponse.close();
}
return statusCode;
}
Also, in order to import `` `com.amazonaws.xray.proxies.apache.http.HttpClientBuilder```, add the following dependency to pom.xml.
pom.xml
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-apache-http</artifactId>
</dependency>
</dependencies>
Then, downstream information can also be acquired as shown below.
By the way, this downstream service was implemented by the Lambda function, so when I suddenly became interested and enabled the X-Ray setting on the Lambda function side, ↓ Like this, duplicate elements were not acquired. smart.
First, push the X-Ray container that has been confirmed to work up to this point to ECR. Don't forget to create an xray repository in advance.
$ docker tag xray:latest [AWS account ID].dkr.ecr.[region].amazonaws.com/xray:latest
$ docker push [AWS account ID].dkr.ecr.[region].amazonaws.com/xray:latest
Also, here as well, AWSXRayDaemonWriteAccess
is assigned to the ECS task role and task execution role.
Put the image of xray PUSHed in ↑ in the task definition of the container. Speaking of CloudFormation template, in `` `ContainerDefinitions```, write the following definition alongside the existing container definition. In the case of ECS on EC2 that does not use awsvpc, other settings are required, but in the case of Fargate, it works with awsvpc, so it seems easy to add.
- Name: X-Ray-Daemon
Image: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/xray:latest
Cpu: 32
MemoryReservation: 256
PortMappings:
- ContainerPort: 2000
Protocol: udp
When I enabled active tracing on the Lambda side, I was able to get it in the same way as EC2.
However, when the active trace on the Lambda side was disabled, the trace for the request could be obtained, but the downstream trace could not be obtained. There may be some settings that are still missing.
Recommended Posts