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.19
Committed: Sun Mar 9 21:49:13 2003 UTC (21 years, 2 months ago) by tdb
Branch: MAIN
Changes since 1.18: +77 -32 lines
Log Message:
Added support for all the new stuff that ihost provides us with. Ideally
this lot needs to be revamped some day, but for now this brings it all back
up to date.

The biggest change is in the Disk monitor. It wasn't overly neat before,
so I've tidied that up, and also added support for inode monitoring.

Created the DiskIO, NetIO, and Paging monitors to support new types of data
we now handle. The first two sprung from the Disk monitor, whilst the last
is pretty normal.

Configuration has been updated to support the new monitors, although I
don't really have a feel for thresholds for the new types of data.

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org.uk
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.18 2003/02/05 16:43: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.18 $";
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 (!_hosts.containsKey(source)) {
70 _hosts.put(source, new HashMap());
71 }
72 if (!_hostsInode.containsKey(source)) {
73 _hostsInode.put(source, new HashMap());
74 }
75
76 HashMap diskRegisters = (HashMap) _hosts.get(source);
77 HashMap diskInodeRegisters = (HashMap) _hostsInode.get(source);
78
79 // key prefix
80 String keyPrefix = "packet.disk.p";
81
82 // a temporary holder for all the disk attributes we find
83 HashSet disks = new HashSet();
84
85 // unfortunatly we need to check the whole packet
86 // to find the disks, and then get the data attributes
87 Set packetSet = packet.getSet();
88 Iterator i = packetSet.iterator();
89 while (i.hasNext()) {
90 String dataKey = (String) i.next();
91 if(dataKey.startsWith(keyPrefix)) {
92 // pos is after "packet.disk.p"
93 int pos = keyPrefix.length();
94 String diskNumber = dataKey.substring(pos, dataKey.indexOf('.', pos));
95 String thisDisk = keyPrefix.concat(diskNumber);
96
97 if(!disks.contains(thisDisk)) {
98 // add the disk to our list
99 disks.add(thisDisk);
100
101 // device
102 String device = packet.getParam(thisDisk + ".attributes.name");
103 // mount point
104 String mount = packet.getParam(thisDisk + ".attributes.mount");
105
106 // these next two will be used to calculate the %age
107 // total
108 String total = packet.getParam(thisDisk + ".attributes.total");
109 // available
110 String avail = packet.getParam(thisDisk + ".attributes.avail");
111
112 String totalInodes = packet.getParam(thisDisk + ".attributes.totalinodes");
113 String availInodes = packet.getParam(thisDisk + ".attributes.freeinodes");
114
115 // *** now process this disk ***
116
117 // check if we've seen this disk before on a previous run
118 // if not, we need to create a register for it
119 // nb. use the mount as the key as this is unlikely to change,
120 // unlike diskNumber which could easily change
121 // (diskNumber is based on the order of df's output!)
122 if(!diskRegisters.containsKey(mount)) {
123 diskRegisters.put(mount, new Register(source, _name, mount));
124 }
125 if(!diskInodeRegisters.containsKey(mount)) {
126 diskInodeRegisters.put(mount, new Register(source, _nameInode, mount));
127 }
128
129 // get the register for this disk
130 Register reg = (Register) diskRegisters.get(mount);
131 Register regInode = (Register) diskInodeRegisters.get(mount);
132
133 // get the packet data
134 double diskTotal, diskAvail;
135 int diskInodeTotal, diskInodeAvail;
136 try {
137
138 if(total==null || avail==null || totalInodes==null || availInodes==null) {
139 throw new NumberFormatException("Disk data invalid");
140 }
141 diskTotal = Double.parseDouble(total);
142 diskAvail = Double.parseDouble(avail);
143 diskInodeTotal = Integer.parseInt(totalInodes);
144 diskInodeAvail = Integer.parseInt(availInodes);
145 } catch (NumberFormatException e) {
146 _logger.write(this.toString(), Logger.WARNING, "Received packet from "+source+" with bad disk information: "+e);
147 // don't try to continue and process, try next disk
148 break;
149 }
150
151 boolean useValue = false;
152 boolean useValueInode = false;
153 try {
154 // try looking for a mount-point specific thresholdMeasure first
155 String option = _cp.getProperty("Host." + source, "Monitor." + _name + "." + mount + ".thresholdMeasure");
156 if (option.equals("VALUE")) {
157 useValue = true;
158 }
159 option = _cp.getProperty("Host." + source, "Monitor." + _nameInode + "." + mount + ".thresholdMeasure");
160 if (option.equals("VALUE")) {
161 useValueInode = true;
162 }
163 } catch (PropertyNotFoundException e) {
164 try {
165 // now look for a more general thresholdMeasure
166 String option = _cp.getProperty("Host." + source, "Monitor." + _name + ".thresholdMeasure");
167 if (option.equals("VALUE")) {
168 useValue = true;
169 }
170 option = _cp.getProperty("Host." + source, "Monitor." + _nameInode + ".thresholdMeasure");
171 if (option.equals("VALUE")) {
172 useValueInode = true;
173 }
174 } catch (PropertyNotFoundException f) {
175 // we default to percentage in any case
176 }
177 }
178
179 // this bit determines if the disk check is a % check
180 // or a byte check
181 String type;
182 double curValue;
183 int newThreshold;
184 if(useValue) {
185 // byte disk available
186 curValue = diskAvail;
187 // negate check
188 newThreshold = checkAttributeThreshold(curValue, reg, true);
189 type = "bytes";
190 } else {
191 // % disk in use
192 curValue = (1 - ((double)diskAvail / (double)diskTotal)) * 100;
193 // normal check
194 newThreshold = checkAttributeThreshold(curValue, reg, false);
195 type = "%";
196 }
197
198 String typeInode;
199 double curValueInode;
200 int newThresholdInode;
201 if(useValueInode) {
202 // inodes available
203 curValueInode = diskInodeAvail;
204 // negate check
205 newThresholdInode = checkAttributeThreshold(curValueInode, regInode, true);
206 typeInode = "count";
207 } else {
208 // % inodes in use
209 curValueInode = (1 - ((double)diskInodeAvail / (double)diskInodeTotal)) * 100;
210 // normal check
211 newThresholdInode = checkAttributeThreshold(curValueInode, regInode, false);
212 typeInode = "%";
213 }
214
215 // format the diskInUse to a String
216 NumberFormat nf = NumberFormat.getInstance();
217 nf.setMaximumFractionDigits(2);
218 nf.setMinimumFractionDigits(2);
219 String strCurValue = nf.format(curValue);
220 String strCurValueInode = nf.format(curValueInode);
221
222 // say which disk had the problem
223 String attributeName = "Disk in use " + type + " on " + mount + " (" + device + ")";
224 String attributeNameInode = "Disk inodes in use " + type + " on " + mount + " (" + device +")";
225
226 processAlert(newThreshold, attributeName, reg, source, strCurValue);
227 processAlert(newThresholdInode, attributeNameInode, regInode, source, strCurValueInode);
228 }
229 }
230 }
231 }
232
233 /**
234 * Overrides the {@link java.lang.Object#toString() Object.toString()}
235 * method to provide clean logging (every class should have this).
236 *
237 * This uses the uk.org.iscream.cms.util.NameFormat class
238 * to format the toString()
239 *
240 * @return the name of this class and its CVS revision
241 */
242 public String toString() {
243 return FormatName.getName(
244 _name,
245 getClass().getName(),
246 REVISION);
247 }
248
249 /**
250 * return the String representation of what the monitor does
251 */
252 public String getDescription(){
253 return DESC;
254 }
255
256 //---PRIVATE METHODS---
257
258 /**
259 * Checks a piece of current data, and returns the
260 * threshold it breaches, if any.
261 *
262 * The option to negate the check can be used in
263 * situations where being *below* the threshold
264 * is an 'alertable' situation. In this specific
265 * case, we'd do this with kb disk checks.
266 *
267 * @param value the current value
268 * @param reg the Register for the host
269 * @param negateCheck whether to negate the check
270 * @return the threshold level breached, if any
271 */
272 private int checkAttributeThreshold(double value, Register reg, boolean negateCheck) {
273 for(int thresholdLevel = Alert.thresholdLevels.length - 1; thresholdLevel >= 0; thresholdLevel--) {
274 if (reg.getThreshold(thresholdLevel) != -1.0) {
275 if(!negateCheck) {
276 // normal check - has the value gone *over* the threshold
277 if(((double) reg.getThreshold(thresholdLevel)) < value) {
278 return thresholdLevel;
279 }
280 }
281 else {
282 // negated check - has the value gone *under* the threshold
283 if(((double) reg.getThreshold(thresholdLevel)) > value) {
284 return thresholdLevel;
285 }
286 }
287 }
288 }
289 return Alert.thresholdNORMAL;
290 }
291
292 //---ACCESSOR/MUTATOR METHODS---
293
294 /**
295 * Returns a reference to a specific Queue for this
296 * monitor. This Queue returns only the data packets
297 * (based on type) that we want too look at.
298 *
299 * @return a reference to a Queue
300 */
301 protected Queue getQueue() {
302 return MonitorManager.getInstance().getDataQueue();
303 }
304
305 //---ATTRIBUTES---
306
307 /**
308 * This is the friendly identifier of the
309 * component this class is running in.
310 * eg, a Filter may be called "filter1",
311 * If this class does not have an owning
312 * component, a name from the configuration
313 * can be placed here. This name could also
314 * be changed to null for utility classes.
315 */
316 private String _name = "Disk";
317
318 /**
319 * Inodes have the name "DiskInode" in the
320 * configuration.
321 */
322 private String _nameInode = "DiskInode";
323
324 /**
325 * A reference to the configuration proxy in use
326 */
327 private ConfigurationProxy _cp = ConfigurationProxy.getInstance();
328
329 /**
330 * A HashMap of Registers (or groups of Registers), one
331 * for each host we're monitoring.
332 */
333 private HashMap _hosts = new HashMap();
334
335 /**
336 * A HashMap of Registers (or groups of Registers), one
337 * for each host we're monitoring (inodes).
338 */
339 private HashMap _hostsInode = new HashMap();
340
341 //---STATIC ATTRIBUTES---
342
343 }