Here's one solution for access logging using Play-Authenticate (
joscha.github.io/play-authenticate).
The only thing I'd like to add is the HTTP status code (e.g. 404 for file not found, 200 for success, etc).
Any suggestions are welcome.
1. Create a logging actions file, I'll call it app/actions/AddUserToAccessLog.java
The contents are here:
package actions;
import java.util.Date;
import models.User;
import controllers.Application;
import play.Logger;
import play.Logger.ALogger;
import play.libs.F;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;
public class AddUserToAccessLog extends Action.Simple {
private final ALogger accessLogger = Logger.of("access");
String usern = "nouser";
@Override
public F.Promise<Result> call(Http.Context context) throws Throwable {
Http.Session session = context.session();
Http.Request request = context.request();
Http.Response response = context.response();
// Size of payload
String size = request.getHeader("Content-Length");
if (size == null) {
size = "0";
}
// Get users email address from play-authenticate
User user = Application.getLocalUser(context.session());
if (user != null) {
usern = user.email;
}
// Generate Common Log Format timestamp
String timestamp = new java.text.SimpleDateFormat("MM/dd/yyyy:H:mm:ss Z").format(new Date());
// Exchange HTTP for HTTPS if its an SSL connection - just for kicks
String version = request.version();
Boolean ssl = request.secure();
if (ssl) {
version = version.replace("HTTP", "HTTPS");
}
// Apache Common Log Format entry
accessLogger.info(request.remoteAddress() + " - " + usern + " [" + timestamp + "] \"" + request.method() + " " + request.uri() + " " + version + "\" - " + size);
return delegate.call(context);
}
}
2. Your conf/application-logger.xml file needs to have the name of the access logger in it (here named "access")
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${application.home}/logs/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- Daily rollover with compression -->
<fileNamePattern>${application.home}/logs/application-log-%d{yyyy-MM-dd}.gz</fileNamePattern>
<!-- keep 30 days worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss ZZZZ} [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="ACCESS_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${application.home}/logs/access.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover with compression -->
<fileNamePattern>${application.home}/logs/access-log-%d{yyyy-MM-dd}.gz</fileNamePattern>
<!-- keep 30 days worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%message%n</pattern>
<!-- this quadruples logging throughput -->
<!-- immediateFlush>false</immediateFlush -->
</encoder>
</appender>
<!-- additivity=false ensures access log data only goes to the access log -->
<logger name="access" level="INFO" additivity="false">
<appender-ref ref="ACCESS_FILE" />
</logger>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</configuration>
3. Any Controllers that you want to intercept (probably all of them), need to have an @With line added like this:
import play.mvc.With;
import actions.AddUserToAccessLog;
@With({AddUserToAccessLog.class})
public class MyFunController extends Controller {
...........
}
That's it. Any suggestions on how to add the HTTP status code to the access log are appreciated.
J