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

# User Rev Content
1 tdb 1.16 /*
2     * i-scream central monitoring system
3 tdb 1.17 * http://www.i-scream.org.uk
4 tdb 1.16 * 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 ajm 1.1 //---PACKAGE DECLARATION---
22 tdb 1.9 package uk.org.iscream.cms.server.client.monitors;
23 ajm 1.1
24     //---IMPORTS---
25     import java.util.HashMap;
26 tdb 1.19 import java.util.HashSet;
27 ajm 1.1 import java.util.Set;
28     import java.util.Iterator;
29     import java.text.NumberFormat;
30 tdb 1.9 import uk.org.iscream.cms.server.client.*;
31     import uk.org.iscream.cms.server.core.*;
32 tdb 1.18 import uk.org.iscream.cms.util.*;
33 tdb 1.9 import uk.org.iscream.cms.server.componentmanager.*;
34 ajm 1.1
35     /**
36     * This Monitor watches the Disks for all machines
37     *
38 tdb 1.16 * @author $Author: tdb $
39 tdb 1.19 * @version $Id: Disk__Monitor.java,v 1.18 2003/02/05 16:43:45 tdb Exp $
40 ajm 1.1 */
41     public class Disk__Monitor extends MonitorSkeleton {
42    
43     //---FINAL ATTRIBUTES---
44    
45     /**
46     * The current CVS revision of this class
47     */
48 tdb 1.19 public final String REVISION = "$Revision: 1.18 $";
49 ajm 1.1
50 tdb 1.8 /**
51     * A description of this monitor
52     */
53 ajm 1.1 public final String DESC = "Monitors all host disks.";
54    
55     //---STATIC METHODS---
56    
57     //---CONSTRUCTORS---
58    
59     //---PUBLIC METHODS---
60 tdb 1.8
61     /**
62     * Analyse a packet of data, and generate an alert if
63     * necessary.
64     *
65     * @param packet the XMLPacket to analyse
66     */
67 ajm 1.1 public void analysePacket(XMLPacket packet) {
68 ajm 1.7 String source = packet.getParam("packet.attributes.machine_name");
69     if (!_hosts.containsKey(source)) {
70     _hosts.put(source, new HashMap());
71     }
72 tdb 1.19 if (!_hostsInode.containsKey(source)) {
73     _hostsInode.put(source, new HashMap());
74     }
75 ajm 1.7
76     HashMap diskRegisters = (HashMap) _hosts.get(source);
77 tdb 1.19 HashMap diskInodeRegisters = (HashMap) _hostsInode.get(source);
78 tdb 1.8
79     // key prefix
80     String keyPrefix = "packet.disk.p";
81    
82 tdb 1.11 // a temporary holder for all the disk attributes we find
83 tdb 1.19 HashSet disks = new HashSet();
84 ajm 1.7
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 tdb 1.8 if(dataKey.startsWith(keyPrefix)) {
92 tdb 1.19 // 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 ajm 1.7
101     // device
102 tdb 1.19 String device = packet.getParam(thisDisk + ".attributes.name");
103 ajm 1.7 // mount point
104 tdb 1.19 String mount = packet.getParam(thisDisk + ".attributes.mount");
105 ajm 1.7
106     // these next two will be used to calculate the %age
107     // total
108 tdb 1.19 String total = packet.getParam(thisDisk + ".attributes.total");
109 ajm 1.7 // available
110 tdb 1.19 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 ajm 1.7
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 tdb 1.15 // nb. use the mount as the key as this is unlikely to change,
120 tdb 1.12 // unlike diskNumber which could easily change
121     // (diskNumber is based on the order of df's output!)
122 tdb 1.15 if(!diskRegisters.containsKey(mount)) {
123     diskRegisters.put(mount, new Register(source, _name, mount));
124 ajm 1.7 }
125 tdb 1.19 if(!diskInodeRegisters.containsKey(mount)) {
126     diskInodeRegisters.put(mount, new Register(source, _nameInode, mount));
127     }
128 ajm 1.7
129     // get the register for this disk
130 tdb 1.15 Register reg = (Register) diskRegisters.get(mount);
131 tdb 1.19 Register regInode = (Register) diskInodeRegisters.get(mount);
132 ajm 1.7
133     // get the packet data
134     double diskTotal, diskAvail;
135 tdb 1.19 int diskInodeTotal, diskInodeAvail;
136 ajm 1.7 try {
137    
138 tdb 1.19 if(total==null || avail==null || totalInodes==null || availInodes==null) {
139 ajm 1.7 throw new NumberFormatException("Disk data invalid");
140 ajm 1.2 }
141 ajm 1.7 diskTotal = Double.parseDouble(total);
142     diskAvail = Double.parseDouble(avail);
143 tdb 1.19 diskInodeTotal = Integer.parseInt(totalInodes);
144     diskInodeAvail = Integer.parseInt(availInodes);
145 ajm 1.7 } 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 ajm 1.2
151 ajm 1.7 boolean useValue = false;
152 tdb 1.19 boolean useValueInode = false;
153 ajm 1.7 try {
154 tdb 1.13 // try looking for a mount-point specific thresholdMeasure first
155     String option = _cp.getProperty("Host." + source, "Monitor." + _name + "." + mount + ".thresholdMeasure");
156 ajm 1.7 if (option.equals("VALUE")) {
157     useValue = true;
158 tdb 1.13 }
159 tdb 1.19 option = _cp.getProperty("Host." + source, "Monitor." + _nameInode + "." + mount + ".thresholdMeasure");
160     if (option.equals("VALUE")) {
161     useValueInode = true;
162     }
163 ajm 1.7 } catch (PropertyNotFoundException e) {
164 tdb 1.13 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 tdb 1.19 option = _cp.getProperty("Host." + source, "Monitor." + _nameInode + ".thresholdMeasure");
171     if (option.equals("VALUE")) {
172     useValueInode = true;
173     }
174 tdb 1.13 } catch (PropertyNotFoundException f) {
175     // we default to percentage in any case
176     }
177 ajm 1.7 }
178 ajm 1.2
179 ajm 1.7 // this bit determines if the disk check is a % check
180 tdb 1.19 // or a byte check
181 ajm 1.7 String type;
182 tdb 1.10 double curValue;
183     int newThreshold;
184 ajm 1.7 if(useValue) {
185 tdb 1.19 // byte disk available
186 tdb 1.10 curValue = diskAvail;
187     // negate check
188     newThreshold = checkAttributeThreshold(curValue, reg, true);
189 tdb 1.19 type = "bytes";
190 ajm 1.7 } else {
191     // % disk in use
192 tdb 1.19 curValue = (1 - ((double)diskAvail / (double)diskTotal)) * 100;
193 tdb 1.10 // normal check
194     newThreshold = checkAttributeThreshold(curValue, reg, false);
195 ajm 1.7 type = "%";
196 ajm 1.1 }
197 tdb 1.19
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 ajm 1.7 // format the diskInUse to a String
216     NumberFormat nf = NumberFormat.getInstance();
217     nf.setMaximumFractionDigits(2);
218     nf.setMinimumFractionDigits(2);
219 tdb 1.10 String strCurValue = nf.format(curValue);
220 tdb 1.19 String strCurValueInode = nf.format(curValueInode);
221 ajm 1.7
222     // say which disk had the problem
223     String attributeName = "Disk in use " + type + " on " + mount + " (" + device + ")";
224 tdb 1.19 String attributeNameInode = "Disk inodes in use " + type + " on " + mount + " (" + device +")";
225 ajm 1.7
226 tdb 1.10 processAlert(newThreshold, attributeName, reg, source, strCurValue);
227 tdb 1.19 processAlert(newThresholdInode, attributeNameInode, regInode, source, strCurValueInode);
228 ajm 1.1 }
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 tdb 1.18 * This uses the uk.org.iscream.cms.util.NameFormat class
238 ajm 1.1 * 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 tdb 1.8
258     /**
259     * Checks a piece of current data, and returns the
260     * threshold it breaches, if any.
261     *
262 tdb 1.10 * 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 tdb 1.8 * @param reg the Register for the host
269 tdb 1.10 * @param negateCheck whether to negate the check
270 tdb 1.8 * @return the threshold level breached, if any
271     */
272 tdb 1.14 private int checkAttributeThreshold(double value, Register reg, boolean negateCheck) {
273 ajm 1.1 for(int thresholdLevel = Alert.thresholdLevels.length - 1; thresholdLevel >= 0; thresholdLevel--) {
274     if (reg.getThreshold(thresholdLevel) != -1.0) {
275 tdb 1.10 if(!negateCheck) {
276     // normal check - has the value gone *over* the threshold
277 tdb 1.14 if(((double) reg.getThreshold(thresholdLevel)) < value) {
278 tdb 1.10 return thresholdLevel;
279     }
280     }
281     else {
282     // negated check - has the value gone *under* the threshold
283 tdb 1.14 if(((double) reg.getThreshold(thresholdLevel)) > value) {
284 tdb 1.10 return thresholdLevel;
285     }
286 ajm 1.1 }
287     }
288     }
289     return Alert.thresholdNORMAL;
290     }
291    
292     //---ACCESSOR/MUTATOR METHODS---
293 ajm 1.7
294 tdb 1.8 /**
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 ajm 1.7 protected Queue getQueue() {
302     return MonitorManager.getInstance().getDataQueue();
303     }
304    
305 ajm 1.1 //---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 tdb 1.19 * Inodes have the name "DiskInode" in the
320     * configuration.
321     */
322     private String _nameInode = "DiskInode";
323    
324     /**
325 ajm 1.1 * A reference to the configuration proxy in use
326     */
327     private ConfigurationProxy _cp = ConfigurationProxy.getInstance();
328 tdb 1.8
329     /**
330     * A HashMap of Registers (or groups of Registers), one
331     * for each host we're monitoring.
332     */
333 ajm 1.1 private HashMap _hosts = new HashMap();
334 tdb 1.19
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 ajm 1.1
341     //---STATIC ATTRIBUTES---
342    
343     }