[Yanel-dev] Access logging
Cedric Staub
cedric.staub at wyona.com
Thu Sep 2 11:56:51 CEST 2010
Hello
Here is a first version of my patch.
Resources can now use appendFieldToLog to append a new field to the log
entry generated by the current request. I noticed that the contact-form
resourced already does something like this, but by simply generating a
second log entry, which is not very nice. So I modified the contact form
to use the the new functions.
Example: In a resource, you can call
appendFieldToLog("email", resource.getParameter("email"))
which will result in a log entry with e.g.
email:cedric.staub%40wyona.com
in the access log file.
Feedback is welcome. By the way, I also improved the performance of the
access log by replacing string appends with a StringBuilder and I
inserted some Javadocs along the way as well.
Cheers
Cedric
-------------- next part --------------
Index: src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java
===================================================================
--- src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java (revision 52939)
+++ src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java (working copy)
@@ -1121,7 +1121,7 @@
- Or authentication was successful and web authenticator sends a redirect
*/
if(logAccessEnabled) {
- doLogAccess(request, response);
+ doLogAccess(request, response, null);
}
return response;
} else {
@@ -1872,7 +1872,7 @@
if (view.getMimeType() != null) {
// TODO: Add more mime types or rather make it configurable
if (view.getMimeType().indexOf("html") > 0 || view.getMimeType().indexOf("pdf") > 0 || view.getMimeType().indexOf("video") >= 0) {
- doLogAccess(request, response);
+ doLogAccess(request, response, res);
}
}
}
@@ -1908,7 +1908,7 @@
if(logAccessEnabled) {
if (mimeType != null) {
if (mimeType.indexOf("html") > 0 || mimeType.indexOf("pdf") > 0) { // INFO: Only HTML pages and PDFs etc. should be logged, but no images, CSS, etc. Check the mime-type instead the suffix or use JavaScript or Pixel
- doLogAccess(request, response);
+ doLogAccess(request, response, res);
}
}
}
@@ -2358,7 +2358,7 @@
/**
* Log browser history of each user
*/
- private void doLogAccess(HttpServletRequest request, HttpServletResponse response) {
+ private void doLogAccess(HttpServletRequest request, HttpServletResponse response, Resource res) {
Cookie cookie = AccessLog.getYanelAnalyticsCookie(request, response);
// TBD: What about a cluster, performance/scalability? See for example http://www.oreillynet.com/cs/user/view/cs_msg/17399 (also see Tomcat conf/server.xml <Valve className="AccessLogValve" and className="FastCommonAccessLogValve")
// See apache-tomcat-5.5.20/logs/localhost_access_log.2009-11-07.txt
@@ -2388,14 +2388,16 @@
- Log analysis (no special tracking required)
*/
- String requestURL = request.getRequestURL().toString();
- logAccess.info(requestURL + " r:" + realm.getID() + " c:" + cookie.getValue() + " u:" + identity.getUsername() + " ref:" + request.getHeader("referer") + " ua:" + request.getHeader("User-Agent")); // INFO: See a list of user agents at http://www.user-agents.org/
+ java.util.Map<String, String> extra = null;
+ if(res != null) extra = res.getLogFields();
+ if(extra == null) extra = new HashMap<String, String>();
+ extra.put("u", identity.getUsername());
+ logAccess.info(AccessLog.getLogMessage(request, response, realm.getID(), extra));
} else {
// INFO: Log access of anonymous user
- String requestURL = request.getRequestURL().toString();
- // TODO: Also log referer as entry point
- //logAccess.info(requestURL + " r:" + realm.getID() + " c:" + cookie.getValue() + " ref:" + request.getHeader("referer") + " ua:" + request.getHeader("User-Agent"));
- logAccess.info(AccessLog.getLogMessage(request, response, realm.getID()));
+ java.util.Map<String, String> extra = null;
+ if(res != null) extra = res.getLogFields();
+ logAccess.info(AccessLog.getLogMessage(request, response, realm.getID(), extra));
}
//log.warn("DEBUG: Referer: " + request.getHeader(HTTP_REFERRER));
} catch(Exception e) { // Catch all exceptions, because we do not want to throw exceptions because of logging browser history
Index: src/core/java/org/wyona/yanel/core/Resource.java
===================================================================
--- src/core/java/org/wyona/yanel/core/Resource.java (revision 52939)
+++ src/core/java/org/wyona/yanel/core/Resource.java (working copy)
@@ -27,7 +27,7 @@
import org.wyona.yanel.core.map.Realm;
/**
- *
+ * The mother of all resources.
*/
public abstract class Resource {
@@ -44,78 +44,92 @@
protected HttpServletResponse response;
private Environment environment;
protected Map parameters;
+ private Map<String, String> logFields;
public static final String DEFAULT_LANGUAGE = "en";
/**
- *
+ * Constructor.
*/
public Resource() {
rtd = null;
this.parameters = new HashMap();
+ this.logFields = new HashMap<String, String>();
}
/**
- *
+ * Set resource type definition.
*/
public void setRTD(ResourceTypeDefinition rtd) {
this.rtd = rtd;
}
/**
- *
+ * Get resource type definition.
*/
public ResourceTypeDefinition getRTD() {
return rtd;
}
/**
- *
+ * Set Yanel.
*/
public void setYanel(Yanel yanel) {
this.yanel = yanel;
}
/**
- *
+ * Get Yanel.
*/
public Yanel getYanel() {
return yanel;
}
/**
- *
+ * Get universal resource type name.
*/
public String getResourceTypeUniversalName() {
return rtd.getResourceTypeUniversalName();
}
/**
- *
+ * Get local resource type name.
*/
public String getResourceTypeLocalName() {
return rtd.getResourceTypeLocalName();
}
/**
- *
+ * Get resource type namespace.
*/
public String getResourceTypeNamespace() {
return rtd.getResourceTypeNamespace();
}
+ /**
+ * Get path.
+ */
public String getPath() {
return path;
}
+ /**
+ * Set path.
+ */
public void setPath(String path) {
this.path = path;
}
+ /**
+ * Get realm.
+ */
public Realm getRealm() {
return realm;
}
+ /**
+ * Set realm.
+ */
public void setRealm(Realm realm) {
this.realm = realm;
}
@@ -313,13 +327,42 @@
return getRTI().getProperties(name);
}
+ /**
+ * Get environment.
+ */
public Environment getEnvironment() {
return environment;
}
+ /**
+ * Set environment.
+ */
public void setEnvironment(Environment environment) {
this.environment = environment;
this.request = environment.getRequest();
this.response = environment.getResponse();
}
+
+ /**
+ * Append a field to the access log.
+ * For example, if you call this function with the
+ * parameters "source" and "xml", then "source:xml"
+ * will be appended to the access log line of the
+ * current request.
+ *
+ * @param key The name of the field.
+ * @param value The value of the field.
+ */
+ public void appendFieldToLog(String key, String value) {
+ this.logFields.put(key, value);
+ }
+
+ /**
+ * Get additional log fields.
+ * @return Additional a set of key:value pairs that
+ * should be appended to the access log.
+ */
+ public Map<String, String> getLogFields() {
+ return this.logFields;
+ }
}
Index: src/webapp/src/java/org/wyona/yanel/servlet/AccessLog.java
===================================================================
--- src/webapp/src/java/org/wyona/yanel/servlet/AccessLog.java (revision 52939)
+++ src/webapp/src/java/org/wyona/yanel/servlet/AccessLog.java (working copy)
@@ -4,8 +4,10 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import java.util.Date;
+import java.util.Map;
+import java.util.UUID;
import java.net.URLEncoder;
+import java.lang.StringBuilder;
import java.io.UnsupportedEncodingException;
import org.apache.log4j.Logger;
@@ -34,16 +36,23 @@
* @param cookieValue Value/UUID of unique persistent cookie
* @param referer Referer
* @param userAgent User agent, e.g. Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.0.19) Gecko/2010031218 Firefox/3.0.19
+ * @param extra Additional fields to be appended.
*/
- public static String getLogMessage(String requestURL, String realmID, String cookieValue, String referer, String userAgent) {
- String result =
- encodeLogField("url", requestURL) +
- encodeLogField("r", realmID) +
- encodeLogField("c", cookieValue) +
- encodeLogField("ref", referer) +
- encodeLogField("ua", userAgent);
+ public static String getLogMessage(String requestURL, String realmID, String cookieValue, String referer, String userAgent, Map<String, String> extra) {
+ StringBuilder result = new StringBuilder();
+ result.append(encodeLogField("url", requestURL));
+ result.append(encodeLogField("r", realmID));
+ result.append(encodeLogField("c", cookieValue));
+ result.append(encodeLogField("ref", referer));
+ result.append(encodeLogField("ua", userAgent));
- return result;
+ if(extra != null) {
+ for(Map.Entry<String, String> e : extra.entrySet()) {
+ result.append(encodeLogField(e.getKey(), e.getValue()));
+ }
+ }
+
+ return result.toString();
}
/**
@@ -68,22 +77,29 @@
/**
* Get log message
+ * @param request The request.
+ * @param response The response.
+ * @param realmID The id of the current realm.
+ * @param extra Additional fields to be appended to the log.
*/
- public static String getLogMessage(HttpServletRequest request, HttpServletResponse response, String realmID) {
+ public static String getLogMessage(HttpServletRequest request, HttpServletResponse response, String realmID, Map<String, String> extra) {
Cookie cookie = getYanelAnalyticsCookie(request, response);
- return getLogMessage(request.getRequestURL().toString(), realmID, cookie.getValue(), request.getHeader("referer"), request.getHeader("User-Agent"));
+ return getLogMessage(request.getRequestURL().toString(), realmID, cookie.getValue(), request.getHeader("referer"), request.getHeader("User-Agent"), extra);
}
/**
* Get log message
+ * @param request The request.
+ * @param realmID The id of the current realm.
+ * @param extra Additional fields to be appended to the log.
*/
- public static String getLogMessage(HttpServletRequest request, String realmID) {
+ public static String getLogMessage(HttpServletRequest request, String realmID, Map<String, String> extra) {
Cookie cookie = getYanelAnalyticsCookie(request);
String cookieValue = null;
if (cookie != null) {
cookieValue = cookie.getValue();
}
- return getLogMessage(request.getRequestURL().toString(), realmID, cookieValue, request.getHeader("referer"), request.getHeader("User-Agent"));
+ return getLogMessage(request.getRequestURL().toString(), realmID, cookieValue, request.getHeader("referer"), request.getHeader("User-Agent"), extra);
}
/**
@@ -112,7 +128,8 @@
Cookie c = getYanelAnalyticsCookie(request);
if (c != null) return c;
- Cookie analyticsCookie = new Cookie(ANALYTICS_COOKIE_NAME, "YA-" + new Date().getTime()); // TODO: getTime() is not unique!
+ String value = "YA-" + UUID.randomUUID();
+ Cookie analyticsCookie = new Cookie(ANALYTICS_COOKIE_NAME, value);
analyticsCookie.setMaxAge(31536000); // 1 year
//analyticsCookie.setMaxAge(86400); // 1 day
analyticsCookie.setPath(request.getContextPath());
Index: src/contributions/resources/contact-form/src/java/org/wyona/yanel/impl/resources/contactform/ContactResource.java
===================================================================
--- src/contributions/resources/contact-form/src/java/org/wyona/yanel/impl/resources/contactform/ContactResource.java (revision 52939)
+++ src/contributions/resources/contact-form/src/java/org/wyona/yanel/impl/resources/contactform/ContactResource.java (working copy)
@@ -117,9 +117,7 @@
throw new Exception("there is no spamblock implemented in the form.");
}
if (request.getParameter("spamblock_hidden").equals("TRyAg41n") && request.getParameter("spamblock_input").equals("8989890")) {
- logAccess.info(
- org.wyona.yanel.servlet.AccessLog.getLogMessage(request, getRealm().getID()) +
- org.wyona.yanel.servlet.AccessLog.encodeLogField("e-mail", request.getParameter("email")));
+ appendFieldToLog("email", request.getParameter("email"));
javax.servlet.http.Cookie cookie = org.wyona.yanel.servlet.AccessLog.getYanelAnalyticsCookie(request);
String cookieValue = null;
if (cookie != null) {
More information about the Yanel-development
mailing list