Skip to content

Commit 51e4b07

Browse files
committed
JamonPerformanceMonitorInterceptor tracks exceptions as well (consistent with JAMon's other interceptors)
Issue: SPR-12068
1 parent c65a82a commit 51e4b07

File tree

3 files changed

+113
-6
lines changed

3 files changed

+113
-6
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ project("spring-aop") {
407407
compile("aopalliance:aopalliance:1.0")
408408
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
409409
optional("commons-pool:commons-pool:1.6")
410-
optional("com.jamonapi:jamon:2.76")
410+
optional("com.jamonapi:jamon:2.78")
411411
}
412412
}
413413

spring-aop/src/main/java/org/springframework/aop/interceptor/JamonPerformanceMonitorInterceptor.java

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,21 +16,26 @@
1616

1717
package org.springframework.aop.interceptor;
1818

19+
import com.jamonapi.MonKey;
20+
import com.jamonapi.MonKeyImp;
1921
import com.jamonapi.Monitor;
2022
import com.jamonapi.MonitorFactory;
23+
import com.jamonapi.utils.Misc;
2124
import org.aopalliance.intercept.MethodInvocation;
2225
import org.apache.commons.logging.Log;
2326

2427
/**
25-
* Performance monitor interceptor that uses <b>JAMon</b> library
26-
* to perform the performance measurement on the intercepted method
27-
* and output the stats.
28+
* Performance monitor interceptor that uses <b>JAMon</b> library to perform the
29+
* performance measurement on the intercepted method and output the stats.
30+
* In addition, it tracks/counts exceptions thrown by the intercepted method.
31+
* The stack traces can be viewed in the JAMon web application.
2832
*
2933
* <p>This code is inspired by Thierry Templier's blog.
3034
*
3135
* @author Dmitriy Kopylenko
3236
* @author Juergen Hoeller
3337
* @author Rob Harrop
38+
* @author Steve Souza
3439
* @since 1.1.3
3540
* @see com.jamonapi.MonitorFactory
3641
* @see PerformanceMonitorInterceptor
@@ -103,10 +108,16 @@ protected boolean isInterceptorEnabled(MethodInvocation invocation, Log logger)
103108
@Override
104109
protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable {
105110
String name = createInvocationTraceName(invocation);
106-
Monitor monitor = MonitorFactory.start(name);
111+
MonKey key = new MonKeyImp(name, name, "ms.");
112+
113+
Monitor monitor = MonitorFactory.start(key);
107114
try {
108115
return invocation.proceed();
109116
}
117+
catch (Throwable ex) {
118+
trackException(key, ex);
119+
throw ex;
120+
}
110121
finally {
111122
monitor.stop();
112123
if (!this.trackAllInvocations || isLogEnabled(logger)) {
@@ -115,4 +126,19 @@ protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throw
115126
}
116127
}
117128

129+
/**
130+
* Count the thrown exception and put the stack trace in the details portion of the key.
131+
* This will allow the stack trace to be viewed in the JAMon web application.
132+
*/
133+
protected void trackException(MonKey key, Throwable ex) {
134+
String stackTrace = "stackTrace=" + Misc.getExceptionTrace(ex);
135+
key.setDetails(stackTrace);
136+
137+
// Specific exception counter. Example: java.lang.RuntimeException
138+
MonitorFactory.add(new MonKeyImp(ex.getClass().getName(), stackTrace, "Exception"), 1);
139+
140+
// General exception counter which is a total for all exceptions thrown
141+
MonitorFactory.add(new MonKeyImp(MonitorFactory.EXCEPTIONS_LABEL, stackTrace, "Exception"), 1);
142+
}
143+
118144
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 2002-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.aop.interceptor;
18+
19+
import com.jamonapi.MonitorFactory;
20+
import org.aopalliance.intercept.MethodInvocation;
21+
import org.apache.commons.logging.Log;
22+
import org.junit.After;
23+
import org.junit.Before;
24+
import org.junit.Test;
25+
26+
import static org.junit.Assert.*;
27+
import static org.mockito.BDDMockito.*;
28+
29+
/**
30+
* @author Steve Souza
31+
* @since 4.1
32+
*/
33+
public class JamonPerformanceMonitorInterceptorTests {
34+
35+
private JamonPerformanceMonitorInterceptor interceptor = new JamonPerformanceMonitorInterceptor();
36+
37+
private MethodInvocation mi = mock(MethodInvocation.class);
38+
39+
private Log log = mock(Log.class);
40+
41+
42+
@Before
43+
public void setUp() {
44+
MonitorFactory.reset();
45+
}
46+
47+
@After
48+
public void tearDown() {
49+
MonitorFactory.reset();
50+
}
51+
52+
53+
@Test
54+
public void testInvokeUnderTraceWithNormalProcessing() throws Throwable {
55+
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
56+
57+
interceptor.invokeUnderTrace(mi, log);
58+
59+
assertEquals("jamon must track the method being invoked", 1, MonitorFactory.getNumRows());
60+
assertTrue("The jamon report must contain the toString method that was invoked", MonitorFactory.getReport().contains("toString"));
61+
}
62+
63+
@Test
64+
public void testInvokeUnderTraceWithExceptionTracking() throws Throwable {
65+
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
66+
given(mi.proceed()).willThrow(new IllegalArgumentException());
67+
68+
try {
69+
interceptor.invokeUnderTrace(mi, log);
70+
fail("Must have propagated the IllegalArgumentException");
71+
}
72+
catch (IllegalArgumentException expected) {
73+
}
74+
75+
assertEquals("Monitors must exist for the method invocation and 2 exceptions", 3, MonitorFactory.getNumRows());
76+
assertTrue("The jamon report must contain the toString method that was invoked", MonitorFactory.getReport().contains("toString"));
77+
assertTrue("The jamon report must contain the generic exception: " + MonitorFactory.EXCEPTIONS_LABEL, MonitorFactory.getReport().contains(MonitorFactory.EXCEPTIONS_LABEL));
78+
assertTrue("The jamon report must contain the specific exception: IllegalArgumentException'", MonitorFactory.getReport().contains("IllegalArgumentException"));
79+
}
80+
81+
}

0 commit comments

Comments
 (0)