Log4j common custom interface - java

I am using slf4j and log4j2 and i want to create a common interceptor. like below so in future if any log4j uprade came up, i would not have to change every class.
Please review below code and let me know your thoughts regarding performance and memory.
Is there any other better way we can do this?
Class LoggingHelper {
public static void logEvent(Class clazz, String message, Object ...args) {
Logger logger = LoggerFactory.getLogger(clazz);
logger.info(message,args);
}
}

Protecting users against changes in the underlying implementation is exactly what APIs like SLF4J or Log4j2 API (cf. API separation) are for. Although a semantic major version bump in the API can break consumer code, no such change ever occurred: e.g. the recent 2.x version of SLF4J semantically is a minor version bump and only requires updates in the implementations.
Using API wrappers like the one you are proposing is usually a bad idea, because you have to reimplement a lot of details that the API already takes care of. In your example:
instantiating a logger is an expensive operation, that is why loggers are almost always static fields or are instantiated in constructors of services (cf. Static vs non-static loggers),
your wrapper breaks location information: all logs will appear to be generated by LoggingHelper,
your wrapper always creates a temporary varargs array, which must be then collected by the GC. Logging APIs don't create temporary objects for the most common cases: SLF4J supports up to 2 non-varargs parameters, Log4j2 API supports up to 10 non-varargs parameters (cf. garbage-free logging).
Software systems have a tendency to abandon their custom logging APIs: e.g. Jetty dropped its custom logging API in version 10.x.

Related

How to upgrade Priority to log4j-2?

I am trying to upgrade log4j to log4j2. The particular line of code I am trying to upgrade is:
log(targetClass, Priority.DEBUG_INT, message, null);
The static field Priority.DEBUG_INT is no longer available in the new Priority. Instead it looks like the getPriority(Facility facility, org.apache.logging.log4j.Level level) static method is used to access priority int value, to which DEBUG can be specified as the Level.
However, this method also requires a Facility to be specified. How do I know which Facility to specify when calling getPriority?
old Priority: https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Priority.html
new Priority: https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/net/Priority.html
new Facility: https://logging.apache.org/log4j/log4j-2.8/log4j-core/apidocs/org/apache/logging/log4j/core/net/Facility.html
Assuming you are talking about Log4j 1's Category.log(String, Priority, Object, Throwable), it appears these Priority classes are pretty (if not completely) unrelated. Log4j 1's Priority is actually the level (indeed it has a subclass Level).
So you would have to look at Log4j 2's Logger class to see if any method with Level parameter matches, but there appears to be no identical alternative (except logMessage maybe, but that appears to be pretty low level).
However, you should check whether that targetClass argument for parameter callerFQCN is actually needed. It looks like it is intended to find the caller of the logger method and might mainly be intended for usage by logging libraries extending Log4j 1. Unless you are indeed upgrading such library, I would assume that the method is misused and a regular Log4j 2 logger.debug(message) would do equally well. Though it would help nonetheless if you could provide more context.

Only use library if available java

In C++ or C, you can do things like this:
#ifdef WINAPI
public void showWindow(int cmdShow);
#endif
But in java, how can I define methods, that will only be compiled when user has enabled a library? I'm making a cross-platform application that uses certain native features which were not yet abstracted by JVM.
Also, I often make constructors that allow making my class from an object coming from some library. In that case, once the constructor is there, it force user to have that library. Instead, I'd like it to be only enabled when user has that library.
Java does not have the concept of macros or templates. Instead it has reflection and generics. In your case, you would use reflection. The idea is to code to interfaces and then at runtime figure out which implementation to use. If no suitable/custom implementation is found you need to fall back to some default (possibly a no-op implementation if you want nothing to happen by default).
The best way to support such architecture is to provide an entry point to your hierarchy of interfaces, i.e., a factory. The entry point will then provide to all clients the implementations they need. The entry point can use reflection to figure out which implementation you want, e.g.,
public final class LibraryManager {
public static LibraryInterface find(String url) { ... }
}
The LibraryManager above figures out via reflection which implementation of LibraryInterface you want to obtain at runtime. The url can be simply the fully qualified class name of the required implementation of LibraryInterface, e.g., com.my.pack.MyLibraryInterfaceImpl.
To understand this in practice, take a look at JDBC's DriverManager: you get an implementation of Connection by providing the DriverManager.getConnection method with a jdbc URL. Behind the curtains, DriverManager uses reflection to find the right driver and returns the implementation needed. If the driver library for the given URL is not available you will get an exception.
In your case, the only modification you need to make to that pattern is to provide some default implementation if no library is specified. If the implementations rely on 3rd party libraries you are going to need to write appropriate adapters that use these, etc.
Note that in many cases you would actually return a factory to your library implementation so you can create many instances of the library objects. This works exactly the same way as above except you return some LibraryFactoryInterface instead.
Finally, if you use some kind of IoC or DI framework like Spring, you can define your implementation factory at configuration time to be injected in your application. A typical example and an alternative to DriverManager is DataSource. It's very common in a Spring application to define your DataSources in the configuration file. Spring will take care of wiring the DataSource into the objects that need to connect to the database.

Force all Java arithmetic to strictfp at runtime, using javassist?

Given a Java application which was written with performance in mind (i.e. methods are deliberately not declared 'strictfp' in the source code), is it possible to allow users to run the entire application in strictfp mode?
It looks like a crude approach would be to simply add the "strictfp" attribute to all methods of all classes using a custom class loader written using javassist. This would be similar to:
http://www.verious.com/qa/no-strictfp-in-scala-workarounds/
However, the class loader would need to add the strictpf attribute to all class methods in the application, including private ones. (The application is simply too large and complex to explicitly list all possible methods which might requre the strictfp attribute.)
The reflection API in javassist does not seem to support listing private methods:
http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/html/javassist/CtClass.html#getMethods()
Is what I want to do possible in javassist (or at all via the custom class loader approach)?
I don't know if this will help you, but if you could change to using the Oracle JRockit JVM, it has a JVM option to enable strictfp globally - '-XX+:-StrictFP`
(There is a '-XX+:-UseStrictFP' option on Hotspot JVMs, but it has the reverse effect to what you want.)
Reference:
http://docs.oracle.com/cd/E15289_01/doc.40/e15062/optionxx.htm#BABHBDAH
http://stas-blogspot.blogspot.com.au/2011/07/most-complete-list-of-xx-options-for.html

Implementing logger for java application

I am trying to implement logger using apache commonn logging and log4j.xml file as configuration file .
So in the actual java code i am writing log as
I am using appache common logging
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
and i am logging information such as in . I am creating a instance of log for each class
private static Log logger = LogFactory.getLog( MyClass.class );
private static final String name ="SAM";
logger.info("name= "+name);
So now my question is does implementing logger like this create a performanace issue?
Is it necessary to check log like
if ( log.isInfoEnabled( ) )
{
log.info( "Info message" );
}
The confusion is mainly because in Apache common logging they have mentioned to do this and in log4j they have mentioned it is unnecessary.
Each time when we write log in the files?
-Sam
yes and no, logging always reduces your performance, but some functions are more expensive then others, e.g. getting the calling class/method-Name uses reflection and is very slow. But a normal logfuntion is not that expensive if you do not have an expensive statement in the calling logging function (this will be evaluated every time before the log-Level is checked. In this case you can use the .isLevelEnabledcheck to prevent the evaluation). Also logging to the console takes longer for the output than logging to a file. You will find more information about this by googling and in the FAQ/manual of log4j.
You do not have to check the Log-Level before logging. This is done within the log-function itself. Therefore are the different methods for every Level or the Level-Argument in the generic log-Method.
A big potential performance problem with logging is usually if you have something passed into the log method that is very expensive to convert to a string. That's why you have methods like isInfoEnabled(), so that the code can avoid creating the message string from the parameter (otherwise the check within the info() method is too late, the conversion is already done). If your objects passed into the log methods are strings or are not very involved then the is*Enabled() methods won't be that useful.
SLF4J is worth checking out. It doesn't depend on classloader tricks (which is a big part of why commons-logging is reviled), and it has a different way of creating log messages which delays when the message string gets created so that the enabled check can take place within the logging method.
There's a better way to do all of this. You can get really great performance without having to add the clutter of ifDebugEnabled, etc methods. Check out something like Logback (or SLF4J). Here's the great documentation about what kind of an API you want. Note that Log4J and Commons-Logging doesn't have an API like this. Use Parameterized Logging.

Cons for defining logger non-static

Comments for this answer How do you reduce Java logging boilerplate code? strongly suggest not to use loggers as instance member variables. I can think of two negative side-effects:
1) superclass logs with the subclass's logger
2) object cannot be serialized (unless marked transient)
But if serializing is not necessary and logging with subclass name is not a problem, is there anything else why it should be avoided? I think it reduces boilerplate code and avoids copy-paste errors while copying logger variable definition from one class to another. Even Spring framework (which I believe has very good coding standards) uses this method.
If your Logger is an instance member instead of static, the Logger has to be retrieved every time a new object is created. Albeit this overhead is probably insignificant, but it's one disadvantage.
From a design perspective, Loggers aren't really a property of an object, since they're usually meta-information about your system rather than business information within the system itself. A Logger isn't really part of something like a Car object in the same way an Engine or a Transmission is. Tying Loggers to objects as members (in most cases) doesn't make sense semantically more than anything.
You might want to have a look at these pages discussing the subject:
SLF4j FAQ: Should Logger members of a class be declared as static?
Commons Wiki: When Static References to Log objects can be used
The major difference asides from the Superclass logging with subclass name, of course, is that you'll have one Logger object per member of your class. Depending on how many classes are using logging, this can be a huge amount of Loggers, so memory bloat may be an issue.
Plus from an abstract point of view, the logger really does belong to the class and can be shared between all instances, rather than each instance needing its own private copy, so it makes sense to declare it as static. Flipping your question around, what advantages does it have to making it non-static? (Being able to pass getClass() into the getLogger() call instead of passing in the class constant is the only thing I can think of, and that's such a tiny thing).
Another, probably minor con: wasted memory, especially when you have lots of instances, each one with its own logger
Try debugging an error where you see a message generated by the SuperClass class when the error is really being logged in the SubClass class. I've seen several situations where developers create a LoggingUtils class which generates messages which generally duplicate the things which are already baked-in by the logging framework.
The only real situation I see for using a shared logging instance is something like the Apache commons HttpClient logger httpclient.wire which is shared between several classes for logging the contents of the requests and responses sent through the client. This particular logging situation does not log information for the actual implementation of the package, it logs information about the whole http "transaction".
One of the main concerns are at cleaning memory instances. Even you don't create objects of a class, since you use static instances of logger there will be references to those objects.
Also as apache says, this keeps references so they won't freed once after used.
Apache Wiki says like this
The use of the static qualifier can be beneficial in some circumstances. However in others it is a very bad idea indeed, and can have unexpected consequences.
The technical result of using static is obvious: there is only one Log reference shared across all instances of the class. This is clearly memory efficient; only one reference(4 or 8 bytes) is needed no matter how many instances are created. It is also CPU-efficient; the lookup required to find the Log instance is only done once, when the class is first referenced.

Categories