Javaエージェントは、 AWS SQS メッセージキューのインストゥルメンテーションをサポートしています。 SQS インストゥルメンテーションはメッセージ ブローカー トレースを生成しますが、SQS SDK の使用法に関する追加情報が必要になる場合があります。
サポートされているすべての SQS ライブラリを確認するには、 Java の互換性と要件のページを参照してください。
重要
Javaエージェント 8.18.0 のユーザーは、SQS インストゥルメンテーションを手動で有効にする必要があります。 このインストゥルメンテーションは、 newrelic.yml
ファイルで有効にできます。
class_transformer: aws-java-sdk-sqs: enabled: true
あるいは、システム プロパティ-Dnewrelic.config.class_transformer.aws-java-sdk-sqs.enabled=true
または環境変数NEW_RELIC_CLASS_TRANSFORMER_AWS_JAVA_SDK_SQS_ENABLED=true
を設定することもできます。
インストゥルメンテーションは、 Javaエージェントの他のバージョンではデフォルトで有効になっています。
View SQS ディストリビューティッド(分散)トレーシング
AWS SQS SDK インストゥルメンテーションには、SQS メッセージのメッセージ属性としてディストリビューティッド(分散)トレーシング ヘッダーが自動的に含まれます。 この機能はバージョン 2.1.0 以降で利用できます。 ただし、メッセージ受信操作の場合、これらのヘッダーを処理する組み込みメソッドはありません。 ディストリビューティッド(分散)トレーシング ヘッダーを読み取るためにカスタムインストゥルメンテーションを実装することをお勧めします。
以下は、V2 SDK を使用して SQS メッセージからディストリビューティッド(分散)トレーシング ヘッダーを読み取る方法の例です。
// This method will call the SDK to receive messages and then process them public void readMessages(SqsClient sqsClient, String queueUrl) { List<Message> msgs = receiveMessages(queueUrl); for (Message msg : msgs) { handleMessage(msg); } }
// Since calling the SDK to recieve messages is a batch call, it is not recommended to accept distributed trace headers // in the same transaction as the SDK call. Distributed traces can only have one parent span. @Trace(dispatcher = true, metricName = "v2/receiveMessages") public List<Message> receiveMessages(SqsClient sqsClient, String queueUrl) { ReceiveMessageRequest request = ReceiveMessageRequest.builder() .queueUrl(queueUrl) .maxNumberOfMessages(10) .build();
List<Message> messages = sqsClient.receiveMessage(request).messages(); if (messages.isEmpty()) { logger.info("[v2 API] No messages received"); } return messages; }
// Here we accept distributed trace headers in a seperate transaction from the SDK call. @Trace(dispatcher = true, metricName = "v2/handleMessage") public void handleMessage(Message msg, SqsClient sqsClient, String queueUrl) { // We use a wrapper class that helps extract the distributed trace headers SQSReceivedMessageHeaders headers = new SQSReceivedMessageHeaders(msg); // Here we accept the distributed trace headers NewRelic.getAgent().getTransaction().acceptDistributedTraceHeaders(TransportType.Other, headers);
// Process your message here
DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder() .queueUrl(queueUrl) .receiptHandle(msg.receiptHandle()) .build(); sqsClient.deleteMessage(deleteMessageRequest); }
以下は、SQS メッセージからディストリビューティッド(分散)トレーシング ヘッダーを抽出するラッパー クラスSQSReceivedMessageHeaders
です。
import com.newrelic.api.agent.HeaderType;import com.newrelic.api.agent.Headers;import software.amazon.awssdk.services.sqs.model.Message;import software.amazon.awssdk.services.sqs.model.MessageAttributeValue;
import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.List;import java.util.Map;
public class SQSReceivedMessageHeaders implements Headers {
private Message message = null;
public SQSReceivedMessageHeaders(Message msg) { message = msg; }
@Override public HeaderType getHeaderType() { return HeaderType.MESSAGE; }
@Override public String getHeader(String name) { String value = null; Map<String, MessageAttributeValue> msgAttributes = message.messageAttributes(); MessageAttributeValue msgAttributeValue = msgAttributes.get(name); if(msgAttributeValue != null) { if(msgAttributeValue.dataType().equalsIgnoreCase("string")) { value = msgAttributeValue.stringValue(); } } return value; }
@Override public Collection<String> getHeaders(String name) { List<String> list = new ArrayList<String>(); String value = getHeader(name); if(value != null && !value.isEmpty()) { list.add(value); } return list; }
@Override public void setHeader(String name, String value) { // Not supported }
@Override public void addHeader(String name, String value) { // Not supported }
@Override public Collection<String> getHeaderNames() { if(message != null) { Map<String, MessageAttributeValue> attributes = message.messageAttributes(); if(attributes != null) return attributes.keySet(); } return Collections.emptyList(); }
@Override public boolean containsHeader(String name) { return getHeaderNames().contains(name); }
}