Javaエージェントは、 AWS SQS メッセージキューのインストゥルメンテーションをサポートしています。 SQS インストゥルメンテーションはメッセージ ブローカー トレースを生成しますが、SQS SDK の使用法に関する追加情報が必要になる場合があります。
サポートされているすべての SQS ライブラリを確認するには、 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); }
}