[DOCKER] Try running AWS X-Ray in Java

Prerequisites

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.

Create an X-Ray Docker container image.

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.

Application X-Ray support

Receive request support

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.

キャプチャ6.PNG

Get detailed information

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.

キャプチャ7.PNG

Downstream trace support

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.

キャプチャ8.PNG

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.

キャプチャ9.PNG

Run with ECS on Fargate

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.

キャプチャ10.PNG

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

Try running AWS X-Ray in Java
Try running Selenuim 3.141.59 in eclipse (java)
Try using RocksDB in Java
Try calling JavaScript in Java
Try developing Spresense in Java (1)
Try functional type in Java! ①
Try implementing Android Hilt in Java
Try implementing GraphQL server in Java
Try running ruby-net-nntp and tmail in 2020
Try an If expression in Java
Deleting AWS S3 Objects in Java
Renamed folders in AWS S3 (Java)
Try to implement Yubaba in Java
Try to solve Project Euler in Java
Try to implement n-ary addition in Java
Try running Word2vec model on AWS Lambda
Try using the Stream API in Java
Try using JSON format API in Java
Try calling the CORBA service in Java 11+
Try running a Kubernetes Job from Java
Try making a calculator app in Java
Try managing Java libraries with AWS CodeArtifact
Partization in Java
Try Java 8 Stream
Rock-paper-scissors in Java
Pi in Java
Roughly try Java 9
FizzBuzz in Java
[AWS IoT] Implementing Authorizing Direct Calls in Java [Java]
Try scraping about 30 lines in Java (CSV output)
Try using Sourcetrail (win version) in Java code
Try using GCP's Cloud Vision API in Java
Try using Sourcetrail (macOS version) in Java code
Try using the COTOHA API parsing in Java
[java] sort in list
Read JSON in Java
Interpreter implementation in Java
Make Blackjack in Java
Rock-paper-scissors app in Java
Constraint programming in Java
Put java8 in centos7
NVL-ish guy in Java
Combine arrays in Java
"Hello World" in Java
Callable Interface in Java
It's late! Try implementing Android Notification in Java (Beginner)
Azure functions in java
Try LetCode in Ruby-TwoSum
Simple htmlspecialchars in Java
Boyer-Moore implementation in Java
Hello World in Java
webApi memorandum in java
Type determination in Java
Ping commands in Java
Various threads in java
Heapsort implementation (in java)
ASCII art in Java
Compare Lists in Java
POST JSON in Java
Express failure in Java
Try global hooking in Java using the JNativeHook library