Skip to content

Commit f11e902

Browse files
Adjust SQS message transaction lifetime to handle flux flow (#4205)
* Adjust transaction lifetime to handle flux flow * fix span end * update CHANGELOG * Update apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-common/src/main/java/co/elastic/apm/agent/awssdk/common/AbstractMessageIteratorWrapper.java Co-authored-by: SylvainJuge <[email protected]> * review feedback --------- Co-authored-by: SylvainJuge <[email protected]>
1 parent 80df636 commit f11e902

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

CHANGELOG.next-release.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This file contains all changes which are not released yet.
1111
<!--FIXES-START-->
1212
* Fix async httpclient 5.x instrumentation - [#4185](https://github.com/elastic/apm-agent-java/pull/4185)
1313
* Prevent `FileSystemAlreadyExistsException` on single-jar application startup - [#4204](https://github.com/elastic/apm-agent-java/pull/4204)
14+
* Improve SQS async transaction handling to be better with flux flow - [#4205](https://github.com/elastic/apm-agent-java/pull/4205)
1415

1516
<!--FIXES-END-->
1617
# Features and enhancements

apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-common/src/main/java/co/elastic/apm/agent/awssdk/common/AbstractMessageIteratorWrapper.java

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
import javax.annotation.Nullable;
3131
import java.util.Iterator;
32+
import java.util.NoSuchElementException;
33+
import java.util.concurrent.atomic.AtomicBoolean;
3234

3335
import static co.elastic.apm.agent.awssdk.common.AbstractSQSInstrumentationHelper.MESSAGE_PROCESSING_ACTION;
3436
import static co.elastic.apm.agent.awssdk.common.AbstractSQSInstrumentationHelper.MESSAGING_TYPE;
@@ -43,6 +45,7 @@ public abstract class AbstractMessageIteratorWrapper<Message> implements Iterato
4345
private final String queueName;
4446
private final AbstractSQSInstrumentationHelper<?, ?, Message> sqsInstrumentationHelper;
4547
private final TextHeaderGetter<Message> textHeaderGetter;
48+
private final AtomicBoolean iterationEnded;
4649

4750
public AbstractMessageIteratorWrapper(Iterator<Message> delegate, Tracer tracer,
4851
String queueName,
@@ -53,21 +56,25 @@ public AbstractMessageIteratorWrapper(Iterator<Message> delegate, Tracer tracer,
5356
this.queueName = queueName;
5457
this.sqsInstrumentationHelper = sqsInstrumentationHelper;
5558
this.textHeaderGetter = textHeaderGetter;
59+
this.iterationEnded = new AtomicBoolean(false);
5660
}
5761

5862
@Override
5963
public boolean hasNext() {
60-
endCurrentTransaction();
61-
endMessageProcessingSpan();
62-
return delegate.hasNext();
64+
boolean hasNext = delegate.hasNext();
65+
if (!hasNext && iterationEnded.compareAndSet(false, true)) {
66+
endCurrentTransaction();
67+
endMessageProcessingSpan();
68+
}
69+
return hasNext;
6370
}
6471

6572
@Nullable
6673
public Transaction<?> endCurrentTransaction() {
6774
Transaction<?> transaction = null;
6875
try {
6976
transaction = tracer.currentTransaction();
70-
if (transaction != null && MESSAGING_TYPE.equals(transaction.getType())) {
77+
if (transaction != null && !transaction.isFinished() && MESSAGING_TYPE.equals(transaction.getType())) {
7178
transaction.deactivate().end();
7279
return null;
7380
}
@@ -93,12 +100,21 @@ public void endMessageProcessingSpan() {
93100

94101
@Override
95102
public Message next() {
96-
Transaction<?> currentTransaction = endCurrentTransaction();
97-
Message sqsMessage = delegate.next();
98-
if (currentTransaction == null) {
99-
sqsInstrumentationHelper.startTransactionOnMessage(sqsMessage, queueName, textHeaderGetter);
103+
try {
104+
Transaction<?> currentTransaction = endCurrentTransaction();
105+
Message sqsMessage = delegate.next();
106+
if (currentTransaction == null) {
107+
sqsInstrumentationHelper.startTransactionOnMessage(sqsMessage, queueName, textHeaderGetter);
108+
}
109+
return sqsMessage;
110+
} catch (NoSuchElementException e) {
111+
// end the transaction when the caller loops with a try/catch until an exception is thrown
112+
if (iterationEnded.compareAndSet(false, true)) {
113+
endCurrentTransaction();
114+
endMessageProcessingSpan();
115+
}
116+
throw e;
100117
}
101-
return sqsMessage;
102118
}
103119

104120

0 commit comments

Comments
 (0)