You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by ta...@apache.org on 2005/11/03 19:30:27 UTC
svn commit: r330602 -
/portals/jetspeed-2/trunk/components/statistics/src/java/org/apache/jetspeed/statistics/impl/PortalStatisticsImpl.java
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 <A HREF="http://httpd.apache.org/docs/logs.html">Apache Common Log Format (CLF)</A> as its default log format.
- * This format uses the following pattern string: "%h %l %u %t \"%r\" %>s %b",
- * where:
- * <UL>
- * <LI><B>%h</B> - remote host</LI>
- * <LI><B>%l</B> - remote log name</LI>
- * <LI><B>%u</B> - remote user</LI>
- * <LI><B>%t</B> - time in common log time format</LI>
- * <LI><B>%r</B> - first line of request</LI>
- * <LI><B>%s</B> - status (either 200 or 401)</LI>
- * <LI><B>%b</B> - bytes sent (always "-" for no bytes sent). Optionally, portlet load time may be logged (see logLoadTime property)</LI>
- * </UL>
- * <P>
- * Here's an example log entry:
- * <P>
- * <CODE>127.0.0.1 - turbine [26/Aug/2002:11:44:40 -0500] "GET /jetspeed/DatabaseBrowserTest HTTP/1.1" 200 -</CODE>
- * <P>
- * TODO:
- * <UL>
- * <LI>Statistics cache (by portlet and by user)</LI>
- * <LI>Portlet exclusion</LI>
- * <LI>Configurable format pattern</LI>
- * </UL>
+ * <p>
+ * PortalStatisticsImpl
+ * </p>
*
- * @author <a href="mailto:morciuch@apache.org">Mark Orciuch</a>
- * @author <a href="mailto:rklein@bluesunrise.com">Richard Klein</a>
- * @version $Id: $
+ * @author <a href="mailto:chris@bluesunrise.com">Chris Schaefer</a>
+ * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
+ * @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:
- * <OL START="0">
- * <LI>remote address</LI>
- * <LI>always "-"</LI>
- * <LI>user name</LI>
- * <LI>timestamp</LI>
- * <LI>request method</LI>
- * <LI>context</LI>
- * <LI>portlet name</LI>
- * <LI>request protocol</LI>
- * <LI>status code</LI>
- * <LI>always "-" unless logLoadTime is true</LI>
- * </OL>
- */
- 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