Clover Coverage Report - jmxmonitor 1.0.2
Coverage timestamp: Wed Feb 10 2010 07:36:51 GMT
../../../../../img/srcFileCovDistChart8.png 50% of files have more coverage
109   336   41   5.74
20   239   0.38   9.5
19     2.16  
2    
 
  MonitoringGroup       Line # 49 102 0% 34 31 76.9% 0.76865673
  MonitoringGroup.MonitorUrlHolder       Line # 303 7 0% 7 6 57.1% 0.5714286
 
  (2)
 
1    /*
2    * Copyright 2009 Ben Gidley
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 uk.co.gidley.jmxmonitor.monitoring;
18   
19    import org.apache.commons.configuration.CompositeConfiguration;
20    import org.apache.commons.configuration.ConfigurationException;
21    import org.apache.commons.configuration.PropertiesConfiguration;
22    import org.slf4j.Logger;
23    import org.slf4j.LoggerFactory;
24    import uk.co.gidley.jmxmonitor.services.InitialisationException;
25    import uk.co.gidley.jmxmonitor.services.ThreadManager;
26   
27    import javax.management.MBeanServerConnection;
28    import javax.management.MalformedObjectNameException;
29    import javax.management.ObjectName;
30    import javax.management.remote.JMXConnector;
31    import javax.management.remote.JMXConnectorFactory;
32    import javax.management.remote.JMXServiceURL;
33    import javax.script.ScriptEngine;
34    import javax.script.ScriptEngineManager;
35    import javax.script.ScriptException;
36    import java.io.File;
37    import java.io.IOException;
38    import java.net.MalformedURLException;
39    import java.util.ArrayList;
40    import java.util.Date;
41    import java.util.HashMap;
42    import java.util.Iterator;
43    import java.util.List;
44    import java.util.Map;
45   
46    /**
47    * A monitoring group combines a set of monitors and expressions to output data to a logger
48    */
 
49    public class MonitoringGroup implements Runnable {
50   
51    private boolean stopping = false;
52    private long interval;
53    private Long lastRun;
54    private Map<String, MonitorUrlHolder> monitorUrlHolders = new HashMap<String, MonitorUrlHolder>();
55    private CompositeConfiguration monitorsConfiguration = new CompositeConfiguration();
56    private CompositeConfiguration expressionsConfiguration = new CompositeConfiguration();
57    private String name;
58   
59    private boolean alive = true;
60    private static final String URL = ".url";
61    private List<String> expressions = new ArrayList<String>();
62    private ScriptEngineManager scriptEngineManager;
63   
 
64  3 toggle public MonitoringGroup() {
65  3 monitorsConfiguration.setThrowExceptionOnMissing(true);
66  3 expressionsConfiguration.setThrowExceptionOnMissing(true);
67  3 scriptEngineManager = new ScriptEngineManager();
68   
69   
70    }
71   
 
72  0 toggle public String getName() {
73  0 return name;
74    }
75   
 
76  0 toggle public void setName(String name) {
77  0 this.name = name;
78    }
79   
80    private Logger outputLogger;
81    private static final Logger logger = LoggerFactory.getLogger(MonitoringGroup.class);
82    private static final String MONITORING_GROUP = "monitoringGroup.";
83   
84    /**
85    * Called to initialise the monitoring group. The group should use this to construct expensive objects, validate
86    * configuration and prepare to run.
87    *
88    * @param monitorsConfigurationFile The monitors file
89    * @param expressionsConfigurationFile The expression file
90    * @param intervalInMilliseconds The interval to poll in milliseconds
91    */
 
92  3 toggle public void initialise(String name, File monitorsConfigurationFile, File expressionsConfigurationFile,
93    long intervalInMilliseconds) throws InitialisationException {
94  3 try {
95  3 interval = intervalInMilliseconds;
96  3 this.name = name;
97  3 outputLogger = LoggerFactory.getLogger(MONITORING_GROUP + name);
98   
99  3 monitorsConfiguration.addConfiguration(new PropertiesConfiguration(monitorsConfigurationFile));
100  3 expressionsConfiguration.addConfiguration(new PropertiesConfiguration(expressionsConfigurationFile));
101   
102  3 initialiseMonitors();
103  3 initialiseExpressions();
104    } catch (ConfigurationException e) {
105  0 logger.error("{}", e);
106  0 throw new InitialisationException(e);
107    } catch (MalformedObjectNameException e) {
108  0 logger.error("{}", e);
109  0 throw new InitialisationException(e);
110    } catch (MalformedURLException e) {
111  0 logger.error("{}", e);
112  0 throw new InitialisationException(e);
113    }
114    }
115   
 
116  3 toggle private void initialiseExpressions() {
117   
118  3 Iterator<String> keys = expressionsConfiguration.getKeys();
119  7 while (keys.hasNext()) {
120  4 String key = keys.next();
121  4 String expression = expressionsConfiguration.getString(key);
122  4 expressions.add(expression);
123    }
124   
125   
126    }
127   
 
128  3 toggle private void initialiseMonitors() throws MalformedObjectNameException, MalformedURLException {
129  3 List<String> monitorUrls = monitorsConfiguration.getList(ThreadManager.PROPERTY_PREFIX + "connections");
130  3 for (String monitorUrlKey : monitorUrls) {
131  3 monitorUrlHolders.put(monitorUrlKey, new MonitorUrlHolder(monitorUrlKey));
132  3 initialiseMonitorUrl(monitorUrlKey, monitorsConfiguration);
133    }
134    }
135   
136    /**
137    * Initialise the monitor. If possible we start the JMX connection now. If not we create a placeholder.
138    *
139    * @param monitorUrlKey
140    * @param monitorsConfiguration
141    * @throws MalformedObjectNameException
142    * @throws MalformedURLException
143    */
 
144  3 toggle private void initialiseMonitorUrl(String monitorUrlKey,
145    CompositeConfiguration monitorsConfiguration) throws MalformedObjectNameException, MalformedURLException {
146  3 logger.debug("Initialising Monitor Connection {}", monitorUrlKey);
147   
148  3 String url = monitorsConfiguration.getString(ThreadManager.PROPERTY_PREFIX + monitorUrlKey + URL);
149  3 try {
150    // Create JMX connection
151  3 JMXServiceURL serviceUrl = new JMXServiceURL(url);
152  3 JMXConnector jmxc = JMXConnectorFactory.connect(serviceUrl, null);
153  3 logger.debug("JMX connection made {}", jmxc);
154  3 MonitoringGroup.MonitorUrlHolder monitorUrlHolder = monitorUrlHolders.get(monitorUrlKey);
155  3 monitorUrlHolder.setmBeanServerConnection(jmxc.getMBeanServerConnection());
156  3 monitorUrlHolder.getMonitors().clear();
157   
158    // Parse monitors inside this
159  3 List<String> loadedMonitors = new ArrayList<String>();
160  3 Iterator<String> monitorKeys = monitorsConfiguration.getKeys(ThreadManager.PROPERTY_PREFIX + monitorUrlKey);
161  16 while (monitorKeys.hasNext()) {
162  13 String key = monitorKeys.next();
163  13 if (!key.endsWith(URL)) {
164  10 String monitorName = key.substring(
165    ThreadManager.PROPERTY_PREFIX.length() + monitorUrlKey.length() + 1,
166    key.lastIndexOf("."));
167    // Only load each on once (there will be n keys)
168  10 if (!loadedMonitors.contains(monitorName)) {
169  4 constructMonitor(monitorUrlKey, monitorsConfiguration, monitorUrlHolder, monitorName);
170  4 loadedMonitors.add(monitorName);
171    }
172    }
173    }
174    } catch (IOException e) {
175  0 if (e instanceof MalformedURLException) {
176  0 throw (MalformedURLException) e;
177    }
178  0 logger.warn("Unable to connect to {}, {}", monitorUrlKey, e);
179    }
180    }
181   
 
182  4 toggle private void constructMonitor(String monitorUrlKey, CompositeConfiguration monitorsConfiguration,
183    MonitorUrlHolder monitorUrlHolder, String monitorName) throws MalformedObjectNameException {
184   
185    // Value of key is java.lang:type=Memory/HeapMemoryUsage!Heap
186  4 String keyPrefix = ThreadManager.PROPERTY_PREFIX + monitorUrlKey + "." + monitorName;
187  4 String objectName = monitorsConfiguration.getString(
188    keyPrefix + ".objectName");
189  4 String attribute = monitorsConfiguration.getString(
190    keyPrefix + ".attribute");
191  4 String discriminator = monitorsConfiguration.getString(keyPrefix + ".discriminator", null);
192  4 Monitor monitor;
193  4 if (discriminator == null) {
194  2 monitor = new SimpleJmxMonitor(monitorName, new ObjectName(objectName), attribute,
195    monitorUrlHolder.getmBeanServerConnection());
196    } else {
197  2 monitor = new DiscriminatingJmxMonitor(monitorName,
198    new ObjectName(objectName), attribute, discriminator, monitorUrlHolder.getmBeanServerConnection());
199    }
200  4 monitorUrlHolder.getMonitors().add(monitor);
201    }
202   
203    /**
204    * The group should stop at the next opportunity. At most within 5 seconds.
205    */
 
206  1 toggle public void stop() {
207  1 stopping = true;
208    }
209   
210   
211    /**
212    * The group should respond true unless it knows it has failed
213    */
 
214  17 toggle public boolean isAlive() {
215  17 return alive;
216    }
217   
218   
219    /**
220    * Start monitoring (as a thread) return when stopped
221    */
 
222  3 toggle @Override
223    public void run() {
224  3 try {
225  24 while (!stopping) {
226   
227  23 long currentRun = new Date().getTime();
228  23 logger.debug("Checking interval for {} at {}", name, currentRun);
229   
230  23 ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(
231    "JavaScript");
232  23 if (lastRun == null || lastRun + interval < currentRun) {
233  5 logger.debug("Running interval for {} at {}", name, currentRun);
234   
235    // Run Monitors
236  5 for (String monitorUrlHolderKey : monitorUrlHolders.keySet()) {
237  5 MonitorUrlHolder monitorUrlHolder = monitorUrlHolders.get(monitorUrlHolderKey);
238   
239  5 if (isFailed(monitorUrlHolder)) {
240  0 logger.debug("Reinitialising monitors as they are not connected");
241  0 initialiseMonitorUrl(monitorUrlHolder.getUrl(), monitorsConfiguration);
242    } else {
243  5 logger.debug("Executing Monitors");
244  5 Map<String, Object> results = new HashMap<String, Object>();
245  5 for (Monitor monitor : monitorUrlHolder.getMonitors()) {
246  6 try {
247  6 results.put(monitor.getName(), monitor.getReading());
248    } catch (ReadingFailedException e) {
249  0 results.put(monitor.getName(), e);
250  0 logger.error("{}", e);
251    }
252    }
253   
254  5 for (String key : results.keySet()) {
255  6 scriptEngine.put(key, results.get(key));
256    }
257    }
258    }
259  5 for (String expression : expressions) {
260  7 try {
261  7 Object output = scriptEngine.eval(expression);
262  7 outputLogger.info("{}", output);
263    } catch (ScriptException e) {
264  0 logger.warn("Script Error {}", e);
265    }
266    }
267    // Run and output expressions
268  5 lastRun = currentRun;
269    }
270  23 Thread.sleep(4000);
271    }
272    } catch (InterruptedException e) {
273  0 logger.info("Interrupted", e);
274    } catch (MalformedObjectNameException e) {
275  0 logger.error("{}", e);
276  0 throw new RuntimeException(e);
277    } catch (MalformedURLException e) {
278  0 logger.error("{}", e);
279  0 throw new RuntimeException(e);
280    } finally {
281    // Tidy up all monitors / expressions IF possible
282  1 alive = false;
283   
284    }
285   
286    }
287   
 
288  5 toggle private boolean isFailed(MonitorUrlHolder monitorUrlHolder) {
289  5 if (monitorUrlHolder == null || monitorUrlHolder.getmBeanServerConnection() == null) {
290  0 return true;
291    }
292  5 try {
293  5 monitorUrlHolder.getmBeanServerConnection().getMBeanCount();
294    } catch (IOException e) {
295  0 logger.warn("Connection to JMX not functioning {}", e);
296  0 monitorUrlHolder.setmBeanServerConnection(null);
297  0 return true;
298    }
299   
300  5 return false;
301    }
302   
 
303    private class MonitorUrlHolder {
304    private String url;
305    private List<Monitor> monitors = new ArrayList<Monitor>();
306    private MBeanServerConnection mBeanServerConnection;
307   
 
308  3 toggle private MonitorUrlHolder(String url) {
309  3 this.url = url;
310    }
311   
 
312  0 toggle public String getUrl() {
313  0 return url;
314    }
315   
 
316  0 toggle public void setUrl(String url) {
317  0 this.url = url;
318    }
319   
 
320  12 toggle public List<Monitor> getMonitors() {
321  12 return monitors;
322    }
323   
 
324  0 toggle public void setMonitors(List<Monitor> monitors) {
325  0 this.monitors = monitors;
326    }
327   
 
328  14 toggle public MBeanServerConnection getmBeanServerConnection() {
329  14 return mBeanServerConnection;
330    }
331   
 
332  3 toggle public void setmBeanServerConnection(MBeanServerConnection mBeanServerConnection) {
333  3 this.mBeanServerConnection = mBeanServerConnection;
334    }
335    }
336    }