package org.stagemonitor.tracing;
import com.codahale.metrics.Timer;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.scheduling.annotation.Async;
import org.stagemonitor.core.MeasurementSession;
import org.stagemonitor.core.Stagemonitor;
import org.stagemonitor.core.metrics.metrics2.Metric2Filter;
import org.stagemonitor.core.metrics.metrics2.Metric2Registry;
import org.stagemonitor.core.metrics.metrics2.MetricName;
import org.stagemonitor.tracing.utils.SpanUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.stagemonitor.core.metrics.metrics2.MetricName.name;
public class MonitorRequestsTransformerTest {
private TestClass testClass;
private TestClassLevelAnnotationClass testClassLevelAnnotationClass;
private Metric2Registry metricRegistry;
private SpanCapturingReporter spanCapturingReporter;
private Map<String, Object> tags;
@BeforeClass
public static void attachProfiler() {
Stagemonitor.init();
}
@Before
public void before() throws Exception {
testClass = new TestSubClass();
metricRegistry = Stagemonitor.getMetric2Registry();
testClassLevelAnnotationClass = new TestClassLevelAnnotationClass();
metricRegistry.removeMatching(Metric2Filter.ALL);
Stagemonitor.setMeasurementSession(new MeasurementSession("MonitorRequestsTransformerTest", "test", "test"));
Stagemonitor.startMonitoring();
spanCapturingReporter = new SpanCapturingReporter();
tags = new HashMap<>();
Stagemonitor.getPlugin(TracingPlugin.class).addSpanInterceptor(new TagRecordingSpanEventListener(tags));
Stagemonitor.getPlugin(TracingPlugin.class).addReporter(spanCapturingReporter);
}
@AfterClass
public static void resetStagemonitor() {
Stagemonitor.reset();
}
@Test
public void testMonitorRequests() throws Exception {
testClass.monitorMe(1);
final SpanContextInformation spanContext = spanCapturingReporter.get();
// either parameters.arg0 or parameters.s
assertEquals("1", getTagsStartingWith(tags, SpanUtils.PARAMETERS_PREFIX).iterator().next());
assertEquals("MonitorRequestsTransformerTest$TestClass#monitorMe", spanContext.getOperationName());
assertEquals(1, spanContext.getCallTree().getChildren().size());
final String signature = spanContext.getCallTree().getChildren().get(0).getSignature();
assertTrue(signature, signature.contains("org.stagemonitor.tracing.MonitorRequestsTransformerTest$TestClass.monitorMe"));
final Map<MetricName,Timer> timers = metricRegistry.getTimers();
assertNotNull(timers.keySet().toString(), timers.get(name("response_time_server").tag("request_name", "MonitorRequestsTransformerTest$TestClass#monitorMe").layer("All").build()));
}
@Test
public void testMonitorAsyncMethods() throws Exception {
testClass.asyncMethod();
final SpanContextInformation spanContext = spanCapturingReporter.get();
assertEquals("MonitorRequestsTransformerTest$TestClass#asyncMethod", spanContext.getOperationName());
assertEquals(1, spanContext.getCallTree().getChildren().size());
final String signature = spanContext.getCallTree().getChildren().get(0).getSignature();
assertTrue(signature, signature.contains("org.stagemonitor.tracing.MonitorRequestsTransformerTest$TestClass.asyncMethod"));
final Map<MetricName,Timer> timers = metricRegistry.getTimers();
assertNotNull(timers.keySet().toString(), timers.get(name("response_time_server").tag("request_name", "MonitorRequestsTransformerTest$TestClass#asyncMethod").layer("All").build()));
}
@Test
public void testDontMonitorAnySuperMethod() throws Exception {
testClass.dontMonitorMe();
assertNull(spanCapturingReporter.get());
}
@Test
public void testMonitorRequestsThrowingException() throws Exception {
try {
testClass.monitorThrowException();
fail();
} catch (NullPointerException e) {
// expected
}
assertEquals(NullPointerException.class.getName(), tags.get("exception.class"));
final Map<MetricName,Timer> timers = metricRegistry.getTimers();
assertNotNull(timers.keySet().toString(), timers.get(name("response_time_server").tag("request_name", "MonitorRequestsTransformerTest$TestClass#monitorThrowException").layer("All").build()));
}
@Test
public void testMonitorRequestsAnnonymousInnerClass() throws Exception {
testClass.monitorAnnonymousInnerClass();
final SpanContextInformation spanContext = spanCapturingReporter.get();
assertEquals("MonitorRequestsTransformerTest$TestClass$1#run", spanContext.getOperationName());
assertEquals(1, spanContext.getCallTree().getChildren().size());
final String signature = spanContext.getCallTree().getChildren().get(0).getSignature();
assertTrue(signature, signature.contains("org.stagemonitor.tracing.MonitorRequestsTransformerTest$TestClass$1.run"));
final Map<MetricName,Timer> timers = metricRegistry.getTimers();
assertNotNull(timers.keySet().toString(), timers.get(name("response_time_server").tag("request_name", "MonitorRequestsTransformerTest$TestClass$1#run").layer("All").build()));
}
@Test
public void testMonitorRequestsResolvedAtRuntime() throws Exception {
testClass.resolveNameAtRuntime();
final String operationName = spanCapturingReporter.get().getOperationName();
assertEquals("MonitorRequestsTransformerTest$TestSubClass#resolveNameAtRuntime", operationName);
}
@Test
public void testMonitorStaticMethod() throws Exception {
TestClass.monitorStaticMethod();
final String operationName = spanCapturingReporter.get().getOperationName();
assertEquals("MonitorRequestsTransformerTest$TestClass#monitorStaticMethod", operationName);
}
@Test
public void testMonitorRequestsCustomName() throws Exception {
testClass.doFancyStuff();
final String operationName = spanCapturingReporter.get().getOperationName();
assertEquals("My Cool Method", operationName);
}
private static abstract class SuperAbstractTestClass {
@MonitorRequests
public abstract int monitorMe(int i) throws Exception;
}
private static abstract class AbstractTestClass extends SuperAbstractTestClass{
public abstract void dontMonitorMe() throws Exception;
}
private static class TestClass extends AbstractTestClass {
@MonitorRequests
public int monitorMe(int i) throws Exception {
return i;
}
@Override
public void dontMonitorMe() throws Exception {
}
@MonitorRequests(resolveNameAtRuntime = true)
public void resolveNameAtRuntime() throws Exception {
}
@MonitorRequests
public static void monitorStaticMethod() {
}
@MonitorRequests(requestName = "My Cool Method")
public void doFancyStuff() throws Exception {
}
public void monitorAnnonymousInnerClass() {
new Runnable() {
@Override
@MonitorRequests
public void run() {
}
}.run();
}
@MonitorRequests
public int monitorThrowException() throws Exception {
throw null;
}
@Async
public void asyncMethod() {
}
}
private static class TestSubClass extends TestClass {
}
@Test
public void testClassLevelAnnotationClass() throws Exception {
testClassLevelAnnotationClass.monitorMe("1");
testClassLevelAnnotationClass.dontMonitorMe();
final SpanContextInformation spanContext = spanCapturingReporter.get();
// either parameters.arg0 or parameters.s
assertEquals("1", getTagsStartingWith(tags, SpanUtils.PARAMETERS_PREFIX).iterator().next());
assertEquals("MonitorRequestsTransformerTest$TestClassLevelAnnotationClass#monitorMe", spanContext.getOperationName());
assertEquals(1, spanContext.getCallTree().getChildren().size());
final String signature = spanContext.getCallTree().getChildren().get(0).getSignature();
assertTrue(signature, signature.contains("org.stagemonitor.tracing.MonitorRequestsTransformerTest$TestClassLevelAnnotationClass.monitorMe"));
final Map<MetricName, Timer> timers = metricRegistry.getTimers();
assertNotNull(timers.keySet().toString(), timers.get(name("response_time_server").tag("request_name", "MonitorRequestsTransformerTest$TestClassLevelAnnotationClass#monitorMe").layer("All").build()));
}
@MonitorRequests
private static class SuperTestClassLevelAnnotationClass {
}
private static class TestClassLevelAnnotationClass extends SuperTestClassLevelAnnotationClass {
public String monitorMe(String s) throws Exception {
return s;
}
private int dontMonitorMe() throws Exception {
return 0;
}
}
private List<Object> getTagsStartingWith(Map<String, Object> tags, String prefix) {
List<Object> tagValuesStartingWith = new ArrayList<Object>();
for (Map.Entry<String, Object> entry : tags.entrySet()) {
if (entry.getKey().startsWith(prefix)) {
tagValuesStartingWith.add(entry.getValue());
}
}
return tagValuesStartingWith;
}
}