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

# Content
1 //---PACKAGE DECLARATION---
2 package uk.org.iscream.cms.server.client.monitors;
3
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 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
15 /**
16 * This Monitor watches the Disks for all machines
17 *
18 * @author $Author: tdb1 $
19 * @version $Id: Disk__Monitor.java,v 1.14 2001/11/26 11:59:19 tdb1 Exp $
20 */
21 public class Disk__Monitor extends MonitorSkeleton {
22
23 //---FINAL ATTRIBUTES---
24
25 /**
26 * The current CVS revision of this class
27 */
28 public final String REVISION = "$Revision: 1.14 $";
29
30 /**
31 * A description of this monitor
32 */
33 public final String DESC = "Monitors all host disks.";
34
35 //---STATIC METHODS---
36
37 //---CONSTRUCTORS---
38
39 //---PUBLIC METHODS---
40
41 /**
42 * Analyse a packet of data, and generate an alert if
43 * necessary.
44 *
45 * @param packet the XMLPacket to analyse
46 */
47 public void analysePacket(XMLPacket packet) {
48 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
55 // key prefix
56 String keyPrefix = "packet.disk.p";
57
58 // a temporary holder for all the disk attributes we find
59 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 if(dataKey.startsWith(keyPrefix)) {
68 if(!disks.contains(dataKey)) {
69 String diskNumber = "";
70
71 // pos is after "packet.disk.p"
72 int pos = keyPrefix.length();
73 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 disks.add(keyPrefix + diskNumber + ".attributes.used");
82
83 // device
84 disks.add(keyPrefix + diskNumber + ".attributes.name");
85 String device = packet.getParam(keyPrefix + diskNumber + ".attributes.name");
86 // mount point
87 disks.add(keyPrefix + diskNumber + ".attributes.mount");
88 String mount = packet.getParam(keyPrefix + diskNumber + ".attributes.mount");
89
90 // these next two will be used to calculate the %age
91 // total
92 disks.add(keyPrefix + diskNumber + ".attributes.kbytes");
93 String total = packet.getParam(keyPrefix + diskNumber + ".attributes.kbytes");
94 // available
95 disks.add(keyPrefix + diskNumber + ".attributes.avail");
96 String avail = packet.getParam(keyPrefix + diskNumber + ".attributes.avail");
97
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 // nb. use the mount as the key as this is unlikely to change,
103 // unlike diskNumber which could easily change
104 // (diskNumber is based on the order of df's output!)
105 if(!diskRegisters.containsKey(mount)) {
106 diskRegisters.put(mount, new Register(source, _name, mount));
107 }
108
109 // get the register for this disk
110 Register reg = (Register) diskRegisters.get(mount);
111
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 }
119 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
127 boolean useValue = false;
128 try {
129 // try looking for a mount-point specific thresholdMeasure first
130 String option = _cp.getProperty("Host." + source, "Monitor." + _name + "." + mount + ".thresholdMeasure");
131 if (option.equals("VALUE")) {
132 useValue = true;
133 }
134 } catch (PropertyNotFoundException e) {
135 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 }
145
146 // this bit determines if the disk check is a % check
147 // or a kb check
148 String type;
149 double curValue;
150 int newThreshold;
151 if(useValue) {
152 // kb disk available
153 curValue = diskAvail;
154 // negate check
155 newThreshold = checkAttributeThreshold(curValue, reg, true);
156 type = "kb";
157 } else {
158 // % disk in use
159 curValue = (1 - (diskAvail / diskTotal)) * 100;
160 // normal check
161 newThreshold = checkAttributeThreshold(curValue, reg, false);
162 type = "%";
163 }
164
165 // format the diskInUse to a String
166 NumberFormat nf = NumberFormat.getInstance();
167 nf.setMaximumFractionDigits(2);
168 nf.setMinimumFractionDigits(2);
169 String strCurValue = nf.format(curValue);
170
171 // say which disk had the problem
172 String attributeName = "Disk in use " + type + " on " + mount + " (" + device + ")";
173
174 processAlert(newThreshold, attributeName, reg, source, strCurValue);
175 }
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 * This uses the uk.org.iscream.cms.server.util.NameFormat class
185 * 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
205 /**
206 * Checks a piece of current data, and returns the
207 * threshold it breaches, if any.
208 *
209 * 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 * @param reg the Register for the host
216 * @param negateCheck whether to negate the check
217 * @return the threshold level breached, if any
218 */
219 private int checkAttributeThreshold(double value, Register reg, boolean negateCheck) {
220 for(int thresholdLevel = Alert.thresholdLevels.length - 1; thresholdLevel >= 0; thresholdLevel--) {
221 if (reg.getThreshold(thresholdLevel) != -1.0) {
222 if(!negateCheck) {
223 // normal check - has the value gone *over* the threshold
224 if(((double) reg.getThreshold(thresholdLevel)) < value) {
225 return thresholdLevel;
226 }
227 }
228 else {
229 // negated check - has the value gone *under* the threshold
230 if(((double) reg.getThreshold(thresholdLevel)) > value) {
231 return thresholdLevel;
232 }
233 }
234 }
235 }
236 return Alert.thresholdNORMAL;
237 }
238
239 //---ACCESSOR/MUTATOR METHODS---
240
241 /**
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 protected Queue getQueue() {
249 return MonitorManager.getInstance().getDataQueue();
250 }
251
252 //---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
270 /**
271 * A HashMap of Registers (or groups of Registers), one
272 * for each host we're monitoring.
273 */
274 private HashMap _hosts = new HashMap();
275
276 //---STATIC ATTRIBUTES---
277
278 }