[2025998] Usage event (statistics) plugin hook

git-svn-id: http://scm.dspace.org/svn/repo/branches/dspace-1_5_x@3402 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Mark Wood
2009-01-29 15:26:05 +00:00
parent b14f5aa54a
commit 722fff1518
20 changed files with 916 additions and 3 deletions

View File

@@ -0,0 +1,178 @@
/*
* AbstractUsageEvent.java
*
* Version: $Revision: 0 $
*
* Date: $Date: 2008/02/08 10:33:00 $
*
* Copyright (C) 2008, The DSpace Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the DSpace Foundation nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.statistics;
import org.dspace.eperson.EPerson;
/**
* Base class to be extended by usage event handlers.
*
* @author Mark H. Wood
* @version $Revision: 0 $
*/
public abstract class AbstractUsageEvent
{
/** Event is "object has been viewed or downloaded" */
public static final int VIEW = 1;
/** Which session sent the query. */
protected String sessionID;
/** Address from which the query was received */
protected String sourceAddress;
/** The EPerson making the request, or null if not logged on */
protected EPerson eperson;
/** What happened? Viewed, logged on, etc. */
protected int eventType;
/**
* Type of object which experienced the event. Bitstream, item, etc. See
* {@link org.dspace.core.Constants Constants} for values.
*/
protected int objectType;
/** Identity of specific object which experienced the event */
protected int objectID;
/**
* Because the PluginManager can only call a plugin's niladic constructor,
* the constructor returns an "empty" event. It must be populated using the
* setter methods before "firing".
*/
public AbstractUsageEvent()
{
super();
}
/**
* @param id
* opaque session identifier returned by the HTTP request
*/
public void setSessionID(String id)
{
sessionID = id;
}
/** */
public String getSessionID()
{
return sessionID;
}
/**
* @param address
* the address from which the HTTP request came
*/
public void setSource(String address)
{
sourceAddress = address;
}
/** */
public String getSource()
{
return sourceAddress;
}
/**
* @param user
* an object representing the logged-on user, if any. May be
* null.
*/
public void setEperson(EPerson user)
{
eperson = user;
}
/** */
public EPerson getEperson()
{
return eperson;
}
/**
* @param type
* the type of event (view, logon, etc.)
*/
public void setEventType(int type)
{
eventType = type;
}
/** */
public int getEventType()
{
return eventType;
}
/**
* @param type
* the type of object experiencing the event (bitstream, etc.)
*/
public void setObjectType(int type)
{
objectType = type;
}
/** */
public int getObjectType()
{
return objectType;
}
/**
* @param id
* the identifier of the specific object experiencing the event
*/
public void setID(int id)
{
objectID = id;
}
/** */
public int getID()
{
return objectID;
}
/** Called when the event is fully configured, to process the data. */
abstract public void fire();
}

View File

@@ -0,0 +1,57 @@
/*
* PassiveUsageEvent.java
*
* Version: $Revision: 0 $
*
* Date: $Date: 2008/02/08 10:33:00 $
*
* Copyright (C) 2008, the DSpace Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the DSpace Foundation nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.statistics;
/**
* A null implementation of AbstractUsageEvent to absorb events harmlessly and
* cheaply.
*
* @author Mark H. Wood
* @version $Revision: 0 $
*/
public class PassiveUsageEvent extends AbstractUsageEvent
{
/**
* Do nothing and return. Effectively, the event is discarded.
*/
public void fire()
{
return;
}
}

View File

@@ -0,0 +1,139 @@
/*
* UsageEventTabFileLogger.java
*
* Version: $Revision: 0 $
*
* Date: $Date: 2008/02/08 10:33:00 $
*
* Copyright (C) 2008, the DSpace Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the DSpace Foundation nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.statistics;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.log4j.Logger;
import org.dspace.core.ConfigurationManager;
/**
* Serialize AbstractUsageEvent data to a file as Tab deliminated. Requires
* configuration: in dspace.cfg specify the path to the file as the value of
* {@code usageEvent.tabFileLogger.file}.
*
* @author Mark H. Wood
* @author Mark Diggory
* @version $Revision: 0 $
*/
public class UsageEventTabFileLogger extends AbstractUsageEvent
{
/** log4j category */
private static Logger errorLog = Logger
.getLogger(UsageEventTabFileLogger.class);
/** File on which to write event records */
private static PrintWriter log = null;
public UsageEventTabFileLogger()
{
super();
if (null == log)
{
boolean appending;
String logPath = ConfigurationManager
.getProperty("usageEvent.tabFileLogger.file");
if (null == logPath)
{
errorLog
.error("UsageEventTabFileLogger unconfigured, will not log events");
return;
}
String logDir = null;
if (!new File(logPath).isAbsolute())
logDir = ConfigurationManager.getProperty("log.dir");
File logFile = new File(logDir, logPath);
appending = logFile.length() > 0;
try
{
log = new PrintWriter(new OutputStreamWriter(
new FileOutputStream(logFile, true)));
}
catch (FileNotFoundException e)
{
errorLog
.error(
"UsageEventTabFileLogger cannot open file, will not log events",
e);
return;
}
if (!appending)
{
log.println("date event objectType objectId sessionId sourceAddress eperson");
}
}
}
/**
* Serialize to a file
*/
public void fire()
{
if (null == log)
return;
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyyMMdd'T'HHmmssSSS");
String string = dateFormat.format(new Date());
string += "\t" + new Integer(eventType);
string += "\t" + new Integer(objectType);
string += "\t" + new Integer(objectID);
string += "\t" + sessionID;
string += "\t" + sourceAddress;
String epersonName = (null == eperson ? "anonymous" : eperson.getEmail());
string += "\t" + epersonName;
log.println(string);
log.flush();
}
}

View File

@@ -0,0 +1,142 @@
/*
* UsageEventXmlLogger.java
*
* Version: $Revision: 0 $
*
* Date: $Date: 2008/02/08 10:33:00 $
*
* Copyright (C) 2008, the DSpace Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the DSpace Foundation nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.statistics;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.log4j.Logger;
import org.dspace.core.ConfigurationManager;
/**
* Serialize AbstractUsageEvent data to a file as XML. Requires configuration:
* in dspace.cfg specify the path to the file as the value of
* {@code usageEvent.xmlLogger.file}.
*
* @author Mark H. Wood
* @version $Revision: 0 $
*/
public class UsageEventXMLLogger extends AbstractUsageEvent
{
/** log4j category */
private static Logger errorLog = Logger
.getLogger(UsageEventXMLLogger.class);
/** File on which to write event records */
private static PrintWriter log = null;
public UsageEventXMLLogger()
{
super();
if (null == log)
{
boolean appending;
String logPath = ConfigurationManager
.getProperty("usageEvent.xmlLogger.file");
if (null == logPath)
{
errorLog
.error("UsageEventXMLLogger unconfigured, will not log events");
return;
}
String logDir = null;
if (!new File(logPath).isAbsolute())
logDir = ConfigurationManager.getProperty("log.dir");
File logFile = new File(logDir, logPath);
appending = logFile.length() > 0;
try
{
log = new PrintWriter(new OutputStreamWriter(
new FileOutputStream(logFile, true)));
}
catch (FileNotFoundException e)
{
errorLog
.error(
"UsageEventXMLLogger cannot open file, will not log events",
e);
return;
}
if (!appending)
{
log.println("<?xml version='1.0' ?>");
log.println("<usagelog>");
}
}
}
/**
* Serialize to a file
*/
public void fire()
{
if (null == log)
return;
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyyMMdd'T'HHmmssSSS");
log.print(" <event time='" + dateFormat.format(new Date()) + "'");
log.print(" type='" + new Integer(eventType) + "'");
log.print(" objectType='" + new Integer(objectType) + "'");
log.print(" objectID='" + new Integer(objectID) + "'");
log.print(">");
log.print("<session>" + sessionID + "</session>");
log.print("<source>" + sourceAddress + "</source>");
String epersonName = (null == eperson ? "" : eperson.getEmail());
log.print("<eperson>" + epersonName + "</eperson>");
log.println("</event>");
log.flush();
}
}

View File

@@ -0,0 +1,72 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>org.dspace.app.statistics package</title>
<!--
* Copyright (C) 2008, the DSpace Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the DSpace Foundation nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
-->
</head>
<body>
<p>
Defines usage event instrumentation points and provides implementations for
testing.
</p>
<p>
This package makes usage instrumentation (for statistics, or whatever else
you may fancy) pluggable, while avoiding any unnecessary assumptions about how
usage events may be transmitted, persisted, or processed.
</p>
<p>
At appropriate points in the processing of user actions, events may be
assembled and "fired". What happens when an event is fired is configurable
via the PluginManager. One must configure a plugin for the AbstractUsageEvent
class, defined in this package, to select an event processing implementation.
</p>
<p>
Three "stock" implementations are provided.
</p>
<dl>
<dt>{@link org.dspace.app.statistics.PassiveUsageEvent PassiveUsageEvent}</dt>
<dd>absorbs events without taking action, resulting in behavior identical
to that of DSpace before this package was added. This is the default
if no plugin is configured.</dd>
<dt>{@link org.dspace.app.statistics.UsageEventTabFileLogger UsageEventTabFileLogger}</dt>
<dd>writes event records to a file in Tab Separated Values format.</dd>
<dt>{@link org.dspace.app.statistics.UsageEventXMLLogger UsageEventXMLLogger}</dt>
<dd>writes event records to a file in an XML format. Suitable mainly for
testing.</dd>
</dl>
</body>
</html>