001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2002-2004 French National Institute For Research In Computer
004: * Science And Control (INRIA).
005: * Contact: sequoia@continuent.org
006: *
007: * Licensed under the Apache License, Version 2.0 (the "License");
008: * you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: *
019: * Initial developer(s): Emmanuel Cecchet.
020: * Contributor(s): Julie Marguerite, Sara Bouchenak.
021: */package org.continuent.sequoia.common.util;
022:
023: /**
024: * This class provides thread-safe statistics. Each statistic entry is composed
025: * as follow:
026: * <ul>
027: * <li>count: statistic counter</li>
028: * <li>error: statistic error counter</li>
029: * <li>minTime: minimum time for this entry (automatically computed)</li>
030: * <li>maxTime: maximum time for this entry (automatically computed)</li>
031: * <li>totalTime: total time for this entry</li>
032: * </ul>
033: *
034: * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
035: * @author <a href="mailto:julie.marguerite@inria.fr">Julie Marguerite </a>
036: * @version 1.0
037: */
038:
039: public class Stats {
040: /** Statistic counter */
041: private int count;
042:
043: /** Statistic error counter */
044: private int error;
045:
046: /** Cache hits counter */
047: private int cacheHit;
048:
049: /** Minimum time for this entry (automatically computed) */
050: private long minTime;
051:
052: /** Maximum time for this entry (automatically computed) */
053: private long maxTime;
054:
055: /** Total time for this entry */
056: private long totalTime;
057:
058: /** Name of the stats. */
059: private String name;
060:
061: /**
062: * Creates a new <code>Stats</code> instance. The entries are reset to 0.
063: *
064: * @param statName The stat name
065: */
066: public Stats(String statName) {
067: name = statName;
068: reset();
069: }
070:
071: /**
072: * Resets all entries to 0.
073: */
074: public synchronized void reset() {
075: count = 0;
076: error = 0;
077: minTime = Long.MAX_VALUE;
078: maxTime = Long.MIN_VALUE;
079: totalTime = 0;
080: }
081:
082: /**
083: * Increments an entry count by one.
084: */
085: public synchronized void incrementCount() {
086: count++;
087: }
088:
089: /**
090: * Increments an entry error by one.
091: */
092: public synchronized void incrementError() {
093: error++;
094: }
095:
096: /**
097: * Increments an entry cache hit by one.
098: */
099: public synchronized void incrementCacheHit() {
100: cacheHit++;
101: }
102:
103: /**
104: * Adds a new time sample for this entry. <code>time</code> is added to
105: * total time and both minTime and maxTime are updated if needed.
106: *
107: * @param time time to add to this entry
108: */
109: public synchronized void updateTime(long time) {
110: if (time < 0) {
111: System.err
112: .println("Negative time received in Stats.updateTime("
113: + time + ")\n");
114: return;
115: }
116: totalTime += time;
117: if (time > maxTime)
118: maxTime = time;
119: if (time < minTime)
120: minTime = time;
121: }
122:
123: /**
124: * Gets the name of the current stat.
125: *
126: * @return stat name
127: */
128: public String getName() {
129: return name;
130: }
131:
132: /**
133: * Gets current count of an entry.
134: *
135: * @return current entry count value
136: */
137: public synchronized int getCount() {
138: return count;
139: }
140:
141: /**
142: * Gets current error count of an entry
143: *
144: * @return current entry error value
145: */
146: public synchronized int getError() {
147: return error;
148: }
149:
150: /**
151: * Gets current cache hit count of an entry
152: *
153: * @return current entry cache hit value
154: */
155: public synchronized int getCacheHit() {
156: return cacheHit;
157: }
158:
159: /**
160: * Gets the minimum time of an entry
161: *
162: * @return entry minimum time
163: */
164: public synchronized long getMinTime() {
165: return minTime;
166: }
167:
168: /**
169: * Gets the maximum time of an entry
170: *
171: * @return entry maximum time
172: */
173: public synchronized long getMaxTime() {
174: return maxTime;
175: }
176:
177: /**
178: * Gets the total time of an entry
179: *
180: * @return entry total time
181: */
182: public synchronized long getTotalTime() {
183: return totalTime;
184: }
185:
186: /**
187: * Adds the entries of another <code>Stats</code> object to this one.
188: *
189: * @param anotherStat stat to merge with current stat
190: * @throws Exception if you try to merge a stat with itself
191: */
192: public synchronized void merge(Stats anotherStat) throws Exception {
193: if (this == anotherStat) {
194: throw new Exception("You cannot merge a stat with itself");
195: }
196:
197: count += anotherStat.getCount();
198: error += anotherStat.getError();
199: cacheHit += anotherStat.getCacheHit();
200: if (minTime > anotherStat.getMinTime())
201: minTime = anotherStat.getMinTime();
202: if (maxTime < anotherStat.getMaxTime())
203: maxTime = anotherStat.getMaxTime();
204: totalTime += anotherStat.getTotalTime();
205: }
206:
207: /**
208: * Displays the statistics on the standard output.
209: */
210: public void displayOnStdout() {
211: System.out.println(multipleLineDisplay());
212: }
213:
214: /**
215: * Displays the statistics information on multiple lines.
216: *
217: * @return a <code>String</code> containing the Stat output
218: */
219: public String multipleLineDisplay() {
220: String output = name + " statistics:\n" + " Count: " + count
221: + "\n" + " Error: " + error + "\n";
222: if (totalTime != 0) {
223: output += " Min time: " + minTime + " ms\n";
224: output += " Max time: " + maxTime + " ms\n";
225: } else {
226: output += " Min time: 0 ms\n";
227: output += " Max time: 0 ms\n";
228: }
229: if (count == 0)
230: output += " Avg time: 0 ms\n";
231: else
232: output += " Avg time: " + totalTime / count + " ms\n";
233: output += " Tot time: " + totalTime + " ms\n";
234:
235: double timeSec = totalTime / 1000;
236: double timeMin = timeSec / 60, throup;
237: throup = (timeMin != 0) ? (count / timeMin) : (count / timeSec);
238: output += " Throughput: "
239: + throup
240: + ((timeMin != 0) ? " requests/minute"
241: : " requests/second");
242: return output;
243: }
244:
245: /**
246: * Displays the statistics information on a single line in the format: name
247: * count error cacheHit %hit minTime maxTime avgTime totalTime
248: *
249: * @return a <code>String</code> containing the Stat output
250: */
251: public String singleLineDisplay() {
252: String output = name + " " + count + " " + error + " "
253: + cacheHit + " ";
254: if (count == 0)
255: output += "0 ";
256: else
257: output += ((double) cacheHit / (double) count * 100.0)
258: + " ";
259: if (totalTime != 0)
260: output += minTime + " " + maxTime + " ";
261: else
262: output += " 0 0 ";
263: if (count == 0)
264: output += "0 ";
265: else
266: output += totalTime / count + " ";
267: output += totalTime;
268: double timeSec = totalTime / 1000;
269: double timeMin = timeSec / 60, throup;
270: throup = (timeMin != 0) ? (count / timeMin) : (count / timeSec);
271: output += throup
272: + ((timeMin != 0) ? " requests/minute"
273: : " requests/second");
274: return output;
275: }
276:
277: /**
278: * Get the stat information in the form of a String table. Format is: name
279: * count error cacheHit %hit minTime maxTime avgTime totalTime
280: *
281: * @return the String table corresponding to this stat
282: */
283: public String[] toStringTable() {
284: String[] foo = {
285: name,
286: Integer.toString(count),
287: Integer.toString(error),
288: Integer.toString(cacheHit),
289: (count == 0) ? "0" : Float.toString((float) cacheHit
290: / (float) count * (float) 100.0),
291: Long.toString(minTime),
292: Long.toString(maxTime),
293: (count == 0) ? "0" : Float.toString((float) totalTime
294: / (float) count), Long.toString(totalTime) };
295: return foo;
296: }
297: }
|