View Javadoc

1   package org.opensync.tools;
2   
3   import java.io.*;
4   import java.util.*;
5   import java.sql.*;
6   import java.net.*;
7   import javax.mail.*;
8   import javax.mail.internet.*;
9   import java.text.SimpleDateFormat;
10  import java.text.DecimalFormat;
11  
12  public final class Tracker extends Thread {
13      // Static Definitions
14      private static Tracker theTracker = null;
15      private static Hashtable hTabTrackIn  = new Hashtable();
16      private static Hashtable hTabTrackOut = new Hashtable();
17      private static Hashtable hTabSourceId = new Hashtable();
18      private static DecimalFormat _DF1,_DF2;
19      private static SimpleDateFormat _DTF;
20      private static long _USL_RESPONSE_TIME = 10000;
21      private static int _LOG_BATCH_COUNT = 20;
22      private static int _DBWRITER_WAIT_TIME = 900000;
23      private static long _REPORT_INTERVAL = 3600000;
24      private static String [] ITEMNAME = {"Process","ClassMethod"};
25      //
26      private boolean isDebug = false;
27      private boolean isActive = false;
28      private int logBatchCount;
29      private int dbWriterWaitTime;
30      private ConnectionPool pool = null;
31      private long reportInterval;
32      private String  applicationName;
33      privateong> String  packageId;
34      private long lastReportTimeMillis;
35      private long uslResponseTime;
36      private String localHost;
37      //
38      private boolean emailEnable;
39      private String  emailTransportProtocol;
40      private String  emailHost;
41      private String  emailUserId;
42      private String  emailPassword;
43      private String  emailRecipientFrom;
44      private String  emailRecipientTo;
45      private Session emailSession;
46  
47  
48      private Tracker() {
49      }
50  
51      public static void setUp(PoolManager poolMgr, String connectionName) {
52          printMessage("Tracker::setUp");
53          Connection conn = null;
54          SETUP_BLOCK:
55          try {
56              if (theTracker == null) {
57                  // Instantiate singleTon
58                  theTracker = new Tracker();
59                  theTracker.pool = poolMgr.getConnectionPool(connectionName);
60                  _DF1 = new DecimalFormat("000");
61                  _DF2 = new DecimalFormat("#,###,###,##0");
62                  _DTF = new SimpleDateFormat("MMM-dd, yyyy hh:mm:ss a");
63                  theTracker.localHost = InetAddress.getLocalHost().getHostName();
64                  conn = theTracker.pool.getConnection();
65                  String trackerMode = getTrackerParam(conn,"TRACKER_MODE").toUpperCase();
66                  if ((trackerMode.equals("FALSE") || (!trackerMode.equals("SPECIFIC") && !trackerMode.equals("ALL")))) {
67                      if(Utils.debug) System.out.println(_DTF.format(new java.util.Date(System.currentTimeMillis())) + ": Tracker is OFF");
68                      break SETUP_BLOCK;
69                  }
70  
71                  theTracker.applicationName = getTrackerParam(conn,"TRACKER_APPLICATION_NAME");
72                  theTracker.isDebug = translateBoolean(getTrackerParam(conn,"TRACKER_DEBUG_ENABLE"));
73  
74                  theTracker.packageId = getTrackerParam(conn,"TRACKER_PACKAGE_ID");
75                  if (theTracker.applicationName.equals("")) throw new Exception("TrackerException: Undefined application name");
76                  rong>if (theTracker.packageId.equals("")) throw new Exception("TrackerException: Undefined target package id");
77                  try {
78                      theTracker.logBatchCount = (new Integer(getTrackerParam(conn,"TRACKER_DBWRITE_BATCH_COUNT"))).intValue();
79                  } catch (Exception e) {
80                      theTracker.logBatchCount = _LOG_BATCH_COUNT;
81                  }
82                  try {
83                      theTracker.dbWriterWaitTime = (new Integer(getTrackerParam(conn,"TRACKER_DRIVER_WAIT_TIME"))).intValue();
84                  } catch (Exception e) {
85                      theTracker.dbWriterWaitTime = _DBWRITER_WAIT_TIME;
86                  }
87                  try {
88                      theTracker.reportInterval = (new Long(getTrackerParam(conn,"TRACKER_REPORT_INTERVAL"))).longValue();
89                  } catch (Exception e) {
90                      theTracker.reportInterval = _REPORT_INTERVAL;
91                  }
92                  try {
93                      theTracker.uslResponseTime = (new Long(getTrackerParam(conn,"TRACKER_USL_RESPONSE_TIME"))).longValue();
94                  } catch (Exception e) {
95                      theTracker.uslResponseTime = _USL_RESPONSE_TIME;
96                  }
97                  //
98                  theTracker.lastReportTimeMillis = System.currentTimeMillis();
99                  theTracker.emailEnable = translateBoolean(getTrackerParam(conn,"TRACKER_EMAIL_ENABLE"));
100                 if (theTracker.emailEnable) {
101                     theTracker.emailHost = getTrackerParam(conn,"TRACKER_EMAIL_HOST");
102                     theTracker.emailUserId = getTrackerParam(conn,"TRACKER_EMAIL_USERID");
103                     theTracker.emailPassword = getTrackerParam(conn,"TRACKER_EMAIL_PASSWORD");
104                     theTracker.emailRecipientFrom = getTrackerParam(conn,"TRACKER_EMAIL_RECIPIENT_FROM");
105                     theTracker.emailRecipientTo = getTrackerParam(conn,"TRACKER_EMAIL_RECIPIENT_TO");
106                     theTracker.emailTransportProtocol = getTrackerParam(conn,"TRACKER_EMAIL_TRANSPORT_PROTOCOL");
107                     if (theTracker.emailHost.equals("")
108                     ||  theTracker.emailRecipientFrom.equals("")
109                     ||  theTracker.emailRecipientTo.equals("")
110                     ||  theTracker.emailTransportProtocol.equals("")) {
111                         theTracker.emailEnable = false;
112                         throw new Exception("TrackerException: Incorrect Tracker Email setup");
113                     }
114                     Properties sysProps = System.getProperties();
115                     sysProps.put("mail.transport.protocol",theTracker.emailTransportProtocol);
116                     sysProps.put("mail." + theTracker.emailTransportProtocol + ".host",theTracker.emailHost);
117                     theTracker.emailSession = Session.getInstance(sysProps, null);
118                 }
119 
120                 // Start TrackerDriver Thread
121                 Thread trackerThread = new Thread(theTracker,"TrackerDriver");
122                 theTracker.isActive = true;
123                 trackerThread.start();
124                 if(Utils.debug) System.out.println(_DTF.format(new java.util.Date(System.currentTimeMillis())) + ": Tracker is ON");
125             }
126         } catch (Exception e) {
127             handleException(e);
128         } finally {
129             try {
130                 if (theTracker != null && theTracker.pool != null ) theTracker.pool.freeConnection(conn);
131             } catch (Exception e) {}
132         }
133     }
134 
135     public void run() {
136         try {
137             while (theTracker.isActive) {
138                 if (hTabTrackOut.size() == 0) {
139                     synchronized(theTracker) {
140                         wait(theTracker.dbWriterWaitTime);
141                     }
142                 }
143                 dbWriteTrackOut();
144                 cleanTrackIn();
145                 sendReport();
146             }// while loop
147         } catch (Exception e) {
148             handleException(e);
149         }
150     }
151 
152     public static void begin(String processItem, String uid, String comments) {
153         printMessage("Tracker::begin processItem,uid,comments");
154         if (theTracker == null || !theTracker.isActive) return;
155         boolean isBeginValid = false;
156         try {
157             if (processItem == null || processItem.trim().length() == 0) {
158                 throw new Exception("Undefined process item");
159             }
160             if (processItem.indexOf("?") != -1) {
161                 throw new Exception("Unidentified process item(" + processItem + ")");
162             }
163             isBeginValid = true;
164             printMessage("Tracker::begin begin is valid");
165         } catch (Exception e) {
166             printMessage(e.getMessage());
167         }
168 
169         try {
170             if (isBeginValid) {
171                 if (uid == null || uid.trim().length() == 0) {
172                     uid = "N/A";
173                 }
174                 Thread threadInstance = Thread.currentThread();
175                 // Create new TrackProcess & add to hashTable
176                 TrackProcess trackProcess = new TrackProcess(processItem,uid);
177                 synchronized (hTabTrackIn) {
178                     printMessage("Tracker::begin adding thread instance "+threadInstance);
179                     hTabTrackIn.put(threadInstance,trackProcess);
180                 }
181                 begin("");
182                 trackProcess.setComments(comments);
183             }
184         } catch (Exception e) {
185             handleException(e);
186         }
187     }
188 
189     public static void begin() {
190         printMessage("Tracker::begin");
191         begin("");
192     }
193 
194     public static void begin(String comments) {
195         printMessage("Tracker::begin comments");
196         try {
197             if (isActive()) {
198                 printMessage("Tracker::begin tracker active");
199                 Thread threadInstance = Thread.currentThread();
200                 TrackProcess trackProcess = null;
201                 String sourceMethod = findCaller(new Throwable());
202                 synchronized (hTabTrackIn) {
203                     trackProcess = (TrackProcess)hTabTrackIn.get(threadInstance);
204                 }
205                 if (trackProcess != null && !trackProcess.isEnd()) {
206                     String eventId = trackProcess.addTrackSourceMethod(sourceMethod,comments);
207                     printMessage(eventId + ":" + threadInstance.hashCode() + ":" + sourceMethod + ",begin");
208                 }
209             }else{
210               printMessage("Tracker::begin tracker not active");
211             }
212         } catch(Exception e){
213             handleException(e);
214         }
215     }
216 
217     public static void end() {
218         end("",null);
219     }
220 
221     public static void end(String comments) {
222         end(comments,null);
223     }
224 
225     public static void end(Exception methodException) {
226         end("",methodException);
227     }
228 
229     public static void end(Exception methodException, String comments) {
230         end(comments,methodException);
231     }
232 
233     public static void end(String comments, Exception methodException) {
234       printMessage("Tracker::end - comments="+comments);
235         if (!isActive()){
236           printMessage("Tracker::end = tracker is not active");
237           return;
238         }
239         try {
240             //Capture current system time, before doing anything else
241             long lTime = System.currentTimeMillis();
242             Thread threadInstance = Thread.currentThread();
243             if (hTabTrackIn.containsKey(threadInstance)) {
244                 printMessage("Tracker::end - got thread instance");
245                 TrackProcess trackProcess = (TrackProcess)hTabTrackIn.get(threadInstance);
246                 if (trackProcess.isHung()){
247                   printMessage("Tracker::end - hung");
248                   return;
249                 }
250                 String originSourceMethod = findCaller(new Throwable());
251                 trackProcess.end(lTime, originSourceMethod,methodException,comments);
252                 printMessage(trackProcess.processEventId() + ":" + threadInstance.hashCode() + ",end (level=" + trackProcess.level() + ")");
253                 if (trackProcess.isEnd()) {
254                     synchronized(hTabTrackOut) {
255                         printMessage("Tracker::end - putting track out");
256                         hTabTrackOut.put(trackProcess.processEventId(),trackProcess);
257                         printMessage("Tracker::end removing thread instance "+threadInstance);
258                         hTabTrackIn.remove(threadInstance);
259                     }
260                     printMessage(trackProcess.processEventId() + ":complete");
261                     theTracker.notifyDBWriter();
262                 }else{
263                   printMessage("Tracker::end - track process not done");
264                 }
265             }else{
266               printMessage("Tracker::end - could not get thread instance for "+threadInstance);
267             }
268         } catch(Exception e){
269             handleException(e);
270         }
271     }
272 
273     private synchronized void notifyDBWriter() throws Exception {
274         if (hTabTrackOut.size() >= theTracker.logBatchCount) {
275           theTracker.notify();
276         }
277     }
278 
279     private void cleanTrackIn() throws Exception {
280         Thread threadInstance;
281         TrackProcess trackProcess;
282         synchronized (hTabTrackIn) {
283             Enumeration enumKeys = hTabTrackIn.keys();
284             while (enumKeys.hasMoreElements()) {
285                 threadInstance = (Thread)enumKeys.nextElement();
286                 trackProcess = (TrackProcess) hTabTrackIn.get(threadInstance);
287                 // Check age of the entry, if it is more than 5 mins, delete it.
288                 if (trackProcess.isHung()) {
289                     printMessage("Tracker::cleanTrackIn removing thread instance "+threadInstance);
290                     hTabTrackIn.remove(threadInstance);
291                     printMessage(trackProcess.processEventId() + ":aged out");
292                 }
293             }
294         }
295     }
296 
297     private void sendReport() throws Exception {
298         long currentTimeMillis = System.currentTimeMillis();
299         if (currentTimeMillis >= theTracker.lastReportTimeMillis + theTracker.reportInterval) {
300             String reportText = createReport();
301             if (!reportText.equals("")) {
302                 theTracker.lastReportTimeMillis = currentTimeMillis;
303                 sendMail(theTracker.applicationName + "-Tracker Report [" + theTracker.localHost + "]", reportText);
304             }
305         }
306     }
307 
308     private String createReport() throws Exception {
309         Connection conn = null;
310         PreparedStatement pSelectStmt = null;
311         PreparedStatement pUpdateStmt = null;
312         ResultSet rSet = null;
313         Timestamp ts = null;
314         Exception createReportException = null;
315         boolean resetReportMode = false;
316         boolean hdrLine = false;
317         StringBuffer reportTextBuffer = new StringBuffer("");
318         char itemType = ' ';
319         long avgResponseTime = 0;
320         //
321         try {
322             conn = theTracker.pool.getConnection();
323             conn.setAutoCommit(false);
324             hdrLine = false;
325             itemType = ' ';
326             pSelectStmt = conn.prepareStatement("SELECT ITEM_TYPE, TRACK_ITEM, AVG_RESPONSE_TIME " +
327                                                 "FROM TRACKER WHERE ITEM_TYPE <> 'C' " +
328                                                 "AND AVG_RESPONSE_TIME > ? " +
329                                                 "AND REPORT_MODE = 1 ORDER BY ITEM_TYPE DESC");
330             pSelectStmt.setLong(1,theTracker.uslResponseTime);
331             rSet = pSelectStmt.executeQuery();
332             while (rSet.next()) {
333                 resetReportMode = true;
334                 if (rSet.getString(1).charAt(0) != itemType) {
335                     reportTextBuffer.append(itemName(rSet.getString(1)) + ":\n");
336                     itemType = rSet.getString(1).charAt(0);
337                 }
338                 if (!hdrLine) {
339                     reportTextBuffer.append("\nAverage response time exceeds upper spec limit (USL) for the following items:\n\n");
340                     hdrLine = true;
341                 }
342                 reportTextBuffer.append(rSet.getString(2) + ",");
343                 reportTextBuffer.append(_DF2.format(rSet.getLong(3)/1000) + " secs\n");
344             }
345             if (hdrLine) reportTextBuffer.append("--End Of List--\n");
346             try { rSet.close(); } catch (Exception e) {}
347             try { pSelectStmt.close(); } catch (Exception e) {}
348 
349             // Reset reportMode
350             if (resetReportMode) {
351                 pUpdateStmt = conn.prepareStatement("UPDATE TRACKER SET REPORT_MODE = 2 " +
352                                                     "WHERE ITEM_TYPE <> 'C' " +
353                                                     "AND AVG_RESPONSE_TIME > ? " +
354                                                     "AND REPORT_MODE = 1");
355                 pUpdateStmt.setLong(1,theTracker.uslResponseTime);
356                 pUpdateStmt.executeUpdate();
357                 pUpdateStmt.close();
358             }
359             //
360 
361             hdrLine = false;
362             itemType = ' ';
363             pSelectStmt = conn.prepareStatement("SELECT LAST_ERROR_TIMESTAMP, ITEM_TYPE, TRACK_ITEM, LAST_ERROR_MSG " +
364                                                 "FROM TRACKER WHERE LAST_ERROR_TIMESTAMP > ? ORDER BY ITEM_TYPE DESC");
365             pSelectStmt.setLong(1,theTracker.lastReportTimeMillis);
366             rSet = pSelectStmt.executeQuery();
367             while (rSet.next()) {
368                 if (!hdrLine) {
369                     reportTextBuffer.append("\nException occurred for following items:\n\n");
370                     hdrLine = true;
371                 }
372                 if (rSet.getString(2).charAt(0) != itemType) {
373                     reportTextBuffer.append(itemName(rSet.getString(2)) + ":\n");
374                     itemType = rSet.getString(2).charAt(0);
375                 }
376                 ts = new Timestamp(rSet.getLong(1));
377                 reportTextBuffer.append(ts + " - " + rSet.getString(3) + "," + rSet.getString(3));
378             }
379             if (hdrLine) reportTextBuffer.append("--End Of List--\n");
380             try { rSet.close(); } catch (Exception e) {}
381             try { pSelectStmt.close(); } catch (Exception e) {}
382             //
383             hdrLine = false;
384             itemType = ' ';
385             pSelectStmt = conn.prepareStatement("SELECT BEGIN_TIMESTAMP, TRACKER_LOG.ITEM_TYPE, EVENT_ITEM, USER_ID, " +
386                                                 "RESPONSE_TIME FROM TRACKER_LOG, TRACKER " +
387                                                 "WHERE BEGIN_TIMESTAMP > ? " +
388                                                 "  AND TRACKER_LOG.ITEM_TYPE = TRACKER.ITEM_TYPE " +
389                                                 "  AND TRACKER_LOG.EVENT_ITEM = TRACKER.TRACK_ITEM " +
390                                                 "  AND TRACKER_LOG.RESPONSE_TIME > ? " +
391                                                 "  ORDER BY TRACKER_LOG.ITEM_TYPE DESC,TRACKER_LOG.BEGIN_TIMESTAMP");
392             pSelectStmt.setLong(1,theTracker.lastReportTimeMillis);
393             pSelectStmt.setLong(2,theTracker.uslResponseTime);
394             rSet = pSelectStmt.executeQuery();
395             while (rSet.next()) {
396                 if (!hdrLine) {
397                     reportTextBuffer.append("\nResponse time exceeded upper spec limit(USL) for the following events:\n\n");
398                     hdrLine = true;
399                 }
400                 if (rSet.getString(2).charAt(0) != itemType) {
401                     reportTextBuffer.append(itemName(rSet.getString(2)) + ":\n");
402                     itemType = rSet.getString(2).charAt(0);
403                 }
404                 ts = new Timestamp(rSet.getLong(1));
405                 reportTextBuffer.append(ts + " - " + rSet.getString(3) + ",User=" + rSet.getString(4) + ",");
406                 reportTextBuffer.append(_DF2.format(rSet.getLong(5)/1000) + " secs\n");
407             }
408             if (hdrLine) reportTextBuffer.append("--End Of List--\n");
409             try { rSet.close(); } catch (Exception e) {}
410             try { pSelectStmt.close(); } catch (Exception e) {}
411             //
412             hdrLine = false;
413             itemType = ' ';
414             pSelectStmt = conn.prepareStatement("SELECT LAST_ERROR_TIMESTAMP, ITEM_TYPE, TRACK_ITEM, LAST_ERROR_MSG " +
415                                                 "FROM TRACKER WHERE LAST_ERROR_TIMESTAMP > ? ORDER BY ITEM_TYPE DESC");
416             pSelectStmt.setLong(1,theTracker.lastReportTimeMillis);
417             rSet = pSelectStmt.executeQuery();
418             while (rSet.next()) {
419                 if (!hdrLine) {
420                     reportTextBuffer.append("\nExceptions :\n\n");
421                     hdrLine = true;
422                 }
423                 if (rSet.getString(2).charAt(0) != itemType) {
424                     reportTextBuffer.append(itemName(rSet.getString(2)) + ":\n");
425                     itemType = rSet.getString(2).charAt(0);
426                 }
427                 ts = new Timestamp(rSet.getLong(1));
428                 reportTextBuffer.append(ts + " - " + rSet.getString(3) + ","+rSet.getString(4)+"\n");
429             }
430             if (hdrLine) reportTextBuffer.append("--End Of List--\n");
431             try { rSet.close(); } catch (Exception e) {}
432             try { pSelectStmt.close(); } catch (Exception e) {}
433         } catch (Exception e) {
434             createReportException = e;
435             try { conn.rollback(); } catch (Exception re) {}
436             handleException(e);
437         } finally {
438             try { rSet.close(); } catch (Exception e) {}
439             try { pSelectStmt.close(); } catch (Exception e) {}
440             try { if (createReportException == null) conn.commit(); } catch (Exception e) {}
441             try { theTracker.pool.freeConnection(conn); } catch (Exception e) {}
442         }
443         return reportTextBuffer.toString();
444     }
445 
446     private String itemName(String itemType) {
447         String itemName = null;
448         if (itemType.equals("P")) itemName = ITEMNAME[0];
449         else if (itemType.equals("M")) itemName = ITEMNAME[1];
450         return itemName;
451     }
452 
453     private void dbWriteTrackOut() throws Exception {
454         String processEventId;
455         TrackProcess trackProcess;
456         Enumeration enumKeys;
457         synchronized (hTabTrackOut) {
458             enumKeys = hTabTrackOut.keys();
459         }
460         while (enumKeys.hasMoreElements()) {
461             processEventId = (String)enumKeys.nextElement();
462             synchronized (hTabTrackOut) {
463                 trackProcess = (TrackProcess) hTabTrackOut.get(processEventId);
464             }
465             if (trackProcess == null) {
466                 hTabTrackOut.remove(processEventId);
467                 continue;
468             }
469 
470             logToDB(trackProcess);
471 
472             synchronized (hTabTrackOut) {
473                 hTabTrackOut.remove(processEventId);
474                 printMessage(processEventId + ":dumped");
475             }
476         }
477     }
478 
479     private void logToDB(TrackProcess trackProcess)
480       throws Exception {
481         Connection conn = null;
482         PreparedStatement pSelectStmt = null;
483         PreparedStatement pUpdateStmt = null;
484         PreparedStatement pInsertStmt = null;
485         PreparedStatement pInsertLog  = null;
486         PreparedStatement pSelectLog  = null;
487         PreparedStatement pUpdateLog  = null;
488         ResultSet rSet = null;
489         Exception logToDBException = null;
490         TrackSourceMethod trackSourceMethod = null;
491 
492         try {
493             conn = theTracker.pool.getConnection();
494             conn.setAutoCommit(false);
495             pSelectStmt = conn.prepareStatement("SELECT HIGH_RESPONSE_TIME,AVG_RESPONSE_TIME,USAGE_COUNT,PASS_COUNT,THROW_COUNT,ERROR_COUNT,HIGH_RESPONSE_COUNT,LAST_EVENT_ID,LAST_EVENT_TIMESTAMP,LAST_ERROR_TIMESTAMP,LAST_ERROR_MSG,LAST_ERROR_TRACK_ITEM,LAST_ERROR_EVENT_ID,REPORT_MODE FROM TRACKER " +
496                                                 "WHERE TRACK_ITEM = ? AND ITEM_TYPE = ?");
497             pInsertStmt = conn.prepareStatement("INSERT INTO TRACKER (TRACK_ITEM,ITEM_TYPE,LOG_MODE,REPORT_MODE) " +
498                                                 "VALUES(?,?,?,?)");
499             pUpdateStmt = conn.prepareStatement("UPDATE TRACKER SET HIGH_RESPONSE_TIME = ?," +
500                                                 "AVG_RESPONSE_TIME = ?, " +
501                                                 "USAGE_COUNT = ?, " +
502                                                 "PASS_COUNT = ?, " +
503                                                 "THROW_COUNT = ?, " +
504                                                 "ERROR_COUNT = ?, " +
505                                                 "HIGH_RESPONSE_COUNT = ?, " +
506                                                 "LAST_EVENT_ID = ?, " +
507                                                 "LAST_EVENT_TIMESTAMP = ?, " +
508                                                 "LAST_ERROR_TIMESTAMP = ?, " +
509                                                 "LAST_ERROR_MSG = ?, " +
510                                                 "LAST_ERROR_TRACK_ITEM = ?, " +
511                                                 "LAST_ERROR_EVENT_ID = ?, " +
512                                                 "REPORT_MODE = ? " +
513                                                 "WHERE TRACK_ITEM = ? AND ITEM_TYPE = ?");
514             pInsertLog  = conn.prepareStatement("INSERT INTO TRACKER_LOG " +
515                                                 "(EVENT_ID,EVENT_ITEM,ITEM_TYPE,USER_ID,PROCESS_ID,PROCESS_ITEM,CALLER_ID,ACTION_LEVEL,BEGIN_TIMESTAMP,END_TIMESTAMP,RESPONSE_TIME,ERROR_MSG,ERROR_STATUS,COMMENTS) " +
516                                                 "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
517             pSelectLog  = conn.prepareStatement("SELECT BEGIN_TIMESTAMP,END_TIMESTAMP,RESPONSE_TIME,ERROR_MSG,ERROR_STATUS " +
518                                                 "FROM TRACKER_LOG WHERE EVENT_ID = ?");
519             pUpdateLog  = conn.prepareStatement("UPDATE TRACKER_LOG SET BEGIN_TIMESTAMP = ?," +
520                                                 "END_TIMESTAMP = ?," +
521                                                 "RESPONSE_TIME = ?," +
522                                                 "ERROR_MSG = ?," +
523                                                 "ERROR_STATUS = ? " +
524                                                 "WHERE EVENT_ID = ?");
525 
526             //
527             dbWriteProcess(trackProcess,pInsertLog,pSelectStmt,pUpdateStmt,pInsertStmt);
528             //
529 
530             // Process each source method call in the threadprocess
531             ArrayList arrListTrackSourceMethods = trackProcess.arrListTrackSourceMethods();
532             for (int i=0;i<arrListTrackSourceMethods.size();i++) {
533                 trackSourceMethod = (TrackSourceMethod)arrListTrackSourceMethods.get(i);
534                 if (trackSourceMethod == null) continue;
535                 if (!trackSourceMethod.isEnd()) {
536                     printMessage(trackSourceMethod.sourceMethodEventId() +  " " +
537                                  trackSourceMethod.sourceMethod() + ",not ended.");
538                     continue;
539                 }
540                 //
541                 dbWriteSourceMethod(trackSourceMethod,pInsertLog,pSelectStmt,pUpdateStmt,pInsertStmt);
542                 //
543             } // End of for loop
544 
545         } catch (Exception e) {
546             conn.rollback();
547             logToDBException = e;
548             throw e;
549         } finally {
550             try { rSet.close(); } catch (Exception e) {}
551             try { pSelectStmt.close(); } catch (Exception e) {}
552             try { pInsertStmt.close(); } catch (Exception e) {}
553             try { pUpdateStmt.close(); } catch (Exception e) {}
554             try { pSelectLog.close(); } catch (Exception e) {}
555             try { pInsertLog.close(); } catch (Exception e) {}
556             try { pUpdateLog.close(); } catch (Exception e) {}
557             try { if (logToDBException == null) conn.commit(); } catch (Exception e) {}
558             try { theTracker.pool.freeConnection(conn); } catch (Exception e) {}
559         }
560     }
561 
562     private void dbWriteProcess(TrackProcess trackProcess,
563                                 PreparedStatement pInsertLog,
564                                 PreparedStatement pSelectStmt,
565                                 PreparedStatement pUpdateStmt,
566                                 PreparedStatement pInsertStmt)
567         throws Exception {
568         ResultSet rSet = null;
569         long highResponseTime = 0;
570         long avgResponseTime = 0;
571         long usageCount = 0;
572         long passCount = 0;
573         long throwCount = 0;
574         long exceptionCount = 0;
575         long highResponseCount = 0;
576         long eventTimestamp = 0;
577         long exceptionTimestamp = 0;
578         short reportMode = 0;
579         Exception exception = null;
580         String exceptionMessage = null;
581         String exceptionTrackItem = null;
582         String exceptionEventId = null;
583         String eventId = null;
584 
585         pInsertLog.setString(1,trackProcess.processEventId());
586         pInsertLog.setString(2,trackProcess.processItem());
587         pInsertLog.setString(3,"P");
588         pInsertLog.setString(4,trackProcess.uid());
589         pInsertLog.setString(5,"P");
590         pInsertLog.setString(6,trackProcess.processItem());
591         pInsertLog.setString(7,"");
592         pInsertLog.setInt(8,0);
593         pInsertLog.setLong(9,trackProcess.beginTimestamp());
594         pInsertLog.setLong(10,trackProcess.endTimestamp());
595         pInsertLog.setLong(11,trackProcess.responseTime());
596         pInsertLog.setString(12,trackProcess.exceptionMessage());
597         pInsertLog.setShort(13,trackProcess.exceptionStatus());
598         pInsertLog.setString(14,trackProcess.comments());
599         pInsertLog.executeUpdate();
600         printMessage("Log Entry Process : " + trackProcess.processEventId() + ":" + trackProcess.processItem());
601 
602         //Update/Create Tracker Summary Table
603 
604         pSelectStmt.setString(1,trackProcess.processItem());
605         pSelectStmt.setString(2,"P");
606         rSet = pSelectStmt.executeQuery();
607         if (!rSet.next()) {
608             pInsertStmt.setString(1,trackProcess.processItem());
609             pInsertStmt.setString(2,"P");
610             pInsertStmt.setShort(3,(short)1);
611             pInsertStmt.setShort(4,(short)0);
612             pInsertStmt.executeUpdate();
613             printMessage("Track Entry Process : " + trackProcess.processItem());
614             rSet.close();
615             rSet = pSelectStmt.executeQuery(); //Refire Query
616             if (!rSet.next()) throw new Exception ("TrackerException: Unable to locate " + trackProcess.processItem());
617         }
618         highResponseTime = rSet.getLong(1);
619         avgResponseTime = rSet.getLong(2);
620         usageCount = rSet.getLong(3);
621         passCount = rSet.getLong(4);
622         exceptionCount = rSet.getLong(6);
623         highResponseCount = rSet.getLong(7);
624         eventId = rSet.getString(8);
625         eventTimestamp = rSet.getLong(9);
626         exceptionTimestamp = rSet.getLong(10);
627         exceptionMessage = rSet.getString(11);
628         exceptionTrackItem = rSet.getString(12);
629         exceptionEventId = rSet.getString(13);
630         reportMode = rSet.getShort(14);
631         if ((trackProcess.endTimestamp() != 0) &&
632             (eventTimestamp == 0 || eventTimestamp < trackProcess.endTimestamp())) {
633             eventId = trackProcess.processEventId();
634             eventTimestamp = trackProcess.endTimestamp();
635         }
636         if (trackProcess.exception() != null) {
637             exceptionCount++;
638             if (exceptionTimestamp == 0 || exceptionTimestamp < trackProcess.exceptionTimestamp()) {
639                 exceptionTimestamp = trackProcess.exceptionTimestamp();
640                 exceptionMessage = trackProcess.exceptionMessage();
641                 exceptionTrackItem = trackProcess.exceptionTrackItem();
642                 exceptionEventId = trackProcess.exceptionEventId();
643             }
644         } else {
645             passCount++;
646             avgResponseTime = ((rSet.getLong(2) * rSet.getLong(4)) + trackProcess.responseTime()) / (passCount);
647             if (trackProcess.responseTime() > highResponseTime) highResponseTime = trackProcess.responseTime();
648             if (trackProcess.responseTime() > theTracker.uslResponseTime) highResponseCount++;
649             if (reportMode == 0 && theTracker.uslResponseTime < avgResponseTime) reportMode = 1;
650             if (reportMode > 0 && avgResponseTime <= theTracker.uslResponseTime) reportMode = 0;
651         }
652 
653         usageCount++;
654         pUpdateStmt.setLong(1,highResponseTime);
655         pUpdateStmt.setLong(2,avgResponseTime);
656         pUpdateStmt.setLong(3,usageCount);
657         pUpdateStmt.setLong(4,passCount);
658         pUpdateStmt.setLong(5,0);  // throwCount not applicable to process tracker entry
659         pUpdateStmt.setLong(6,exceptionCount);
660         pUpdateStmt.setLong(7,highResponseCount);
661         pUpdateStmt.setString(8,eventId);
662         pUpdateStmt.setLong(9,eventTimestamp);
663         pUpdateStmt.setLong(10,exceptionTimestamp);
664         pUpdateStmt.setString(11,exceptionMessage);
665         pUpdateStmt.setString(12,exceptionTrackItem);
666         pUpdateStmt.setString(13,exceptionEventId);
667         pUpdateStmt.setShort(14,reportMode);
668         pUpdateStmt.setString(15,trackProcess.processItem());
669         pUpdateStmt.setString(16,"P");
670         pUpdateStmt.executeUpdate();
671         printMessage("Track Update Process : " + trackProcess.processItem());
672     }
673 
674     private void dbWriteSourceMethod(TrackSourceMethod trackSourceMethod,
675                                      PreparedStatement pInsertLog,
676                                      PreparedStatement pSelectStmt,
677                                      PreparedStatement pUpdateStmt,
678                                      PreparedStatement pInsertStmt)
679         throws Exception {
680 
681         ResultSet rSet = null;
682         long highResponseTime = 0;
683         long avgResponseTime = 0;
684         long usageCount = 0;
685         long passCount = 0;
686         long throwCount = 0;
687         long highResponseCount = 0;
688         long sourceHighResponseCount = 0;
689         long exceptionCount = 0;
690         long exceptionTimestamp = 0;
691         long eventTimestamp = 0;
692         short reportMode = 0;
693         Exception exception = null;
694         String exceptionMessage = null;
695         String exceptionTrackItem = null;
696         String exceptionEventId = null;
697         String eventId = null;
698 
699         short exceptionStatus = 0;
700 
701         if (trackSourceMethod.exceptionMessage() != null) exceptionStatus = 1;
702         pInsertLog.setString(1,trackSourceMethod.sourceMethodEventId());
703         pInsertLog.setString(2,trackSourceMethod.sourceMethod());
704         pInsertLog.setString(3,"M");
705         pInsertLog.setString(4,trackSourceMethod.uid());
706         pInsertLog.setString(5,trackSourceMethod.processEventId());
707         pInsertLog.setString(6,trackSourceMethod.processItem());
708         pInsertLog.setString(7,trackSourceMethod.callerEventId());
709         pInsertLog.setInt(8,trackSourceMethod.level());
710         pInsertLog.setLong(9,trackSourceMethod.beginTimestamp());
711         pInsertLog.setLong(10,trackSourceMethod.endTimestamp());
712         pInsertLog.setLong(11,trackSourceMethod.responseTime());
713         pInsertLog.setString(12,trackSourceMethod.exceptionMessage());
714         pInsertLog.setShort(13,trackSourceMethod.exceptionStatus());
715         pInsertLog.setString(14,trackSourceMethod.comments());
716         pInsertLog.executeUpdate();
717         printMessage("Log Entry SourceMethod : " + trackSourceMethod.sourceMethodEventId() + ":" + trackSourceMethod.sourceMethod());
718 
719         // Update/Create class method record
720         pSelectStmt.setString(1,trackSourceMethod.sourceMethod());
721         pSelectStmt.setString(2,"M");
722         rSet = pSelectStmt.executeQuery();
723         if (!rSet.next()) {
724             pInsertStmt.setString(1,trackSourceMethod.sourceMethod());
725             pInsertStmt.setString(2,"M");
726             pInsertStmt.setShort(3,(short)1);
727             pInsertStmt.setShort(4,(short)0);
728             pInsertStmt.executeUpdate();
729             printMessage("Track Entry SourceMethod : " + trackSourceMethod.sourceMethod());
730             rSet.close();
731             rSet = pSelectStmt.executeQuery(); //Refire Query
732             if (!rSet.next()) throw new Exception ("TrackerException: Unable to locate " + trackSourceMethod.sourceMethod());
733         }
734 
735         highResponseTime = rSet.getLong(1);
736         avgResponseTime = rSet.getLong(2);
737         usageCount = rSet.getLong(3);
738         passCount = rSet.getLong(4);
739         throwCount = rSet.getLong(5);
740         exceptionCount = rSet.getLong(6);
741         highResponseCount = rSet.getLong(7);
742         exceptionTimestamp = rSet.getLong(10);
743         exceptionMessage = rSet.getString(11);
744         exceptionTrackItem = rSet.getString(12);
745         exceptionEventId = rSet.getString(13);
746         reportMode = rSet.getShort(14);
747         usageCount++;
748         //
749         if (trackSourceMethod.exception() != null) {
750             if (trackSourceMethod.exceptionStatus() == 1) {
751                 exceptionCount++;
752                 exceptionTimestamp = trackSourceMethod.exceptionTimestamp();
753                 exceptionMessage = trackSourceMethod.exceptionMessage();
754                 exceptionTrackItem = trackSourceMethod.exceptionSourceMethod();
755                 exceptionEventId = trackSourceMethod.exceptionEventId();
756             }
757             else {
758                 throwCount++;
759             }
760         } else {
761             passCount++;
762             avgResponseTime = ((rSet.getLong(2) * rSet.getLong(4)) + trackSourceMethod.responseTime()) / (passCount);
763             if (trackSourceMethod.responseTime() > highResponseTime) highResponseTime = trackSourceMethod.responseTime();
764             if (trackSourceMethod.responseTime() > theTracker.uslResponseTime) { highResponseCount++; sourceHighResponseCount = 1; }
765             if (reportMode == 0 && theTracker.uslResponseTime < avgResponseTime) reportMode = 1;
766             if (reportMode > 0 && avgResponseTime <= theTracker.uslResponseTime) reportMode = 0;
767         }
768         pUpdateStmt.setLong(1,highResponseTime);
769         pUpdateStmt.setLong(2,avgResponseTime);
770         pUpdateStmt.setLong(3,usageCount);
771         pUpdateStmt.setLong(4,passCount);
772         pUpdateStmt.setLong(5,throwCount);
773         pUpdateStmt.setLong(6,exceptionCount);
774         pUpdateStmt.setLong(7,highResponseCount);
775         pUpdateStmt.setString(8,trackSourceMethod.sourceMethodEventId());
776         pUpdateStmt.setLong(9,trackSourceMethod.beginTimestamp());
777         pUpdateStmt.setLong(10,exceptionTimestamp);
778         pUpdateStmt.setString(11,exceptionMessage);
779         pUpdateStmt.setString(12,exceptionTrackItem);
780         pUpdateStmt.setString(13,exceptionEventId);
781         pUpdateStmt.setShort(14,reportMode);
782         pUpdateStmt.setString(15,trackSourceMethod.sourceMethod());
783         pUpdateStmt.setString(16,"M");
784         pUpdateStmt.executeUpdate();
785         printMessage("Track Update SourceMethod : " + trackSourceMethod.sourceMethod());
786 
787         // Close ResultSet
788         try { rSet.close(); } catch (Exception e) {}
789 
790         // Update class definition master record
791         pSelectStmt.setString(1,trackSourceMethod.sourceId());
792         pSelectStmt.setString(2,"C");
793         rSet = pSelectStmt.executeQuery();
794         if (!rSet.next()) {
795             pInsertStmt.setString(1,trackSourceMethod.sourceId());
796             pInsertStmt.setString(2,"C");
797             pInsertStmt.setShort(3,(short)1); // set logMode default to 1
798             pInsertStmt.setShort(4,(short)0); // reportMode not applicable at class row
799             pInsertStmt.executeUpdate();
800             printMessage("Track Entry Class : " + trackSourceMethod.sourceId());
801             rSet.close();
802             rSet = pSelectStmt.executeQuery(); //Refire Query
803             if (!rSet.next()) throw new Exception ("TrackerException: Unable to locate " + trackSourceMethod.sourceId());
804         }
805 
806         usageCount = rSet.getLong(4);
807         passCount = rSet.getLong(5);
808         throwCount = rSet.getLong(6);
809         exceptionCount = rSet.getLong(6);
810         highResponseCount = rSet.getLong(7);
811         exceptionTimestamp = rSet.getLong(10);
812         exceptionMessage = rSet.getString(11);
813         exceptionTrackItem = rSet.getString(12);
814         exceptionEventId = rSet.getString(13);
815         usageCount++;
816         if (trackSourceMethod.exception() != null) {
817             if (trackSourceMethod.exceptionStatus() == 1) {
818                 exceptionCount++;
819                 exceptionMessage = trackSourceMethod.exceptionMessage();
820                 exceptionTimestamp = trackSourceMethod.exceptionTimestamp();
821                 exceptionTrackItem = trackSourceMethod.exceptionSourceMethod();
822                 exceptionEventId = trackSourceMethod.exceptionEventId();
823             } else {
824                 throwCount++;
825             }
826         } else {
827             passCount++;
828             highResponseCount += sourceHighResponseCount;
829         }
830         pUpdateStmt.setLong(1,0); // response time not applicable at class row
831         pUpdateStmt.setLong(2,0);
832         pUpdateStmt.setLong(3,usageCount);
833         pUpdateStmt.setLong(4,passCount);
834         pUpdateStmt.setLong(5,throwCount);
835         pUpdateStmt.setLong(6,exceptionCount);
836         pUpdateStmt.setLong(7,highResponseCount);
837         pUpdateStmt.setString(8,trackSourceMethod.sourceMethodEventId());
838         pUpdateStmt.setLong(9,trackSourceMethod.beginTimestamp());
839         pUpdateStmt.setLong(10,exceptionTimestamp);
840         pUpdateStmt.setString(11,exceptionMessage);
841         pUpdateStmt.setString(12,exceptionTrackItem);
842         pUpdateStmt.setString(13,exceptionEventId);
843         pUpdateStmt.setShort(14,(short)0);
844         pUpdateStmt.setString(15,trackSourceMethod.sourceId());
845         pUpdateStmt.setString(16,"C");
846         pUpdateStmt.executeUpdate();
847         printMessage("Track Update Class : " + trackSourceMethod.sourceId());
848 
849         // Close ResultSet
850         try { rSet.close(); } catch (Exception e) {}
851 
852     }
853 
854     private static String getTrackerParam(Connection conn, String paramName) {
855         String paramValue;
856         PreparedStatement pStmt = null;
857         ResultSet rSet = null;
858         try {
859             pStmt = conn.prepareStatement("SELECT PROP_VALUE FROM TRACKER_PROP WHERE PROP_NAME = ?");
860             pStmt.setString(1,paramName);
861             rSet = pStmt.executeQuery();
862             if (rSet.next()) {
863                 paramValue = rSet.getString(1);
864                 if (paramValue == null) paramValue = new String("");
865             } else {
866                 paramValue = new String("");
867             }
868         } catch (Exception e) {
869             paramValue = new String("");
870         } finally {
871             try { rSet.close(); } catch(Exception e) {}
872             try { pStmt.close(); } catch(Exception e) {}
873         }
874         return paramValue.trim();
875     }
876 
877     public static boolean isActive() {
878         boolean isFlag = false;
879         if (theTracker != null) {
880           isFlag = theTracker.isActive;
881         }
882         return isFlag;
883     }
884 
885     public static boolean isDebug() {
886         boolean isFlag = false;
887         if (theTracker != null) {
888           isFlag = theTracker.isDebug;
889         }
890         return isFlag;
891     }
892 
893     private final static void sendMail(String mailContext) throws Exception {
894         sendMail(new String(mailContext),new String(mailContext));
895     }
896 
897     private final static void sendMail(String mailSubject, String mailText) throws Exception {
898         if (!theTracker.emailEnable) return;
899         String toMailAddress = null;
900         Message.RecipientType recipientType = Message.RecipientType.TO;
901         Message msg = new MimeMessage(theTracker.emailSession);
902         mailText = mailHeader() + mailText;
903         msg.setContent(mailText,"text/plain");
904         msg.setFrom(new InternetAddress(theTracker.emailRecipientFrom,theTracker.applicationName + ":TRACKER"));
905         msg.setSubject(mailSubject);
906         StringTokenizer addressList = new StringTokenizer(theTracker.emailRecipientTo,";");
907         while (addressList.hasMoreTokens()) {
908             toMailAddress = addressList.nextToken();
909             if (toMailAddress == null || toMailAddress.equals("")) continue;
910             Address addressTo = new InternetAddress (toMailAddress);
911             msg.addRecipient(recipientType,addressTo);
912             recipientType = Message.RecipientType.CC;
913         }
914         Transport transport = theTracker.emailSession.getTransport(theTracker.emailTransportProtocol);
915         transport.connect(theTracker.emailHost,theTracker.emailUserId,theTracker.emailPassword);
916         transport.send(msg);
917     }
918 
919     private static final String mailHeader() throws Exception {
920         String mailHeader = "";
921         String timeStamp = null;
922         SimpleDateFormat formatter = new SimpleDateFormat("MMM-dd-yyyy HH:mm:ss");
923         timeStamp = formatter.format(new java.util.Date());
924         mailHeader = "** PLEASE DO NOT REPLY TO THIS EMAIL **\n\n"
925                    + "=======================================================================\n"
926                    + "This is a notification from TRACKER. \n"
927                    + "Mail dispatched : " + timeStamp + "\n"
928                    + "=======================================================================\n";
929         return mailHeader;
930     }
931 
932     public static String findCaller(Throwable t) throws Exception {
933         StringBuffer sbLine = new StringBuffer("");
934         // Generate a stack trace and capture it into a string
935         StringWriter stringWriter = new StringWriter();
936         PrintWriter writer = new PrintWriter(stringWriter);
937         t.printStackTrace(writer);
938         String stackOutput = stringWriter.toString();
939 
940         // Split the stack trace up by lines, look for the non-Tracker class
941         StringTokenizer st = new StringTokenizer(stackOutput,"\n");
942         String tokenLine = null;
943         while (st.hasMoreTokens()) {
944             tokenLine = st.nextToken();
945             // Check if the line is not of the Tracker package.
946             if (tokenLine.indexOf(theTracker.packageId) < 0) continue;
947             if (tokenLine.indexOf("Tracker") >= 0) continue;
948             sbLine.append(tokenLine.substring(tokenLine.indexOf(theTracker.packageId)));
949             break;
950         }
951         int lPoint = 0;
952         lPoint = sbLine.toString().indexOf("(");
953         if (lPoint > 0) {
954             sbLine.delete(lPoint,sbLine.length());
955         }
956         if (sbLine.length() > 0) {
957             lPoint = sbLine.toString().lastIndexOf(".");
958             sbLine.setCharAt(lPoint,':');
959         }
960     return sbLine.toString();
961     }
962 
963 
964     private static boolean translateBoolean(String sBoolean) {
965       if (sBoolean == null) {
966           return false;
967       }
968       if (sBoolean.equalsIgnoreCase("Y")
969       ||  sBoolean.equalsIgnoreCase("Yes")
970       ||  sBoolean.equals("1")
971       ||  sBoolean.equalsIgnoreCase("True")) {
972           return true;
973       } else {
974           return false;
975       }
976     }
977 
978     private static void handleException(Exception e) {
979         //Important: Set tracker off
980         if (theTracker != null) {
981             theTracker.isActive = false;
982         }
983         if (e.getMessage() != null
984             && e.getMessage().length() > 16
985             && e.getMessage().indexOf("TrackerException") != -1) {
986             System.out.println(e.getMessage());
987         } else {
988             e.printStackTrace();
989         }
990         if (!theTracker.isActive) {
991             System.out.println(_DTF.format(new java.util.Date(System.currentTimeMillis())) + ": Tracker is OFF");
992         }
993     }
994 
995     private static void printMessage(String msg) {
996         if (isDebug()) {
997             System.out.println("Tracker::" + msg);
998         }
999     }
1000 }