Return-Path: Delivered-To: apmail-portals-jetspeed-dev-archive@www.apache.org Received: (qmail 66328 invoked from network); 3 Nov 2005 18:31:10 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 3 Nov 2005 18:31:10 -0000 Received: (qmail 8129 invoked by uid 500); 3 Nov 2005 18:31:07 -0000 Delivered-To: apmail-portals-jetspeed-dev-archive@portals.apache.org Received: (qmail 8095 invoked by uid 500); 3 Nov 2005 18:31:07 -0000 Mailing-List: contact jetspeed-dev-help@portals.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Jetspeed Developers List" Delivered-To: mailing list jetspeed-dev@portals.apache.org Received: (qmail 8084 invoked by uid 99); 3 Nov 2005 18:31:07 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 03 Nov 2005 10:31:07 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Thu, 03 Nov 2005 10:31:01 -0800 Received: (qmail 65285 invoked by uid 65534); 3 Nov 2005 18:30:27 -0000 Message-ID: <20051103183027.65284.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r330602 - /portals/jetspeed-2/trunk/components/statistics/src/java/org/apache/jetspeed/statistics/impl/PortalStatisticsImpl.java Date: Thu, 03 Nov 2005 18:30:27 -0000 To: jetspeed-dev@portals.apache.org From: taylor@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: taylor Date: Thu Nov 3 10:30:16 2005 New Revision: 330602 URL: http://svn.apache.org/viewcvs?rev=330602&view=rev Log: http://issues.apache.org/jira/browse/JS2-362 Implemented database support for statistics component Modified: portals/jetspeed-2/trunk/components/statistics/src/java/org/apache/jetspeed/statistics/impl/PortalStatisticsImpl.java Modified: portals/jetspeed-2/trunk/components/statistics/src/java/org/apache/jetspeed/statistics/impl/PortalStatisticsImpl.java URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/statistics/src/java/org/apache/jetspeed/statistics/impl/PortalStatisticsImpl.java?rev=330602&r1=330601&r2=330602&view=diff ============================================================================== --- portals/jetspeed-2/trunk/components/statistics/src/java/org/apache/jetspeed/statistics/impl/PortalStatisticsImpl.java (original) +++ portals/jetspeed-2/trunk/components/statistics/src/java/org/apache/jetspeed/statistics/impl/PortalStatisticsImpl.java Thu Nov 3 10:30:16 2005 @@ -16,196 +16,481 @@ package org.apache.jetspeed.statistics.impl; +import java.security.Principal; +import java.sql.Timestamp; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; - -// javax stuff +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; import javax.servlet.http.HttpServletRequest; +import javax.sql.DataSource; +import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.jetspeed.components.rdbms.ojb.ConnectionRepositoryEntry; import org.apache.jetspeed.request.RequestContext; import org.apache.jetspeed.statistics.PortalStatistics; -import org.apache.pluto.om.portlet.PortletDefinition; - -// java stuff -import java.security.Principal; -import java.text.MessageFormat; -import java.text.SimpleDateFormat; -import java.util.Date; +import org.springframework.orm.ojb.support.PersistenceBrokerDaoSupport; /** - * Simple implementation of the PortletStatsService. This implementation - * uses Apache Common Log Format (CLF) as its default log format. - * This format uses the following pattern string: "%h %l %u %t \"%r\" %>s %b", - * where: - *
    - *
  • %h - remote host
  • - *
  • %l - remote log name
  • - *
  • %u - remote user
  • - *
  • %t - time in common log time format
  • - *
  • %r - first line of request
  • - *
  • %s - status (either 200 or 401)
  • - *
  • %b - bytes sent (always "-" for no bytes sent). Optionally, portlet load time may be logged (see logLoadTime property)
  • - *
- *

- * Here's an example log entry: - *

- * 127.0.0.1 - turbine [26/Aug/2002:11:44:40 -0500] "GET /jetspeed/DatabaseBrowserTest HTTP/1.1" 200 - - *

- * TODO: - *

    - *
  • Statistics cache (by portlet and by user)
  • - *
  • Portlet exclusion
  • - *
  • Configurable format pattern
  • - *
+ *

+ * PortalStatisticsImpl + *

* - * @author Mark Orciuch - * @author Richard Klein - * @version $Id: $ + * @author Chris Schaefer + * @author David Sean Taylor + * @version $Id: TestPortletEntityDAO.java,v 1.3 2005/05/24 14:43:19 ate Exp $ */ -public class PortalStatisticsImpl implements PortalStatistics +public class PortalStatisticsImpl extends PersistenceBrokerDaoSupport implements + PortalStatistics { - /** - * Static initialization of the logger for this class - */ - protected final static Log logger = LogFactory.getLog(PortalStatisticsImpl.class); - - /** - * The default log format pattern string to use with the following elements: - *
    - *
  1. remote address
  2. - *
  3. always "-"
  4. - *
  5. user name
  6. - *
  7. timestamp
  8. - *
  9. request method
  10. - *
  11. context
  12. - *
  13. portlet name
  14. - *
  15. request protocol
  16. - *
  17. status code
  18. - *
  19. always "-" unless logLoadTime is true
  20. - *
- */ - protected static final String defaultLogFormat = "{0} {1} {2} [{3}] \"{4} {5}/{6} {7}\" {8} {9}"; - /** - * Logging enabled flag. If TRUE, the logging will occur. To improve performance, - * the application should use isEnabled() method before calling logAccess(). + /* + * (non-Javadoc) + * + * @see org.apache.jetspeed.statistics.PortalStatistics#forceFlush() */ - private boolean enabled = false; + public void forceFlush() + { + if (pageBatch != null) + { + this.pageBatch.flush(); + } + if (portletBatch != null) + { + this.portletBatch.flush(); + } + if (userBatch != null) + { + this.userBatch.flush(); + } + } - /** - * Date format to use in the log entry. Should conform to standard - * format used by the SimpleDateFormat class. - */ - protected String dateFormat = null; + /* CLF logger */ + protected final static Log logger = LogFactory + .getLog(PortalStatisticsImpl.class); + + /* batch of portlet statistics */ + private BatchedStatistics portletBatch; + + /* batch if page statistics */ + private BatchedStatistics pageBatch; + + /* batch of user statistics */ + private BatchedStatistics userBatch; + + /* format string for a portlet access log entry */ + protected static final String portletLogFormat = "{0} {1} {2} [{3}] \"{4} {5} {6}\" {7} {8}"; + + /* format string for a page access log entry */ + protected static final String pageLogFormat = "{0} {1} {2} [{3}] \"{4} {5}\" {6} {7}"; + + /* Format string for a User Logout log entry */ + protected static final String logoutLogFormat = "{0} {1} {2} [{3}] \"{4}\" {5} {6}"; + + private static final int STATUS_LOGGED_IN = 1; + + private static final int STATUS_LOGGED_OUT = 2; + + /* the following fields should be settable with Spring injection */ + private boolean logToCLF = true; - /** Date formatter */ + private boolean logToDatabase = true; + + private int maxRecordToFlush_Portlet = 30; + + private int maxRecordToFlush_User = 30; + + private int maxRecordToFlush_Page = 30; + + private long maxTimeMsToFlush_Portlet = 10 * 1000; + + private long maxTimeMsToFlush_User = 10 * 1000; + + private long maxTimeMsToFlush_Page = 10 * 1000; + + ConnectionRepositoryEntry jetspeedDSEntry; + + /* after this is NOT for injection */ + + DataSource ds; + + private int currentUsers = 0; + + /* date formatter */ protected SimpleDateFormat formatter = null; - /** Log portlet load time instead of bytes sent (which is always zero) */ - protected boolean logLoadTime = false; + public PortalStatisticsImpl( + boolean logToCLF, + boolean logToDatabase, + int maxRecordToFlush_Portal, + int maxRecordToFlush_User, + int maxRecordToFlush_Page, + long maxTimeMsToFlush_Portal, + long maxTimeMsToFlush_User, + long maxTimeMsToFlush_Page, + ConnectionRepositoryEntry jetspeedDSEntry + ) + { + + this.logToCLF = logToCLF; + this.logToDatabase = logToDatabase; + this.maxRecordToFlush_Portlet = maxRecordToFlush_Portal; + this.maxRecordToFlush_User = maxRecordToFlush_User; + this.maxRecordToFlush_Page = maxRecordToFlush_Page; + this.maxTimeMsToFlush_Portlet = maxTimeMsToFlush_Portal; + this.maxTimeMsToFlush_User = maxTimeMsToFlush_User; + this.maxTimeMsToFlush_Page = maxTimeMsToFlush_Page; + this.jetspeedDSEntry = jetspeedDSEntry; + + } - public PortalStatisticsImpl(boolean enabled, String dateFormat, boolean logLoadTime) + public void springInit() throws NamingException { - this.enabled = enabled; - this.dateFormat = dateFormat; //"dd/MM/yyyy:hh:mm:ss z"); - this.formatter = new SimpleDateFormat(this.dateFormat); - this.logLoadTime = logLoadTime; + formatter = new SimpleDateFormat("dd/MM/yyyy:hh:mm:ss z"); + + if (jetspeedDSEntry != null ) + { + if (jetspeedDSEntry.getJndiName() != null) { + try + { + Context initialContext = new InitialContext(); + ds = (DataSource) initialContext.lookup(jetspeedDSEntry.getJndiName()); + } catch (NamingException e) + { + e.printStackTrace(); + throw e; + } + } + else + { + BasicDataSource bds = new BasicDataSource(); + bds.setDriverClassName(jetspeedDSEntry.getDriverClassName()); + bds.setUrl(jetspeedDSEntry.getUrl()); + bds.setUsername(jetspeedDSEntry.getUsername()); + bds.setPassword(jetspeedDSEntry.getPassword()); + ds = (DataSource) bds; + } + } + + + currentUsers = 0; + } - - /** - * @see org.apache.jetspeed.services.portletstats.PortletStatsService#isEnabled - */ - public boolean isEnabled() + + public DataSource getDataSource() { - return this.enabled; + return ds; } - /** - * @see org.apache.jetspeed.services.portletstats.PortletStatsService#setEnabled - */ - public boolean setEnabled(boolean state) + public void logPortletAccess(RequestContext request, String portletName, + String statusCode, long msElapsedTime) { - boolean oldState = this.enabled; - this.enabled = state; - return oldState; + try + { + HttpServletRequest req = request.getRequest(); + Principal principal = req.getUserPrincipal(); + String userName = (principal != null) ? principal.getName() + : "guest"; + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + PortletLogRecord record = new PortletLogRecord(); + + record.setPortletName(portletName); + record.setUserName(userName); + record.setIpAddress(req.getRemoteAddr()); + record.setPagePath(req.getPathInfo()); + record.setStatus(Integer.parseInt(statusCode)); + record.setTimeStamp(timestamp); + record.setMsElapsedTime(msElapsedTime); + + if (logToCLF) + { + saveAccessToCLF(record); + } + if (logToDatabase) + { + storeAccessToStats(record); + } + } catch (Exception e) + { + logger.error("Exception", e); + } } - /** - * @see org.apache.jetspeed.services.portletstats.PortletStatsService#logAccess - */ - public void logAccess(RequestContext request, PortletDefinition portlet, String statusCode, long time) + protected void storeAccessToStats(LogRecord record) { - - if (!this.isEnabled()) + + if (record instanceof PortletLogRecord) { - return; + if (portletBatch == null) + { + portletBatch = new BatchedPortletStatistics(ds, this.maxRecordToFlush_Portlet, this.maxTimeMsToFlush_Portlet, + "portletLogBatcher"); + } + portletBatch.addStatistic(record); + } - - try + if (record instanceof PageLogRecord) + { + if (pageBatch == null) + { + pageBatch = new BatchedPageStatistics(ds, this.maxRecordToFlush_Page, this.maxTimeMsToFlush_Page, + "pageLogBatcher"); + } + pageBatch.addStatistic(record); + + } + if (record instanceof UserLogRecord) + { + if (userBatch == null) + { + userBatch = new BatchedUserStatistics(ds, this.maxRecordToFlush_User, this.maxTimeMsToFlush_User, + "userLogBatcher"); + } + userBatch.addStatistic(record); + + } + } + + protected void saveAccessToCLF(LogRecord record) + { + Object[] args = + { ""}; + String logMessage = ""; + if (record instanceof PortletLogRecord) + { + PortletLogRecord rec = (PortletLogRecord) record; + Object[] args1 = + { rec.getIpAddress(), "-", rec.getUserName(), rec.getTimeStamp(), + rec.getLogType(), formatter.format(rec.getTimeStamp()), + rec.getPortletName(), + new Integer(rec.getStatus()).toString(), + new Long(rec.getMsElapsedTime())}; + args = args1; + logMessage = MessageFormat.format(portletLogFormat, args) + .toString(); + } + if (record instanceof PageLogRecord) { - logger.info(this.getLogMessage(request, portlet, statusCode, time)); + PageLogRecord rec = (PageLogRecord) record; + Object[] args1 = + { rec.getIpAddress(), "-", rec.getUserName(), rec.getTimeStamp(), + rec.getLogType(), formatter.format(rec.getTimeStamp()), + new Integer(rec.getStatus()).toString(), + new Long(rec.getMsElapsedTime())}; + args = args1; + logMessage = MessageFormat.format(pageLogFormat, args).toString(); } - catch (Exception e) + if (record instanceof UserLogRecord) + { + UserLogRecord rec = (UserLogRecord) record; + Object[] args1 = + { rec.getIpAddress(), "-", rec.getUserName(), rec.getTimeStamp(), + rec.getLogType(), formatter.format(rec.getTimeStamp()), + new Integer(rec.getStatus()).toString(), + new Long(rec.getMsElapsedTime())}; + args = args1; + logMessage = MessageFormat.format(logoutLogFormat, args).toString(); + } + logger.info(logMessage); + } + + public void logPageAccess(RequestContext request, String statusCode, + long msElapsedTime) + { + try + { + HttpServletRequest req = request.getRequest(); + Principal principal = req.getUserPrincipal(); + String userName = (principal != null) ? principal.getName() + : "guest"; + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + PageLogRecord record = new PageLogRecord(); + + record.setUserName(userName); + record.setIpAddress(req.getRemoteAddr()); + record.setPagePath(req.getPathInfo()); + record.setStatus(Integer.parseInt(statusCode)); + record.setTimeStamp(timestamp); + record.setMsElapsedTime(msElapsedTime); + + if (logToCLF) + { + saveAccessToCLF(record); + } + if (logToDatabase) + { + storeAccessToStats(record); + } + + } catch (Exception e) { logger.error("Exception", e); } } - /** - * Formats log message + public void logUserLogout(RequestContext request, long msElapsedTime) + { + try + { + currentUsers = currentUsers - 1; + + HttpServletRequest req = request.getRequest(); + Principal principal = req.getUserPrincipal(); + String userName = (principal != null) ? principal.getName() + : "guest"; + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + UserLogRecord record = new UserLogRecord(); + + record.setUserName(userName); + record.setIpAddress(req.getRemoteAddr()); + record.setStatus(STATUS_LOGGED_OUT); + record.setTimeStamp(timestamp); + record.setMsElapsedTime(msElapsedTime); + + if (logToCLF) + { + saveAccessToCLF(record); + } + if (logToDatabase) + { + storeAccessToStats(record); + } + + } catch (Exception e) + { + logger.error("Exception", e); + } + } + + /* + * (non-Javadoc) * - * @param data - * @param portlet - * @param statusCode - * @param time - * @return Formatted message - * @exception Exception + * @see org.apache.jetspeed.statistics.PortalStatistics#logUserLogin(org.apache.jetspeed.request.RequestContext, + * long) */ - protected String getLogMessage(RequestContext rc, PortletDefinition portlet, String statusCode, long time) - throws Exception - { - HttpServletRequest req = rc.getRequest(); - Principal principal = req.getUserPrincipal(); - String userName = "guest"; - String portletName = "unknown"; - if (portlet != null) - { - portletName = portlet.getName(); - } - if (principal != null) - { - userName = principal.getName(); - } - Object[] args = { - req.getRemoteAddr(), - "-", - userName, - this.formatter.format(new Date()), - req.getMethod(), - req.getContextPath(), - portletName, - req.getProtocol(), - statusCode, - this.logLoadTime == true ? String.valueOf(time) : "-" - }; + public void logUserLogin(RequestContext request, long msElapsedLoginTime) + { + try + { + currentUsers = currentUsers + 1; + + HttpServletRequest req = request.getRequest(); + Principal principal = req.getUserPrincipal(); + String userName = (principal != null) ? principal.getName() + : "guest"; + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + UserLogRecord record = new UserLogRecord(); + + record.setUserName(userName); + record.setIpAddress(req.getRemoteAddr()); + record.setStatus(STATUS_LOGGED_IN); + record.setTimeStamp(timestamp); + record.setMsElapsedTime(msElapsedLoginTime); + + if (logToCLF) + { + saveAccessToCLF(record); + } + if (logToDatabase) + { + storeAccessToStats(record); + } + + } catch (Exception e) + { + logger.error("Exception", e); + } + + } - return MessageFormat.format(defaultLogFormat, args).toString(); + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.DisposableBean#destroy() + */ + public void springDestroy() + { + long start = System.currentTimeMillis(); + if (portletBatch != null) + { + portletBatch.tellThreadToStop(); + synchronized(portletBatch.thread) { + portletBatch.thread.notify(); + } + + } + if (userBatch != null) + { + userBatch.tellThreadToStop(); + synchronized(userBatch.thread) { + userBatch.thread.notify(); + } + } + if (pageBatch != null) + { + pageBatch.tellThreadToStop(); + synchronized(pageBatch.thread) { + pageBatch.thread.notify(); + } + } + if (this.currentUsers != 0) + { + System.out.println("destroying while users are logged in"); + } + boolean done = false; + while (!done) + { + done = true; + if (portletBatch != null) + { + if (!portletBatch.isDone()) + { + done = false; + } + } + if (userBatch != null) + { + if (!userBatch.isDone()) + { + done = false; + } + } + if (pageBatch != null) + { + if (!pageBatch.isDone()) + { + done = false; + } + } + + try + { + Thread.sleep(2); + } catch (InterruptedException ie) + { + } + } + long end = System.currentTimeMillis(); + // new we're done + } - /** - * Formats log message using default load time + /* + * (non-Javadoc) * - * @param data - * @param portlet - * @param statusCode + * @see org.apache.jetspeed.statistics.PortalStatistics#getNumberOfCurrentUsers() */ - public void logAccess(RequestContext request, PortletDefinition portlet, String statusCode) + public int getNumberOfCurrentUsers() { - logAccess(request, portlet, statusCode, 0); + // TODO Auto-generated method stub + return currentUsers; } + } - --------------------------------------------------------------------- To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org For additional commands, e-mail: jetspeed-dev-help@portals.apache.org