Jetspeed Proposal: Portlet Usage Logging (draft)
Version: $Revision: 1.1 $
Proposed by: Mark Orciuch, Next Generation Solutions, Ltd. (mark_orciuch@ngsltd.com)
Status: Initial Proposal
Date: August 16, 2002

Overview
========

The purpose of this proposal is to introduce ability to log every portlet usage. Commercial sites make use of such tools as WebTrends to gauge the traffic and analyze content usage. Due to the dynamic nature of Jetspeed portal, it is not possible to analyze content usage by using a standard web server log. In order to gain meaningful portlet usage statistics, each portlet access should be logged. If the log format conforms to something that can be fed into, say, WebTrends, then getting usage stats would be much easier.

Approach
========

My proposed approach is to create a Turbine service responsible for managing the portlet usage statistcs. The call to this service's logAccess() method would be the "implanted" in appropriate places where portle content is requested.  The most logical choice for the the logging engine is log4j. The following are main features of the feference implementation:

1. Log entry to utilize the Common Log Format for ease of integration with WebTrends (or similar tool).
2. Lightweight implementation of the logAccess method so it won't affect performance.
3. Current stats cache (optional).
4. Methods to return current stats from the cache - by portlet and by user (optional).
5. Administrative portlet to display current stats (optional).

Implementation
==============

1. The following new classes/templates would be added:

org.apache.jetspeed.services.portletstats.PortletStatsService - interface to implement by portlet stats service

org.apache.jetspeed.services.portletstats.JetspeedPortletStatsService - reference implementation

org.apache.jetspeed.services.portletstats.TestPortletStatsService - unit test class

org.apache.jetspeed.services.JetspeedPortletStats - static wrapper for the portlet stats service

org.apache.jetspeed.modules.actions.portlets.PortletStatsAction - action for the portlet-stats-porlet template

portlet-stats-portlet.vm - template to display portlet statics as in the mock up below:

+---------------------+-----------------+------------+
+Portlet/User	      + admin + turbine + Total hits +
+---------------------+-----------------+------------+
+DatabaseBrowserTest  +     1 +      20 +         21 +
+---------------------+-----------------+------------+
+Jetspeed             +     1 +      30 +         31 +
+---------------------+-----------------+------------+
+DatabaseBrowserTest  +     1 +      40 +         41 +
+---------------------+-----------------+------------+
+Total hits           +     3 +      90 +         93 +
+---------------------+-----------------+------------+

2. The following classes/templates would be changed:

org.apache.jetspeed.portal.security.portlets.PortletWrapper - insert a call to JetspeedPortletStats.logAccess() in getContent() method 

3. The following entries would be added to the JetspeedResources.properties:

#########################################
# Portlet Usage Service                 #
#########################################
services.PortletStats.classname = org.apache.jetspeed.services.portletstats.JetspeedPortletStatsService

# Name of the log4j logger defined in tr.props
services.PortletStats.logger = access

# If true, logging will occur
services.PortletStats.enabled = true

# Portlets to exclude from logging
services.PortletStats.excludePortlets=

# Date format to use in the log entry
services.PortletStats.dateFormat = dd/MMM/yyyy:hh:mm:ss z

4. The following entires would be added to the TurbineResources.properties:

services.LoggingService.access.log4j.category.access = INFO, access
services.LoggingService.access.log4j.appender.access = org.apache.log4j.FileAppender
services.LoggingService.access.log4j.appender.access.layout = org.apache.log4j.PatternLayout
services.LoggingService.access.log4j.appender.access.layout.ConversionPattern = %m%n
services.LoggingService.access.log4j.appender.access.append = true
services.LoggingService.access.log4j.appender.access.file=${webappRoot}/WEB-INF/log/access.log
services.LoggingService.access.className = org.apache.turbine.services.logging.Log4JavaLogger
services.LoggingService.access.level = INFO

