001: //** Copyright Statement ***************************************************
002: //The Salmon Open Framework for Internet Applications (SOFIA)
003: // Copyright (C) 1999 - 2002, Salmon LLC
004: //
005: // This program is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU General Public License version 2
007: // as published by the Free Software Foundation;
008: //
009: // This program is distributed in the hope that it will be useful,
010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: // GNU General Public License for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // along with this program; if not, write to the Free Software
016: // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: //
018: // For more information please visit http://www.salmonllc.com
019: //** End Copyright Statement ***************************************************
020: package com.salmonllc.servlets;
021:
022: /////////////////////////
023: //$Archive: /SOFIA/SourceCode/com/salmonllc/servlets/ConnectionMonitor.java $
024: //$Author: Dan $
025: //$Revision: 10 $
026: //$Modtime: 8/24/04 4:25p $
027: /////////////////////////
028:
029: import java.io.*;
030: import java.util.Enumeration;
031: import java.util.Hashtable;
032:
033: import javax.servlet.ServletException;
034: import javax.servlet.http.*;
035:
036: import com.salmonllc.jsp.JspServlet;
037: import com.salmonllc.properties.Props;
038: import com.salmonllc.sql.DBConnection;
039: import com.salmonllc.sql.DBConnectionList;
040: import com.salmonllc.util.VectorSort;
041:
042: /**
043: * This servlet provides useful information on connections in the connection pool and other server statistics<BR>
044: * It should be secured with a password on a production server to prevent unauthorized use.
045: */
046: public class ConnectionMonitor extends HttpServlet {
047: StringBuffer _sbFreeMemory = new StringBuffer();
048:
049: int _iMemoryPrintCntr = 0;
050: int _iListCntr = 0;
051: String _sAppName;
052: boolean _showTimers = true;
053: boolean _showConnections = true;
054: boolean _autoRefresh = true;
055:
056: public class TimerList extends VectorSort {
057: public boolean compare(Object o1, Object o2) {
058: int val = (((Timer) o1).name
059: .compareToIgnoreCase(((Timer) o2).name));
060: return (val < 0);
061: }
062:
063: public void populate(Hashtable t) {
064: Enumeration e = t.keys();
065: while (e.hasMoreElements()) {
066: String name = (String) e.nextElement();
067: Timer tm = new Timer();
068: JspServlet.Timer time = (JspServlet.Timer) t.get(name);
069: tm.count = time.count;
070: tm.totalTime = time.totalTime;
071: tm.name = name;
072: addElement(tm);
073: }
074: }
075:
076: }
077:
078: public class Timer {
079: String name;
080: int count;
081: long totalTime;
082: }
083:
084: public ConnectionMonitor() {
085: super ();
086: }
087:
088: /**
089: * This method handles get events from the browser.
090: */
091: public void doGet(HttpServletRequest req, HttpServletResponse res)
092: throws ServletException, IOException {
093: JspServlet.setUpApplicationContext(getServletContext(), req);
094: Props pr = Props.getSystemProps();
095: if (!pr.getBooleanProperty(Props.SYS_INFO_SERVLETS, true))
096: return;
097:
098: PrintWriter p = res.getWriter();
099:
100: String sValues[] = req.getParameterValues("REFRESH");
101: String sRefresh = "5";
102: if (sValues != null) {
103: sRefresh = req.getParameterValues("REFRESH")[0];
104: if (sRefresh == null)
105: sRefresh = "5";
106: }
107:
108: sValues = req.getParameterValues("APPNAME");
109: if (sValues != null) {
110: String sParam = req.getParameterValues("APPNAME")[0];
111: if (sParam != null)
112: _sAppName = sParam;
113: }
114:
115: sValues = req.getParameterValues("ITERATOR");
116: String sIterator = "5";
117: if (sValues != null) {
118: sIterator = req.getParameterValues("ITERATOR")[0];
119: if (sIterator == null)
120: sIterator = "25";
121: }
122:
123: sValues = req.getParameterValues("PRINTLOG");
124: boolean bPrintLog = false;
125: if (sValues != null) {
126: String sParam = req.getParameterValues("PRINTLOG")[0];
127: if (sParam != null)
128: bPrintLog = true;
129: }
130:
131: res.setContentType("text/html");
132: p.println("<HTML>");
133: p.println("<HEAD>");
134: p.println("<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">");
135: p
136: .println("<META HTTP-EQUIV=\"Cache-Control\" CONTENT=\"no-cache\">");
137: if (_autoRefresh)
138: p.println("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\""
139: + sRefresh + "\">");
140:
141: String serverName = com.salmonllc.util.URLGenerator
142: .generateServerURL(req);
143: p.println("<TITLE>" + serverName + "</TITLE>");
144:
145: long firstHitTime = JspServlet.getFirstPageHitTime();
146: String firstHitInfo = "";
147: float minSinceStart = 1;
148: if (firstHitTime > -1) {
149: java.sql.Timestamp ts = new java.sql.Timestamp(firstHitTime);
150: java.text.SimpleDateFormat sf = new java.text.SimpleDateFormat(
151: "MM/dd/yyyy hh:mm a");
152: firstHitInfo = " --- Started/Reset:" + sf.format(ts);
153: long sec = (System.currentTimeMillis() - firstHitTime) / 1000;
154: long min = sec / 60;
155: minSinceStart = sec / 60F;
156: long hours = min / 60;
157: min = min - (hours * 60);
158: sec = sec - ((hours * 3600) + (min * 60));
159: firstHitInfo += " (" + hours + " hrs " + min + " mins "
160: + sec + " secs)";
161: }
162:
163: java.text.DecimalFormat nf2 = new java.text.DecimalFormat(
164: "###,##0");
165: long lFreeMemory = (Runtime.getRuntime().freeMemory() / 1000);
166:
167: if (bPrintLog) {
168: _sbFreeMemory.append(lFreeMemory);
169: _sbFreeMemory.append(",");
170: _iMemoryPrintCntr++;
171:
172: int iIterator = Integer.parseInt(sIterator);
173:
174: if (_iMemoryPrintCntr > iIterator && printLogInfo()) {
175: _sbFreeMemory = new StringBuffer();
176: _iMemoryPrintCntr = 0;
177: _iListCntr++;
178: }
179: }
180:
181: java.text.DecimalFormat nf = new java.text.DecimalFormat(
182: "###,###0.00");
183: long pageHits = JspServlet.getPageHits();
184: String pageHitInfo = "Page Hits:<b>" + pageHits
185: + "</b> ";
186: if (pageHits > 0) {
187: pageHitInfo += " Average Hits/Minute:<b>"
188: + nf
189: .format(Math
190: .round(((pageHits * 100.0F) / minSinceStart)) / 100D)
191: + "</b>";
192: pageHitInfo += " Average Seconds/Page Request:<b>"
193: + nf.format(JspServlet.getAverageHitTime() / 1000D)
194: + "</b>";
195: }
196:
197: String controllerCacheInfo = "";
198: if (JspServlet.isControllerCacheActive()) {
199: controllerCacheInfo += " Cached Controllers:<b>"
200: + JspServlet.getControllerCacheCount() + "</b>";
201: controllerCacheInfo += " Controller Cache Memory:<b>"
202: + nf2
203: .format(JspServlet
204: .getControllerCacheBytes() / 1000)
205: + " kbs</b>";
206: }
207:
208: p.println("<FORM METHOD=\"POST\">");
209: p.println("<H1>Connection Monitor</H1>");
210: p
211: .println("<INPUT TYPE=\"SUBMIT\" name=\"reset\" value=\"Reset Stats\">");
212: p
213: .println("<INPUT TYPE=\"SUBMIT\" name=\"autorefresh\" value=\"Set Auto Refresh:"
214: + (_autoRefresh ? "Off" : "On") + "\">");
215: p.println("<INPUT TYPE=\"SUBMIT\" name=\"timers\" value=\""
216: + (_showTimers ? "Hide" : "Show") + " Timers\">");
217: p
218: .println("<INPUT TYPE=\"SUBMIT\" name=\"connections\" value=\""
219: + (_showConnections ? "Hide" : "Show")
220: + " Connections\">");
221:
222: p.println("<H3>" + serverName + firstHitInfo + "</H3>");
223:
224: p.println(pageHitInfo);
225: p.println(controllerCacheInfo);
226: p.println(" Free Memory:<b>"
227: + nf2.format(lFreeMemory) + " kbs of "
228: + nf2.format(Runtime.getRuntime().totalMemory() / 1000)
229: + " kbs</b>");
230:
231: TimerList ts = new TimerList();
232: ts.populate(JspServlet.getTimersHashtable());
233: ts.sort();
234: if (_showTimers) {
235: Enumeration e = ts.elements();
236: p.println("<br><br><TABLE border=\"0\" width=\"1000\">");
237: p
238: .println("<TR bgcolor=\"cadetblue\"><TD>Timer</TD><TD>Count</TD><TD>Avg Time (ms)</TD></TR>");
239: while (e.hasMoreElements()) {
240: Timer t = (Timer) e.nextElement();
241: p.println("<TR bgcolor=\"darkgray\"><TD>" + t.name
242: + "</TD><TD>" + t.count + "</TD><TD>"
243: + t.totalTime / t.count + "</TD></TR>");
244: }
245: if (ts.size() == 0)
246: p
247: .println("<TR bgcolor=\"darkgray\"><TD colspan=\"3\">No Timers Set</TD></TR>");
248:
249: p.println("</TABLE>");
250: }
251:
252: if (_showConnections) {
253: p.println("<br><br><TABLE border=\"0\" width=\"1000\">");
254: p
255: .println("<TR bgcolor=\"cadetblue\"><TD>DBMS</TD><TD colspan=\"3\">URL</TD><TD>In Use</TD><TD>Idle</TD><TD>Driver</TD><TD>User ID</TD></TR>");
256: Enumeration e = DBConnection.getConnectionLists();
257: boolean connUsed = false;
258: while (e.hasMoreElements()) {
259: connUsed = true;
260: DBConnectionList list = (DBConnectionList) e
261: .nextElement();
262: p.println("<TR bgcolor=\"darkgray\"><TD>");
263: p.println(list.getDBMS());
264: p.println("</TD><TD colspan=\"3\">");
265: p.println(list.getDatabaseURL());
266: p.println("</TD><TD>");
267: p.println(new Integer(list.getInUseCount()).toString());
268: p.println("</TD><TD>");
269: p.println(new Integer(list.getIdleCount()).toString());
270: p.println("</TD><TD>");
271: p.println(list.getDriver());
272: p.println("</TD><TD>");
273: p.println(list.getDatabaseUser());
274: p.println("</TD></TR>");
275: java.util.Enumeration en = list.getConnections();
276: p
277: .println("<TR><TD> </TD><TD bgcolor=\"darkgray\">In Use</TD><TD bgcolor=\"darkgray\">Last Used</td><TD bgcolor=\"darkgray\">Last Duration</td><TD bgcolor=\"darkgray\" colspan=\"4\" width=\"600\">Last SQL</TD></TR>");
278: long now = System.currentTimeMillis();
279: while (en.hasMoreElements()) {
280: DBConnection conn = (DBConnection) en.nextElement();
281: p.println("<TR><TD> </TD><TD>"
282: + conn.getInUse() + "</TD><TD>"
283: + ((now - conn.getLastUsed()) / 1000)
284: + "</TD><TD>"
285: + (conn.getLastDuration() / 1000D)
286: + "<TD colspan=4>" + conn.getLastSQL()
287: + "</TD></TR>");
288: }
289: }
290: if (!connUsed)
291: p
292: .println("<TR bgcolor=\"darkgray\"><TD colspan=\"9\">No Connections Created</TD></TR>");
293: p.println("</TABLE>");
294: }
295: p.println("</FORM>");
296: p.println("</HTML>");
297: p.close();
298:
299: }
300:
301: public void doPost(HttpServletRequest req, HttpServletResponse res)
302: throws ServletException, IOException {
303: JspServlet.setUpApplicationContext(getServletContext(), req);
304: if (req.getParameter("reset") != null)
305: JspServlet.resetAllTimers();
306: else if (req.getParameter("autorefresh") != null)
307: _autoRefresh = !_autoRefresh;
308: else if (req.getParameter("connections") != null)
309: _showConnections = !_showConnections;
310: else if (req.getParameter("timers") != null)
311: _showTimers = !_showTimers;
312: doGet(req, res);
313: }
314:
315: private boolean printLogInfo() {
316:
317: if (_sAppName == null) {
318: com.salmonllc.util.MessageLog
319: .writeDebugMessage(
320: "com.salmonllc.servlets.ConnectionMonitor.printLogInfo()Application name is not known.",
321: this );
322: return false;
323: }
324:
325: com.salmonllc.util.MessageLog
326: .writeDebugMessage(
327: "com.salmonllc.servlets.ConnectionMonitor.printLogInfo()Starting to write the log.",
328: this );
329: FileOutputStream fos = null;
330: PrintWriter pwr = null;
331: try {
332: String sFilePath = Props.getProps("RealEstate",
333: "ObjectStorePath").getProperty("ObjectStorePath")
334: + "\\FreemMemorySpace" + _iListCntr + ".csv";
335: fos = new FileOutputStream(sFilePath);
336: pwr = new PrintWriter(fos);
337: } catch (Exception ex) {
338: com.salmonllc.util.MessageLog
339: .writeErrorMessage(
340: "com.salmonllc.servlets.ConnectionMonitor.printLogInfo() ;Can not open output file.",
341: ex, this );
342: return false;
343: }
344:
345: StringBuffer sb = new StringBuffer();
346:
347: java.text.StringCharacterIterator sci = new java.text.StringCharacterIterator(
348: _sbFreeMemory.toString());
349: try {
350:
351: for (char c = sci.first(); c != java.text.CharacterIterator.DONE; c = sci
352: .next()) {
353: Character chr = new Character(c);
354: if (chr.equals(new Character(','))) {
355: pwr.println(sb.toString());
356: ;
357: sb = new StringBuffer();
358: } else
359: sb.append(chr);
360: }
361: } catch (Exception ex) {
362: com.salmonllc.util.MessageLog
363: .writeErrorMessage(
364: "com.salmonllc.servlets.ConnectionMonitor.printLogInfo() Iterator ;Can not open output file.",
365: ex, this );
366: return false;
367: } finally {
368: if (pwr != null) {
369: pwr.flush();
370: pwr.close();
371: }
372:
373: if (fos != null)
374: try {
375: fos.close();
376: } catch (Exception ex) {
377: }
378:
379: pwr = null;
380: fos = null;
381: }
382:
383: return true;
384:
385: }
386:
387: }
|