I am looking to understand the pros and cons of centralizing all applications logs into separate files with AOP (e.g. with AspectJ).
Logging is know for being a cross-cutting concern. However, I have never met anyone that centralized all logs into a single or bunch of files. Therefore, I'm left wondering why.
What would be some of the pros and cons of doing it?
I am looking to understand the pros and cons of centralizing all applications logs into separate files with AOP (e.g. with AspectJ).
I will be using the terms AOP and AspectJ interchangeably. Notwithstanding, AOP is the paradigm and AspectJ implements it, just like OOP and Java.
The benefits of centralizing cross-cutting concerns (CCC) into their own modules (e.g., aspect) using AOP are similar to those of modularization concerns with OOP
. Those benefits are described in the literature in papers and books such as:
and many others. One can summarize some of those benefits as follows:
Instead of having logging 1 and 2 tangled directly with the domain-code, duplicated and scattered across separate modules (i.e., Class A
and Class B
), we have those logging-related functionality encapsulated into one aspect.
There are in the literature some papers about the benefit of AOP regarding the modularization of cross-cutting concerns such as logging namely:
S. Canditt and M. Gunter. Aspect oriented logging in a real-world system. In First AOSD Workshop on Aspects, Components, and Patterns for Infrastructure Software (AOSD-2002), March 2002.
The downsides of AOP that one can read in the literature are those typical of a learning/integrating a new technology, namely:
- Hiring skilled programmers
- Following an adoption path to ensure that you don’t risk the project by overextending yourself
- Modifying the build and other development processes
- Dealing with the availability of tools
Other downsides reported by papers such as:
can be summarize to:
having to learn a new paradigm;
lack of tool support;
the performance of the weaving;
making it harder to reason about the code, since the CCC related code was moved elsewhere. The same argument can be applied to subclassing or the use of the decorated pattern for instance. However, IDEs mitigates those problems, in the case of AspectJ
by showing the joinpoints that are being intercepted. Another solution is for instance to use annotations and intercept those annotations:
@Logging public void some_method(){...}
When the programmer looks at the annotation immediately knows that that method is being intercepted by a pointcut. The downside of this approach is that you kind mixing again the CCCs with the domain code, albeit just in a form of an annotation.
On the other hand one can argue that since the domain-related concerns and CCCs are now encapsulated in different modules it is easier to reason about them in isolation.
changes to the base-code can lead to join points incorrectly falling in or out of the scope of pointcuts.
For instance, adding new methods, or changing their signature might cause pointcuts to intercept them or stop intercepting them. There are techniques to mitigate such problems. However, in my option the solution is tooling. When one renames a method in Java one expects the IDE to safely apply those changes.
Users have sometimes wanted AspectJ to pick out many more join points, including method-local field access, array-element access, loop iteration, method parameter evaluation
Most of these have turned out not to make sense, for a variety of reasons: it is not a commonly-understood unit for Java programmers
there are very few use-cases for advice on the join point
a seemingly-insignificant change to the underlying program causes a change in the join point
pointcuts can't really distinguish the join point in question
the join point would differ too much for different implementations of AspectJ, or would only be implementable in one way
We prefer to be very conservative in the join point model for the language, so a new join point would have to be useful, sensible, and implementable. The most promising of the new join points proposed are for exception throws clauses and for synchronized blocks.
You need to evaluate if in your context it pay-off adding an extra layer (i.e., transversal modularization) into your code base; and also evaluate against alternative approaches such as code-generators, frameworks or design patterns.
In the case of the logging some of the aforementioned issues are not as problematic because if things go wrong... well you just lose or add some logging.
Opinion base part
Logging is know for being a cross-cutting concern. However, I have never met anyone that centralized all logs into a single or bunch of files. Therefore, I'm left wondering why.
Is separation of concerns a bad practice?! (unless you take it to the extreme no). I would definitely say that is not a bad practice, is it worth?! well that is more complex and context depended.
I personally hate to see a beautiful snippet of code mixed with logging functionality. IMO given that software has to deal with so many other variables than just the code per si, such as tight deadlines, not having logging mixed with base code seems to not have a higher priority.