Use nano time in JMS consumer Instrumenter (#3986)
* Use nano time in JMS consumer Instrumenter * fix DoNotMockAutoValue
This commit is contained in:
parent
1363e0c093
commit
2b52a8bfe4
|
@ -20,6 +20,7 @@ import javax.jms.Queue;
|
|||
import javax.jms.TemporaryQueue;
|
||||
import javax.jms.TemporaryTopic;
|
||||
import javax.jms.Topic;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
@ -38,6 +39,12 @@ class MessageWithDestinationTest {
|
|||
@Mock Queue queue;
|
||||
@Mock TemporaryQueue temporaryQueue;
|
||||
@Mock Destination destination;
|
||||
@Mock Timer timer;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
given(timer.startTime()).willReturn(START_TIME);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateMessageWithUnknownDestination() throws JMSException {
|
||||
|
@ -46,16 +53,11 @@ class MessageWithDestinationTest {
|
|||
|
||||
// when
|
||||
MessageWithDestination result =
|
||||
MessageWithDestination.create(message, MessageOperation.SEND, null, START_TIME);
|
||||
MessageWithDestination.create(message, MessageOperation.SEND, null, timer);
|
||||
|
||||
// then
|
||||
assertMessage(
|
||||
MessageOperation.SEND,
|
||||
"unknown",
|
||||
"unknown",
|
||||
/* expectedTemporary= */ false,
|
||||
START_TIME,
|
||||
result);
|
||||
MessageOperation.SEND, "unknown", "unknown", /* expectedTemporary= */ false, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -65,16 +67,11 @@ class MessageWithDestinationTest {
|
|||
|
||||
// when
|
||||
MessageWithDestination result =
|
||||
MessageWithDestination.create(message, MessageOperation.SEND, destination, START_TIME);
|
||||
MessageWithDestination.create(message, MessageOperation.SEND, destination, timer);
|
||||
|
||||
// then
|
||||
assertMessage(
|
||||
MessageOperation.SEND,
|
||||
"unknown",
|
||||
"unknown",
|
||||
/* expectedTemporary= */ false,
|
||||
START_TIME,
|
||||
result);
|
||||
MessageOperation.SEND, "unknown", "unknown", /* expectedTemporary= */ false, result);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
@ -97,16 +94,11 @@ class MessageWithDestinationTest {
|
|||
|
||||
// when
|
||||
MessageWithDestination result =
|
||||
MessageWithDestination.create(message, MessageOperation.RECEIVE, null);
|
||||
MessageWithDestination.create(message, MessageOperation.RECEIVE, null, timer);
|
||||
|
||||
// then
|
||||
assertMessage(
|
||||
MessageOperation.RECEIVE,
|
||||
"queue",
|
||||
expectedDestinationName,
|
||||
expectedTemporary,
|
||||
null,
|
||||
result);
|
||||
MessageOperation.RECEIVE, "queue", expectedDestinationName, expectedTemporary, result);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
@ -129,16 +121,11 @@ class MessageWithDestinationTest {
|
|||
|
||||
// when
|
||||
MessageWithDestination result =
|
||||
MessageWithDestination.create(message, MessageOperation.RECEIVE, null);
|
||||
MessageWithDestination.create(message, MessageOperation.RECEIVE, null, timer);
|
||||
|
||||
// then
|
||||
assertMessage(
|
||||
MessageOperation.RECEIVE,
|
||||
"topic",
|
||||
expectedDestinationName,
|
||||
expectedTemporary,
|
||||
null,
|
||||
result);
|
||||
MessageOperation.RECEIVE, "topic", expectedDestinationName, expectedTemporary, result);
|
||||
}
|
||||
|
||||
static Stream<Arguments> destinations() {
|
||||
|
@ -154,14 +141,13 @@ class MessageWithDestinationTest {
|
|||
String expectedDestinationKind,
|
||||
String expectedDestinationName,
|
||||
boolean expectedTemporary,
|
||||
Instant expectedStartTime,
|
||||
MessageWithDestination actual) {
|
||||
|
||||
assertSame(message, actual.getMessage());
|
||||
assertSame(expectedMessageOperation, actual.getMessageOperation());
|
||||
assertEquals(expectedDestinationKind, actual.getDestinationKind());
|
||||
assertEquals(expectedDestinationName, actual.getDestinationName());
|
||||
assertSame(message, actual.message());
|
||||
assertSame(expectedMessageOperation, actual.messageOperation());
|
||||
assertEquals(expectedDestinationKind, actual.destinationKind());
|
||||
assertEquals(expectedDestinationName, actual.destinationName());
|
||||
assertEquals(expectedTemporary, actual.isTemporaryDestination());
|
||||
assertEquals(expectedStartTime, actual.getStartTime());
|
||||
assertEquals(START_TIME, actual.startTime());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
mock-maker-inline
|
|
@ -38,6 +38,9 @@ tasks {
|
|||
val versions: Map<String, String> by project
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.google.auto.value:auto-value-annotations")
|
||||
annotationProcessor("com.google.auto.value:auto-value")
|
||||
|
||||
compileOnly("javax.jms:jms-api:1.1-rev-1")
|
||||
|
||||
testImplementation("javax.annotation:javax.annotation-api:1.3.2")
|
||||
|
|
|
@ -25,13 +25,13 @@ public class JmsMessageAttributesExtractor
|
|||
@Nullable
|
||||
@Override
|
||||
protected String destinationKind(MessageWithDestination messageWithDestination) {
|
||||
return messageWithDestination.getDestinationKind();
|
||||
return messageWithDestination.destinationKind();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected String destination(MessageWithDestination messageWithDestination) {
|
||||
return messageWithDestination.getDestinationName();
|
||||
return messageWithDestination.destinationName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,7 +61,7 @@ public class JmsMessageAttributesExtractor
|
|||
@Override
|
||||
protected String conversationId(MessageWithDestination messageWithDestination) {
|
||||
try {
|
||||
return messageWithDestination.getMessage().getJMSCorrelationID();
|
||||
return messageWithDestination.message().getJMSCorrelationID();
|
||||
} catch (JMSException e) {
|
||||
logger.debug("Failure getting JMS correlation id", e);
|
||||
return null;
|
||||
|
@ -82,14 +82,14 @@ public class JmsMessageAttributesExtractor
|
|||
|
||||
@Override
|
||||
protected MessageOperation operation(MessageWithDestination messageWithDestination) {
|
||||
return messageWithDestination.getMessageOperation();
|
||||
return messageWithDestination.messageOperation();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected String messageId(MessageWithDestination messageWithDestination, Void unused) {
|
||||
try {
|
||||
return messageWithDestination.getMessage().getJMSMessageID();
|
||||
return messageWithDestination.message().getJMSMessageID();
|
||||
} catch (JMSException e) {
|
||||
logger.debug("Failure getting JMS message id", e);
|
||||
return null;
|
||||
|
|
|
@ -17,7 +17,6 @@ import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperat
|
|||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
||||
import java.time.Instant;
|
||||
import javax.jms.Message;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
|
@ -49,13 +48,13 @@ public class JmsMessageConsumerInstrumentation implements TypeInstrumentation {
|
|||
public static class ConsumerAdvice {
|
||||
|
||||
@Advice.OnMethodEnter
|
||||
public static Instant onEnter() {
|
||||
return Instant.now();
|
||||
public static Timer onEnter() {
|
||||
return Timer.start();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Enter Instant startTime,
|
||||
@Advice.Enter Timer timer,
|
||||
@Advice.Return Message message,
|
||||
@Advice.Thrown Throwable throwable) {
|
||||
if (message == null) {
|
||||
|
@ -65,7 +64,7 @@ public class JmsMessageConsumerInstrumentation implements TypeInstrumentation {
|
|||
|
||||
Context parentContext = Java8BytecodeBridge.currentContext();
|
||||
MessageWithDestination request =
|
||||
MessageWithDestination.create(message, MessageOperation.RECEIVE, null, startTime);
|
||||
MessageWithDestination.create(message, MessageOperation.RECEIVE, null, timer);
|
||||
|
||||
if (consumerInstrumenter().shouldStart(parentContext, request)) {
|
||||
Context context = consumerInstrumenter().start(parentContext, request);
|
||||
|
|
|
@ -11,7 +11,6 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
|||
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessagingSpanNameExtractor;
|
||||
import java.time.Instant;
|
||||
|
||||
public final class JmsSingletons {
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jms-1.1";
|
||||
|
@ -37,7 +36,7 @@ public final class JmsSingletons {
|
|||
otel, INSTRUMENTATION_NAME, spanNameExtractor)
|
||||
.addAttributesExtractor(attributesExtractor)
|
||||
.setTimeExtractors(
|
||||
MessageWithDestination::getStartTime, (request, response) -> Instant.now())
|
||||
MessageWithDestination::startTime, (request, response) -> request.endTime())
|
||||
.newInstrumenter(SpanKindExtractor.alwaysConsumer());
|
||||
LISTENER_INSTRUMENTER =
|
||||
Instrumenter.<MessageWithDestination, Void>newBuilder(
|
||||
|
|
|
@ -14,7 +14,7 @@ public final class MessagePropertyGetter implements TextMapGetter<MessageWithDes
|
|||
@Override
|
||||
public Iterable<String> keys(MessageWithDestination message) {
|
||||
try {
|
||||
return Collections.list(message.getMessage().getPropertyNames());
|
||||
return Collections.list(message.message().getPropertyNames());
|
||||
} catch (JMSException e) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public final class MessagePropertyGetter implements TextMapGetter<MessageWithDes
|
|||
String propName = key.replace("-", MessagePropertySetter.DASH);
|
||||
final Object value;
|
||||
try {
|
||||
value = carrier.getMessage().getObjectProperty(propName);
|
||||
value = carrier.message().getObjectProperty(propName);
|
||||
} catch (JMSException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ final class MessagePropertySetter implements TextMapSetter<MessageWithDestinatio
|
|||
public void set(MessageWithDestination carrier, String key, String value) {
|
||||
String propName = key.replace("-", DASH);
|
||||
try {
|
||||
carrier.getMessage().setStringProperty(propName, value);
|
||||
carrier.message().setStringProperty(propName, value);
|
||||
} catch (JMSException e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failure setting jms property: {}", propName, e);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.jms;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.messaging.MessageOperation;
|
||||
import java.time.Instant;
|
||||
import javax.jms.Destination;
|
||||
|
@ -14,69 +15,40 @@ import javax.jms.Queue;
|
|||
import javax.jms.TemporaryQueue;
|
||||
import javax.jms.TemporaryTopic;
|
||||
import javax.jms.Topic;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class MessageWithDestination {
|
||||
@AutoValue
|
||||
public abstract class MessageWithDestination {
|
||||
|
||||
// visible for tests
|
||||
static final String TIBCO_TMP_PREFIX = "$TMP$";
|
||||
|
||||
private final Message message;
|
||||
private final MessageOperation messageOperation;
|
||||
private final String destinationName;
|
||||
private final String destinationKind;
|
||||
private final boolean temporaryDestination;
|
||||
private final Instant startTime;
|
||||
public abstract Message message();
|
||||
|
||||
private MessageWithDestination(
|
||||
Message message,
|
||||
MessageOperation messageOperation,
|
||||
String destinationName,
|
||||
String destinationKind,
|
||||
boolean temporary,
|
||||
Instant startTime) {
|
||||
this.message = message;
|
||||
this.messageOperation = messageOperation;
|
||||
this.destinationName = destinationName;
|
||||
this.destinationKind = destinationKind;
|
||||
this.temporaryDestination = temporary;
|
||||
this.startTime = startTime;
|
||||
public abstract MessageOperation messageOperation();
|
||||
|
||||
public abstract String destinationName();
|
||||
|
||||
public abstract String destinationKind();
|
||||
|
||||
public abstract boolean isTemporaryDestination();
|
||||
|
||||
abstract Timer timer();
|
||||
|
||||
public Instant startTime() {
|
||||
return timer().startTime();
|
||||
}
|
||||
|
||||
public Message getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public MessageOperation getMessageOperation() {
|
||||
return messageOperation;
|
||||
}
|
||||
|
||||
public String getDestinationName() {
|
||||
return destinationName;
|
||||
}
|
||||
|
||||
public String getDestinationKind() {
|
||||
return destinationKind;
|
||||
}
|
||||
|
||||
public boolean isTemporaryDestination() {
|
||||
return temporaryDestination;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Instant getStartTime() {
|
||||
return startTime;
|
||||
public Instant endTime() {
|
||||
return timer().endTime();
|
||||
}
|
||||
|
||||
public static MessageWithDestination create(
|
||||
Message message, MessageOperation operation, Destination fallbackDestination) {
|
||||
return create(message, operation, fallbackDestination, null);
|
||||
return create(message, operation, fallbackDestination, Timer.start());
|
||||
}
|
||||
|
||||
public static MessageWithDestination create(
|
||||
Message message,
|
||||
MessageOperation operation,
|
||||
Destination fallbackDestination,
|
||||
@Nullable Instant startTime) {
|
||||
Message message, MessageOperation operation, Destination fallbackDestination, Timer timer) {
|
||||
Destination jmsDestination = null;
|
||||
try {
|
||||
jmsDestination = message.getJMSDestination();
|
||||
|
@ -88,17 +60,17 @@ public final class MessageWithDestination {
|
|||
}
|
||||
|
||||
if (jmsDestination instanceof Queue) {
|
||||
return createMessageWithQueue(message, operation, (Queue) jmsDestination, startTime);
|
||||
return createMessageWithQueue(message, operation, (Queue) jmsDestination, timer);
|
||||
}
|
||||
if (jmsDestination instanceof Topic) {
|
||||
return createMessageWithTopic(message, operation, (Topic) jmsDestination, startTime);
|
||||
return createMessageWithTopic(message, operation, (Topic) jmsDestination, timer);
|
||||
}
|
||||
return new MessageWithDestination(
|
||||
message, operation, "unknown", "unknown", /* temporary= */ false, startTime);
|
||||
return new AutoValue_MessageWithDestination(
|
||||
message, operation, "unknown", "unknown", /* isTemporaryDestination= */ false, timer);
|
||||
}
|
||||
|
||||
private static MessageWithDestination createMessageWithQueue(
|
||||
Message message, MessageOperation operation, Queue destination, @Nullable Instant startTime) {
|
||||
Message message, MessageOperation operation, Queue destination, Timer timer) {
|
||||
String queueName;
|
||||
try {
|
||||
queueName = destination.getQueueName();
|
||||
|
@ -109,11 +81,12 @@ public final class MessageWithDestination {
|
|||
boolean temporary =
|
||||
destination instanceof TemporaryQueue || queueName.startsWith(TIBCO_TMP_PREFIX);
|
||||
|
||||
return new MessageWithDestination(message, operation, queueName, "queue", temporary, startTime);
|
||||
return new AutoValue_MessageWithDestination(
|
||||
message, operation, queueName, "queue", temporary, timer);
|
||||
}
|
||||
|
||||
private static MessageWithDestination createMessageWithTopic(
|
||||
Message message, MessageOperation operation, Topic destination, @Nullable Instant startTime) {
|
||||
Message message, MessageOperation operation, Topic destination, Timer timer) {
|
||||
String topicName;
|
||||
try {
|
||||
topicName = destination.getTopicName();
|
||||
|
@ -124,6 +97,7 @@ public final class MessageWithDestination {
|
|||
boolean temporary =
|
||||
destination instanceof TemporaryTopic || topicName.startsWith(TIBCO_TMP_PREFIX);
|
||||
|
||||
return new MessageWithDestination(message, operation, topicName, "topic", temporary, startTime);
|
||||
return new AutoValue_MessageWithDestination(
|
||||
message, operation, topicName, "topic", temporary, timer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.jms;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public final class Timer {
|
||||
|
||||
public static Timer start() {
|
||||
return new Timer(Instant.now(), System.nanoTime());
|
||||
}
|
||||
|
||||
private final Instant startTime;
|
||||
private final long startNanoTime;
|
||||
|
||||
private Timer(Instant startTime, long startNanoTime) {
|
||||
this.startTime = startTime;
|
||||
this.startNanoTime = startNanoTime;
|
||||
}
|
||||
|
||||
public Instant startTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public Instant endTime() {
|
||||
long durationNanos = System.nanoTime() - startNanoTime;
|
||||
return startTime().plusNanos(durationNanos);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue