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.15
Committed: Sat Jan 19 17:54:57 2002 UTC (22 years, 4 months ago) by tdb
Branch: MAIN
Branch point for: SERVER_PIRCBOT
Changes since 1.14: +6 -6 lines
Log Message:
After some work elsewhere in i-scream it became apparent that using the
device (filesystem) as the key might not work. As an example:

swap                 7346808      32 7346776     1%    /var/run
swap                  686080    1912  684168     1%    /tmp

These two mounts have the same device name, "swap", but different mount
points. Before this change they would have been treated as the same, even
though they clearly have different properties. Using the mount point isn't
as ideal as the device, as you could move a mount point on a live
filesystem... but that wouldn't cause too many problems as a new Register
would just be created.

File Contents

# User Rev Content
1 ajm 1.1 //---PACKAGE DECLARATION---
2 tdb 1.9 package uk.org.iscream.cms.server.client.monitors;
3 ajm 1.1
4     //---IMPORTS---
5     import java.util.HashMap;
6     import java.util.ArrayList;
7     import java.util.Set;
8     import java.util.Iterator;
9     import java.text.NumberFormat;
10 tdb 1.9 import uk.org.iscream.cms.server.client.*;
11     import uk.org.iscream.cms.server.core.*;
12     import uk.org.iscream.cms.server.util.*;
13     import uk.org.iscream.cms.server.componentmanager.*;
14 ajm 1.1
15     /**
16     * This Monitor watches the Disks for all machines
17     *
18 tdb 1.9 * @author $Author: tdb1 $
19 tdb 1.15 * @version $Id: Disk__Monitor.java,v 1.14 2001/11/26 11:59:19 tdb1 Exp $
20 ajm 1.1 */
21     public class Disk__Monitor extends MonitorSkeleton {
22    
23     //---FINAL ATTRIBUTES---
24    
25     /**
26     * The current CVS revision of this class
27     */
28 tdb 1.15 public final String REVISION = "$Revision: 1.14 $";
29 ajm 1.1
30 tdb 1.8 /**
31     * A description of this monitor
32     */
33 ajm 1.1 public final String DESC = "Monitors all host disks.";
34    
35     //---STATIC METHODS---
36    
37     //---CONSTRUCTORS---
38    
39     //---PUBLIC METHODS---
40 tdb 1.8
41     /**
42     * Analyse a packet of data, and generate an alert if
43     * necessary.
44     *
45     * @param packet the XMLPacket to analyse
46     */
47 ajm 1.1 public void analysePacket(XMLPacket packet) {
48 ajm 1.7 String source = packet.getParam("packet.attributes.machine_name");
49     if (!_hosts.containsKey(source)) {
50     _hosts.put(source, new HashMap());
51     }
52    
53     HashMap diskRegisters = (HashMap) _hosts.get(source);
54 tdb 1.8
55     // key prefix
56     String keyPrefix = "packet.disk.p";
57    
58 tdb 1.11 // a temporary holder for all the disk attributes we find
59 ajm 1.7 ArrayList disks = new ArrayList();
60    
61     // unfortunatly we need to check the whole packet
62     // to find the disks, and then get the data attributes
63     Set packetSet = packet.getSet();
64     Iterator i = packetSet.iterator();
65     while (i.hasNext()) {
66     String dataKey = (String) i.next();
67 tdb 1.8 if(dataKey.startsWith(keyPrefix)) {
68 ajm 1.7 if(!disks.contains(dataKey)) {
69     String diskNumber = "";
70    
71     // pos is after "packet.disk.p"
72 tdb 1.8 int pos = keyPrefix.length();
73 ajm 1.7 while (dataKey.charAt(pos) != '.') {
74     diskNumber = diskNumber + dataKey.charAt(pos);
75     pos++;
76     }
77    
78     // add the disk to our list, with the packet data
79    
80     // used (we won't use this value - but we need it to forget about it ;)
81 tdb 1.8 disks.add(keyPrefix + diskNumber + ".attributes.used");
82 ajm 1.7
83     // device
84 tdb 1.8 disks.add(keyPrefix + diskNumber + ".attributes.name");
85     String device = packet.getParam(keyPrefix + diskNumber + ".attributes.name");
86 ajm 1.7 // mount point
87 tdb 1.8 disks.add(keyPrefix + diskNumber + ".attributes.mount");
88     String mount = packet.getParam(keyPrefix + diskNumber + ".attributes.mount");
89 ajm 1.7
90     // these next two will be used to calculate the %age
91     // total
92 tdb 1.8 disks.add(keyPrefix + diskNumber + ".attributes.kbytes");
93     String total = packet.getParam(keyPrefix + diskNumber + ".attributes.kbytes");
94 ajm 1.7 // available
95 tdb 1.8 disks.add(keyPrefix + diskNumber + ".attributes.avail");
96     String avail = packet.getParam(keyPrefix + diskNumber + ".attributes.avail");
97 ajm 1.7
98     // *** now process this disk ***
99    
100     // check if we've seen this disk before on a previous run
101     // if not, we need to create a register for it
102 tdb 1.15 // nb. use the mount as the key as this is unlikely to change,
103 tdb 1.12 // unlike diskNumber which could easily change
104     // (diskNumber is based on the order of df's output!)
105 tdb 1.15 if(!diskRegisters.containsKey(mount)) {
106     diskRegisters.put(mount, new Register(source, _name, mount));
107 ajm 1.7 }
108    
109     // get the register for this disk
110 tdb 1.15 Register reg = (Register) diskRegisters.get(mount);
111 ajm 1.7
112     // get the packet data
113     double diskTotal, diskAvail;
114     try {
115    
116     if(total==null || avail==null) {
117     throw new NumberFormatException("Disk data invalid");
118 ajm 1.2 }
119 ajm 1.7 diskTotal = Double.parseDouble(total);
120     diskAvail = Double.parseDouble(avail);
121     } catch (NumberFormatException e) {
122     _logger.write(this.toString(), Logger.WARNING, "Received packet from "+source+" with bad disk information: "+e);
123     // don't try to continue and process, try next disk
124     break;
125     }
126 ajm 1.2
127 ajm 1.7 boolean useValue = false;
128     try {
129 tdb 1.13 // try looking for a mount-point specific thresholdMeasure first
130     String option = _cp.getProperty("Host." + source, "Monitor." + _name + "." + mount + ".thresholdMeasure");
131 ajm 1.7 if (option.equals("VALUE")) {
132     useValue = true;
133 tdb 1.13 }
134 ajm 1.7 } catch (PropertyNotFoundException e) {
135 tdb 1.13 try {
136     // now look for a more general thresholdMeasure
137     String option = _cp.getProperty("Host." + source, "Monitor." + _name + ".thresholdMeasure");
138     if (option.equals("VALUE")) {
139     useValue = true;
140     }
141     } catch (PropertyNotFoundException f) {
142     // we default to percentage in any case
143     }
144 ajm 1.7 }
145 ajm 1.2
146 ajm 1.7 // this bit determines if the disk check is a % check
147     // or a kb check
148     String type;
149 tdb 1.10 double curValue;
150     int newThreshold;
151 ajm 1.7 if(useValue) {
152 tdb 1.10 // kb disk available
153     curValue = diskAvail;
154     // negate check
155     newThreshold = checkAttributeThreshold(curValue, reg, true);
156 ajm 1.7 type = "kb";
157     } else {
158     // % disk in use
159 tdb 1.10 curValue = (1 - (diskAvail / diskTotal)) * 100;
160     // normal check
161     newThreshold = checkAttributeThreshold(curValue, reg, false);
162 ajm 1.7 type = "%";
163 ajm 1.1 }
164 ajm 1.7
165     // format the diskInUse to a String
166     NumberFormat nf = NumberFormat.getInstance();
167     nf.setMaximumFractionDigits(2);
168     nf.setMinimumFractionDigits(2);
169 tdb 1.10 String strCurValue = nf.format(curValue);
170 ajm 1.7
171     // say which disk had the problem
172     String attributeName = "Disk in use " + type + " on " + mount + " (" + device + ")";
173    
174 tdb 1.10 processAlert(newThreshold, attributeName, reg, source, strCurValue);
175 ajm 1.1 }
176     }
177     }
178     }
179    
180     /**
181     * Overrides the {@link java.lang.Object#toString() Object.toString()}
182     * method to provide clean logging (every class should have this).
183     *
184 tdb 1.9 * This uses the uk.org.iscream.cms.server.util.NameFormat class
185 ajm 1.1 * to format the toString()
186     *
187     * @return the name of this class and its CVS revision
188     */
189     public String toString() {
190     return FormatName.getName(
191     _name,
192     getClass().getName(),
193     REVISION);
194     }
195    
196     /**
197     * return the String representation of what the monitor does
198     */
199     public String getDescription(){
200     return DESC;
201     }
202    
203     //---PRIVATE METHODS---
204 tdb 1.8
205     /**
206     * Checks a piece of current data, and returns the
207     * threshold it breaches, if any.
208     *
209 tdb 1.10 * The option to negate the check can be used in
210     * situations where being *below* the threshold
211     * is an 'alertable' situation. In this specific
212     * case, we'd do this with kb disk checks.
213     *
214     * @param value the current value
215 tdb 1.8 * @param reg the Register for the host
216 tdb 1.10 * @param negateCheck whether to negate the check
217 tdb 1.8 * @return the threshold level breached, if any
218     */
219 tdb 1.14 private int checkAttributeThreshold(double value, Register reg, boolean negateCheck) {
220 ajm 1.1 for(int thresholdLevel = Alert.thresholdLevels.length - 1; thresholdLevel >= 0; thresholdLevel--) {
221     if (reg.getThreshold(thresholdLevel) != -1.0) {
222 tdb 1.10 if(!negateCheck) {
223     // normal check - has the value gone *over* the threshold
224 tdb 1.14 if(((double) reg.getThreshold(thresholdLevel)) < value) {
225 tdb 1.10 return thresholdLevel;
226     }
227     }
228     else {
229     // negated check - has the value gone *under* the threshold
230 tdb 1.14 if(((double) reg.getThreshold(thresholdLevel)) > value) {
231 tdb 1.10 return thresholdLevel;
232     }
233 ajm 1.1 }
234     }
235     }
236     return Alert.thresholdNORMAL;
237     }
238    
239     //---ACCESSOR/MUTATOR METHODS---
240 ajm 1.7
241 tdb 1.8 /**
242     * Returns a reference to a specific Queue for this
243     * monitor. This Queue returns only the data packets
244     * (based on type) that we want too look at.
245     *
246     * @return a reference to a Queue
247     */
248 ajm 1.7 protected Queue getQueue() {
249     return MonitorManager.getInstance().getDataQueue();
250     }
251    
252 ajm 1.1 //---ATTRIBUTES---
253    
254     /**
255     * This is the friendly identifier of the
256     * component this class is running in.
257     * eg, a Filter may be called "filter1",
258     * If this class does not have an owning
259     * component, a name from the configuration
260     * can be placed here. This name could also
261     * be changed to null for utility classes.
262     */
263     private String _name = "Disk";
264    
265     /**
266     * A reference to the configuration proxy in use
267     */
268     private ConfigurationProxy _cp = ConfigurationProxy.getInstance();
269 tdb 1.8
270     /**
271     * A HashMap of Registers (or groups of Registers), one
272     * for each host we're monitoring.
273     */
274 ajm 1.1 private HashMap _hosts = new HashMap();
275    
276     //---STATIC ATTRIBUTES---
277    
278     }