1 package org.apache.fulcrum.yaafi.interceptor.jamon;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.OutputStreamWriter;
25 import java.io.PrintWriter;
26 import java.io.Writer;
27 import java.lang.reflect.Method;
28
29 import org.apache.avalon.framework.activity.Disposable;
30 import org.apache.avalon.framework.activity.Initializable;
31 import org.apache.avalon.framework.configuration.Configuration;
32 import org.apache.avalon.framework.configuration.ConfigurationException;
33 import org.apache.avalon.framework.configuration.Reconfigurable;
34 import org.apache.avalon.framework.thread.ThreadSafe;
35 import org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorContext;
36 import org.apache.fulcrum.yaafi.framework.reflection.Clazz;
37 import org.apache.fulcrum.yaafi.interceptor.baseservice.BaseInterceptorServiceImpl;
38
39
40
41
42
43
44
45
46 public class JamonInterceptorServiceImpl extends BaseInterceptorServiceImpl
47 implements JamonInterceptorService, Reconfigurable, ThreadSafe, Disposable, Initializable {
48
49 private boolean isJamonAvailable;
50
51
52 private File reportFile;
53
54
55 private long reportTimeout;
56
57
58 private boolean reportOnExit;
59
60
61 private long nextReportTimestamp;
62
63
64 private String performanceMonitorClassName;
65
66
67 private Class<?> performanceMonitorClass;
68
69
70 private static final String MONITORFACTORY_CLASSNAME = "com.jamonapi.MonitorFactory";
71
72
73 private static final String DEFAULT_PERFORMANCEMONITOR_CLASSNAME = "org.apache.fulcrum.yaafi.interceptor.jamon.Jamon2PerformanceMonitorImpl";
74
75
76
77
78
79
80
81
82 public JamonInterceptorServiceImpl() {
83 super();
84 }
85
86
87
88
89 public void configure(Configuration configuration) throws ConfigurationException {
90 super.configure(configuration);
91 this.reportTimeout = configuration.getChild("reportTimeout").getValueAsLong(0);
92
93
94 this.performanceMonitorClassName = configuration.getChild("performanceMonitorClassName")
95 .getValue(DEFAULT_PERFORMANCEMONITOR_CLASSNAME);
96
97
98 String reportFileName = configuration.getChild("reportFile").getValue("./jamon.html");
99 this.reportFile = this.makeAbsoluteFile(reportFileName);
100
101
102 this.nextReportTimestamp = System.currentTimeMillis() + this.reportTimeout;
103
104
105 this.reportOnExit = configuration.getChild("reportOnExit").getValueAsBoolean(false);
106 }
107
108
109
110
111 public void initialize() throws Exception {
112 ClassLoader classLoader = this.getClassLoader();
113
114 if (!Clazz.hasClazz(classLoader, MONITORFACTORY_CLASSNAME)) {
115 String msg = "The JamonInterceptorService is disabled since the JAMON classes are not found in the classpath";
116 this.getLogger().warn(msg);
117 this.isJamonAvailable = false;
118 return;
119 }
120
121 if (!Clazz.hasClazz(classLoader, this.performanceMonitorClassName)) {
122 String msg = "The JamonInterceptorService is disabled since the performance monitor class is not found in the classpath";
123 this.getLogger().warn(msg);
124 this.isJamonAvailable = false;
125 return;
126 }
127
128
129 this.performanceMonitorClass = Clazz.getClazz(this.getClassLoader(), this.performanceMonitorClassName);
130
131
132 JamonPerformanceMonitor testMonitor = this.createJamonPerformanceMonitor(null, null, true);
133 if (testMonitor == null) {
134 String msg = "The JamonInterceptorService is disabled since the performance monitor can't be instantiated";
135 this.getLogger().warn(msg);
136 this.isJamonAvailable = false;
137 return;
138 }
139
140 this.getLogger().debug("The JamonInterceptorService is enabled");
141 this.isJamonAvailable = true;
142 }
143
144
145
146
147 public void reconfigure(Configuration configuration) throws ConfigurationException {
148 super.reconfigure(configuration);
149 this.configure(configuration);
150 }
151
152
153
154
155 public void dispose() {
156 if (this.reportOnExit) {
157 this.run();
158 }
159
160 this.reportFile = null;
161 }
162
163
164
165
166
167
168
169
170 public void onEntry(AvalonInterceptorContext interceptorContext) {
171 if (this.isJamonAvailable()) {
172 this.writeReport();
173
174 String serviceShortHand = interceptorContext.getServiceShorthand();
175 Method serviceMethod = interceptorContext.getMethod();
176 boolean isEnabled = this.isServiceMonitored(interceptorContext);
177 JamonPerformanceMonitor monitor = this.createJamonPerformanceMonitor(serviceShortHand, serviceMethod,
178 isEnabled);
179 monitor.start();
180 interceptorContext.getRequestContext().put(this.getServiceName(), monitor);
181 }
182 }
183
184
185
186
187
188 public void onExit(AvalonInterceptorContext interceptorContext, Object result) {
189 if (this.isJamonAvailable()) {
190 JamonPerformanceMonitor monitor;
191 monitor = (JamonPerformanceMonitor) interceptorContext.getRequestContext().remove(this.getServiceName());
192 monitor.stop();
193 }
194 }
195
196
197
198
199
200 public void onError(AvalonInterceptorContext interceptorContext, Throwable t) {
201 if (this.isJamonAvailable()) {
202 JamonPerformanceMonitor monitor;
203 monitor = (JamonPerformanceMonitor) interceptorContext.getRequestContext().remove(this.getServiceName());
204 monitor.stop(t);
205 }
206 }
207
208
209
210
211
212
213 public void run() {
214 this.writeReport(this.reportFile);
215 }
216
217
218
219
220
221
222
223
224 protected final boolean isJamonAvailable() {
225 return this.isJamonAvailable;
226 }
227
228
229
230
231
232
233
234
235
236 @SuppressWarnings("rawtypes")
237 protected JamonPerformanceMonitor createJamonPerformanceMonitor(String serviceName, Method method,
238 boolean isEnabled) {
239 JamonPerformanceMonitor result = null;
240
241 try {
242 Class[] signature = { String.class, Method.class, Boolean.class };
243 Object[] args = { serviceName, method, isEnabled ? Boolean.TRUE : Boolean.FALSE };
244 result = (JamonPerformanceMonitor) Clazz.newInstance(this.performanceMonitorClass, signature, args);
245 return result;
246 } catch (Exception e) {
247 String msg = "Failed to create a performance monitor instance : " + this.performanceMonitorClassName;
248 this.getLogger().error(msg, e);
249 return result;
250 }
251 }
252
253
254
255
256 protected void writeReport() {
257 if (this.reportTimeout > 0) {
258 long currTimestamp = System.currentTimeMillis();
259
260 if (currTimestamp > this.nextReportTimestamp) {
261 this.nextReportTimestamp = currTimestamp + this.reportTimeout;
262 this.writeReport(this.reportFile);
263 }
264 }
265 }
266
267
268
269
270
271
272 protected void writeReport(File reportFile) {
273 PrintWriter printWriter = null;
274
275 if (this.isJamonAvailable()) {
276 try {
277 if (this.getLogger().isDebugEnabled()) {
278 this.getLogger().debug("Writing JAMOM report to " + reportFile.getAbsolutePath());
279 }
280
281
282 Writer w = new OutputStreamWriter(new FileOutputStream(reportFile), "UTF-8");
283 printWriter = new PrintWriter(w);
284
285 JamonPerformanceMonitor monitor = this.createJamonPerformanceMonitor(null, null, true);
286 String report = monitor.createReport();
287 printWriter.write(report);
288 printWriter.close();
289 } catch (Throwable t) {
290 String msg = "Generating the JAMON report failed for " + reportFile.getAbsolutePath();
291 this.getLogger().error(msg, t);
292 } finally {
293 if (printWriter != null) {
294 printWriter.close();
295 }
296 }
297 }
298 }
299 }