ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/server/uk/org/iscream/cms/server/client/monitors/Disk__Monitor.java
Revision: 1.23
Committed: Thu Feb 10 17:36:00 2005 UTC (19 years, 3 months ago) by tdb
Branch: MAIN
CVS Tags: HEAD
Changes since 1.22: +5 -5 lines
Log Message:
Commit various fixes from skel (Daniel Piddock):

CMS Server:
 - DiskMonitor was overflowing due to using an int variable for the
   inode count. Upped to a long.
 - Updated URL to iscream cms javadoc

RRD graphing:
 - added uptime logging and graph creation
 - diskio - Cope with modern linux device paths
   (eg "ide/host0/bus0/target0/lun0/disc") by replacing / with hex
 - diskio - Cope with windows device paths (eg "0 C: D:") by
   replacing : and space with hex
 - disk - Cope with windows mount points (eg C:\) by
   replacing : and \ with hex
 - net - Cope with windows network "device names". Basically
   the whole network card as it appears in Device Manager,
   not "Local Area Connection"
 - Include total processes (for winhost)

Also modified the PHP code to catch up. Patch slightly modified from that
submitted, but only minor alterations.

Thanks skel!

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org
4 * Copyright (C) 2000-2002 i-scream
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 //---PACKAGE DECLARATION---
22 package uk.org.iscream.cms.server.client.monitors;
23
24 //---IMPORTS---
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Set;
28 import java.util.Iterator;
29 import java.text.NumberFormat;
30 import uk.org.iscream.cms.server.client.*;
31 import uk.org.iscream.cms.server.core.*;
32 import uk.org.iscream.cms.util.*;
33 import uk.org.iscream.cms.server.componentmanager.*;
34
35 /**
36 * This Monitor watches the Disks for all machines
37 *
38 * @author $Author: tdb $
39 * @version $Id: Disk__Monitor.java,v 1.22 2004/08/01 10:40:45 tdb Exp $
40 */
41 public class Disk__Monitor extends MonitorSkeleton {
42
43 //---FINAL ATTRIBUTES---
44
45 /**
46 * The current CVS revision of this class
47 */
48 public final String REVISION = "$Revision: 1.22 $";
49
50 /**
51 * A description of this monitor
52 */
53 public final String DESC = "Monitors all host disks.";
54
55 //---STATIC METHODS---
56
57 //---CONSTRUCTORS---
58
59 //---PUBLIC METHODS---
60
61 /**
62 * Analyse a packet of data, and generate an alert if
63 * necessary.
64 *
65 * @param packet the XMLPacket to analyse
66 */
67 public void analysePacket(XMLPacket packet) {
68 String source = packet.getParam("packet.attributes.machine_name");
69 if(!checkBooleanConfig("Host." + source, "Monitor." + _name + ".enable")) {
70 return;
71 }
72 if (!_hosts.containsKey(source)) {
73 _hosts.put(source, new HashMap());
74 }
75 if (!_hostsInode.containsKey(source)) {
76 _hostsInode.put(source, new HashMap());
77 }
78
79 HashMap diskRegisters = (HashMap) _hosts.get(source);
80 HashMap diskInodeRegisters = (HashMap) _hostsInode.get(source);
81
82 // key prefix
83 String keyPrefix = "packet.disk.p";
84
85 // a temporary holder for all the disk attributes we find
86 HashSet disks = new HashSet();
87
88 // unfortunatly we need to check the whole packet
89 // to find the disks, and then get the data attributes
90 Set packetSet = packet.getSet();
91 Iterator i = packetSet.iterator();
92 while (i.hasNext()) {
93 String dataKey = (String) i.next();
94 if(dataKey.startsWith(keyPrefix)) {
95 // pos is after "packet.disk.p"
96 int pos = keyPrefix.length();
97 String diskNumber = dataKey.substring(pos, dataKey.indexOf('.', pos));
98 String thisDisk = keyPrefix.concat(diskNumber);
99
100 if(!disks.contains(thisDisk)) {
101 // add the disk to our list
102 disks.add(thisDisk);
103
104 // device
105 String device = packet.getParam(thisDisk + ".attributes.name");
106 // mount point
107 String mount = packet.getParam(thisDisk + ".attributes.mount");
108
109 // these next two will be used to calculate the %age
110 // total
111 String total = packet.getParam(thisDisk + ".attributes.total");
112 // available
113 String avail = packet.getParam(thisDisk + ".attributes.avail");
114
115 String totalInodes = packet.getParam(thisDisk + ".attributes.totalinodes");
116 String availInodes = packet.getParam(thisDisk + ".attributes.freeinodes");
117
118 // *** now process this disk ***
119
120 // check if we've seen this disk before on a previous run
121 // if not, we need to create a register for it
122 // nb. use the mount as the key as this is unlikely to change,
123 // unlike diskNumber which could easily change
124 // (diskNumber is based on the order of df's output!)
125 if(!diskRegisters.containsKey(mount)) {
126 diskRegisters.put(mount, new Register(source, _name, mount));
127 }
128 if(!diskInodeRegisters.containsKey(mount)) {
129 diskInodeRegisters.put(mount, new Register(source, _nameInode, mount));
130 }
131
132 // get the register for this disk
133 Register reg = (Register) diskRegisters.get(mount);
134 Register regInode = (Register) diskInodeRegisters.get(mount);
135
136 // get the packet data
137 double diskTotal, diskAvail;
138 long diskInodeTotal, diskInodeAvail;
139 try {
140
141 if(total==null || avail==null || totalInodes==null || availInodes==null) {
142 throw new NumberFormatException("Disk data invalid");
143 }
144 diskTotal = Double.parseDouble(total);
145 diskAvail = Double.parseDouble(avail);
146 diskInodeTotal = Long.parseLong(totalInodes);
147 diskInodeAvail = Long.parseLong(availInodes);
148 } catch (NumberFormatException e) {
149 _logger.write(this.toString(), Logger.WARNING, "Received packet from "+source+" with bad disk information: "+e);
150 // don't try to continue and process, try next disk
151 break;
152 }
153
154 boolean useValue = false;
155 boolean useValueInode = false;
156 try {
157 // try looking for a mount-point specific thresholdMeasure first
158 String option = _cp.getProperty("Host." + source, "Monitor." + _name + "." + mount + ".thresholdMeasure");
159 if (option.equals("VALUE")) {
160 useValue = true;
161 }
162 option = _cp.getProperty("Host." + source, "Monitor." + _nameInode + "." + mount + ".thresholdMeasure");
163 if (option.equals("VALUE")) {
164 useValueInode = true;
165 }
166 } catch (PropertyNotFoundException e) {
167 try {
168 // now look for a more general thresholdMeasure
169 String option = _cp.getProperty("Host." + source, "Monitor." + _name + ".thresholdMeasure");
170 if (option.equals("VALUE")) {
171 useValue = true;
172 }
173 option = _cp.getProperty("Host." + source, "Monitor." + _nameInode + ".thresholdMeasure");
174 if (option.equals("VALUE")) {
175 useValueInode = true;
176 }
177 } catch (PropertyNotFoundException f) {
178 // we default to percentage in any case
179 }
180 }
181
182 // this bit determines if the disk check is a % check
183 // or a byte check
184 String type;
185 double curValue;
186 int newThreshold;
187 if(useValue) {
188 // byte disk available
189 curValue = diskAvail;
190 // negate check
191 newThreshold = checkAttributeThreshold(curValue, reg, true);
192 type = "bytes";
193 } else {
194 // % disk in use
195 curValue = (1 - ((double)diskAvail / (double)diskTotal)) * 100;
196 // normal check
197 newThreshold = checkAttributeThreshold(curValue, reg, false);
198 type = "%";
199 }
200
201 String typeInode;
202 double curValueInode;
203 int newThresholdInode;
204 if(useValueInode) {
205 // inodes available
206 curValueInode = diskInodeAvail;
207 // negate check
208 newThresholdInode = checkAttributeThreshold(curValueInode, regInode, true);
209 typeInode = "count";
210 } else {
211 // % inodes in use
212 curValueInode = (1 - ((double)diskInodeAvail / (double)diskInodeTotal)) * 100;
213 // normal check
214 newThresholdInode = checkAttributeThreshold(curValueInode, regInode, false);
215 typeInode = "%";
216 }
217
218 // format the diskInUse to a String
219 NumberFormat nf = NumberFormat.getInstance();
220 nf.setMaximumFractionDigits(2);
221 nf.setMinimumFractionDigits(2);
222 String strCurValue = nf.format(curValue);
223 String strCurValueInode = nf.format(curValueInode);
224
225 // say which disk had the problem
226 String attributeName = "Disk in use " + type + " on " + mount + " (" + device + ")";
227 String attributeNameInode = "Disk inodes in use " + type + " on " + mount + " (" + device +")";
228
229 processAlert(newThreshold, attributeName, reg, source, strCurValue);
230 processAlert(newThresholdInode, attributeNameInode, regInode, source, strCurValueInode);
231 }
232 }
233 }
234 }
235
236 /**
237 * Overrides the {@link java.lang.Object#toString() Object.toString()}
238 * method to provide clean logging (every class should have this).
239 *
240 * This uses the uk.org.iscream.cms.util.NameFormat class
241 * to format the toString()
242 *
243 * @return the name of this class and its CVS revision
244 */
245 public String toString() {
246 return FormatName.getName(
247 _name,
248 getClass().getName(),
249 REVISION);
250 }
251
252 /**
253 * return the String representation of what the monitor does
254 */
255 public String getDescription(){
256 return DESC;
257 }
258
259 //---PRIVATE METHODS---
260
261 /**
262 * Checks a piece of current data, and returns the
263 * threshold it breaches, if any.
264 *
265 * The option to negate the check can be used in
266 * situations where being *below* the threshold
267 * is an 'alertable' situation. In this specific
268 * case, we'd do this with kb disk checks.
269 *
270 * @param value the current value
271 * @param reg the Register for the host
272 * @param negateCheck whether to negate the check
273 * @return the threshold level breached, if any
274 */
275 private int checkAttributeThreshold(double value, Register reg, boolean negateCheck) {
276 for(int thresholdLevel = Alert.thresholdLevels.length - 1; thresholdLevel >= 0; thresholdLevel--) {
277 if (reg.getThreshold(thresholdLevel) != -1.0) {
278 if(!negateCheck) {
279 // normal check - has the value gone *over* the threshold
280 if(((double) reg.getThreshold(thresholdLevel)) < value) {
281 return thresholdLevel;
282 }
283 }
284 else {
285 // negated check - has the value gone *under* the threshold
286 if(((double) reg.getThreshold(thresholdLevel)) > value) {
287 return thresholdLevel;
288 }
289 }
290 }
291 }
292 return Alert.thresholdNORMAL;
293 }
294
295 //---ACCESSOR/MUTATOR METHODS---
296
297 /**
298 * Returns a reference to a specific Queue for this
299 * monitor. This Queue returns only the data packets
300 * (based on type) that we want too look at.
301 *
302 * @return a reference to a Queue
303 */
304 protected Queue getQueue() {
305 return MonitorManager.getInstance().getDataQueue();
306 }
307
308 //---ATTRIBUTES---
309
310 /**
311 * This is the friendly identifier of the
312 * component this class is running in.
313 * eg, a Filter may be called "filter1",
314 * If this class does not have an owning
315 * component, a name from the configuration
316 * can be placed here. This name could also
317 * be changed to null for utility classes.
318 */
319 private String _name = "Disk";
320
321 /**
322 * Inodes have the name "DiskInode" in the
323 * configuration.
324 */
325 private String _nameInode = "DiskInode";
326
327 /**
328 * A reference to the configuration proxy in use
329 */
330 private ConfigurationProxy _cp = ConfigurationProxy.getInstance();
331
332 /**
333 * A HashMap of Registers (or groups of Registers), one
334 * for each host we're monitoring.
335 */
336 private HashMap _hosts = new HashMap();
337
338 /**
339 * A HashMap of Registers (or groups of Registers), one
340 * for each host we're monitoring (inodes).
341 */
342 private HashMap _hostsInode = new HashMap();
343
344 //---STATIC ATTRIBUTES---
345
346 }