Real world user activity logging strategy for web applications
Recommendation 1: Profile your application with and without your database logging system. You may find that DB logging meets your performance needs without major architectural changes or performance tuning.
If you find that you're able to sustain your throughput requirements, but occasionally back up during peak periods, you could move the DB logging into a single thread and pass log messages using a concurrent queue from java.util.concurrent
. That will be much more efficient than forking a separate thread for each log event.
My suspicion is that if you find a performance issue, you'll find the bottleneck to be the database. But that's just a hunch - you'll have to profile your own setup to find the strengths and weaknesses.
Note: To compare performance with and without logging enabled, you could configure an on/off boolean or specific log levels at startup into final static variables. The JIT will optimize out any code contained in an if (loggingEnabled)
or if (logLevel > 3)
block, if those conditions are guaranteed to be false. That lets you run the same code with and without logging, without paying a performance penalty for the logging code when profiling the current (non-logging) approach.
Logging user activity in web app
It's actually pretty simple to achieve using MDC/NDC functionality built into Log4J (SLF4J and Logback only support MDC).
Implementing MDC filter
First, implement a servlet filter that will add username to MDC/NDC. Logback provides convenient MDCInsertingServletFilter, Spring framework also adds Log4jNestedDiagnosticContextFilter to the store. Look at them but you will need a custom one like this:
public class UserToMdcFilter implements javax.servlet.Filter
{
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
MDC.put("user", SecurityContextHolder.getContext().getAuthentication().getPrincipal());
try {
chain.doFilter(request, response);
} finally {
MDC.remove("user");
}
}
//...
}
Adding MDC value to your logging pattern
Make sure this filter is applied in web.xml
after Spring security filter. MDC feature is really slick - it will add all values saved in MDC thread-local map to each and every logging statement if requested. In your case, simply add this:
%X{user}
to your logging pattern.
Unobtrusive logging method parameters/values
Logging method name, parameters and return values is up to you (username will be added automatically), but there are some elegant ways to remove boilerplate logging code completely. Try this Spring built-in aspect:
<bean id="customizableTraceInterceptor" class="org.springframework.aop.interceptor.CustomizableTraceInterceptor">
<property name="enterMessage" value="Entering $[methodName]($[arguments])"/>
<property name="exitMessage" value="Leaving $[methodName](): $[returnValue]"/>
</bean>
<aop:config>
<aop:advisor advice-ref="customizableTraceInterceptor" pointcut="execution(public * BankAccountServlet.*(..))"/>
</aop:config>
Final thoughts
- Look at this thread: http://forum.springsource.org/showthread.php?88890-MDC-Log4j-Filter-with-Spring-Security-3.0.2
- Consider using Logback as a logging library and stick with SLF4J API.
logging/monitoring user activity in a java web app
I think you need to understand what you are trying to achieve. If you want to have some kind of AuditLog, which means to know when something happened, why something happened, and who did it, log4j/slf4j etc will be absolutely sufficient. Because you will probably need this data only once and after some weeks and only to answer some questions by the police.
However if you want to know what happens in your application, how many requests this or that components receives, how long do the requests take, how many errors are produced and what happens overall... You need something more powerful than logging framework, and of all open source performance monitoring tools MoSKito is best...
So, if you are interested in knowing what exactly a special user has done - logging is sufficient. If you want to know, what happens in your application - its not.
What is the best practice for logging users activity?
As always, "it depends".
If the evolution over time of your core business concepts is important, it should be a first-class concept in your database design, as well as your PHP logic. Fowler writes about this in "Analysis patterns".
This allows you to capture who made which changes to your business objects and answer questions like "who changed the project from type x to y on date z?", "how often did user x change product y?" etc. It does make the domain model more complex.
If you don't need this level of integration, my preference is to put the logging functionality in PHP; triggers have a horrible way of slowing down a database, or leading to unexpected side effects, or being forgotten by developers making changes to the schema. So, in PHP, I'd include explicit "log this" statements, possibly using an aspect-oriented framework (though I've never used that in PHP, only in Java).
Best practice in designing a web app user activities logging?
I guess it depends a bit what kind of specific needs you have with your logging, but generally Log::Log4perl can be tricked into doing what you want.
ASP.Net User activity tracking in database
I ended up using among the first two approaches because they seem more simple and easier. Most of all they provide more control and allow to keep thing as flexible as required (i.e. its near to the actual backend coding which makes it more accessible)
I'm marking it as there has been no other extensive reviews.
Strategy for tracking user recent activity
Our solution is to maintain a "Transaction" table (which follows what was done), in addition to our "Session" table (which follows who was here). UPDATE, INSERT and DELETE instructions are all managed through a "Transaction" object and each of these SQL instruction is stored in the "Transaction" table once it has been successfully executed on the database (depending on tables updated: we have the possibility to specifically follow some tables and ignore others). This "Transaction" table has other fields such as transactiontType (I for INSERT, D for DELETE, U for UPDATE), transactionDateTime, etc, and a foreign key "sessionId", telling us finally who sent the instruction. It is even possible, through some code, to identify who did what and when (Gus created the record on monday, Tim changed the Unit Price on tuesday, Liz added an extra discount on thursday, etc).
Pros for this solution are:
- you're able to tell "what who and when", and to show it to your users! (you'll need some code to analyse SQL statements)
- if your data is replicated, and replication fails, you can rebuild your database through this table
Cons are
- 100 000 data updates per month mean 100 000 records in Tbl_Transaction
- Finally, this table tends to be 99% of your database volume
Our choice: all records older than 90 days are automatically deleted every morning
Related Topics
Is -Djava.Library.Path=... Equivalent to System.Setproperty("Java.Library.Path", ...)
How to Convert Iterable to Collection
Using an Instance of an Object as a Key in Hashmap, and Then Access It with Exactly New Object
Javafx and Maven: Nullpointerexception: Location Is Required
Matrix Multiplication in Apache Spark
Java Conventions: Use Getters/Setters Within the Class
How to Handle Deserializing with Polymorphism
How to Pass Console Arguments to Application in Eclipse
Determine Whether Daylight Savings Time (Dst) Is Active in Java for a Specified Date
Java Code for Getting Current Time
Writing Custom Kafka Serializer
Convert .Jar to an Osx Executable