I want to log information to a file and want to know is there any advantage in using the Java Logger class versus my own personal method of logging?
I know using a logger I just add my own FileHandler to the logger. My personal method is just using a FileOutputStream.
Honestly your logger may be as good, it's pretty easy to put in log levels, filtering, etc.
The problem is when you start to put together code from 10 different groups each with their own logging. Some use System.out, some use some custom logger, some use log4j, ...
How do you parse or redirect the output? How do you filter all that output to just show your messages (For instance, filtering options in log4j won't prevent messages being sent straight to System.out).
It's a pretty big bulk change depending on which system you are moving from/to. Better just to use one very common one from the beginning and hope that it's the one everybody else on the project chooses.
The real question is: why would you bother writing your own logger when there are already existing libraries for doing that? Does your logger do something that the others don't? I kind of doubt it.
Standardization is another big issue - see Bill K's answer.
For most scenarios, a standard logging framework is the way to go. They are pretty flexible. But using your own implementation can also be a valid option, specially if we are not speaking of traditional logging (global debugging, problems, warning messages) but about specific informational meesages or accounting.
Among other factors, bear in mind that the standarization of logging allows third party libraries to cooperate. For example, if you have a standard web application using (say) Hibernate, and you have configured a standard Java logging lib, then you can not only log from your own code but also tell Hibernate to log debugging info to your log files (not necessarily the same files). That is very useful - almost a must.
If you code your own logging library with a plain FileOutputStream, you must decide -among other things- if you are going to keep the file opened, or reopen-append-close in each write - and you must take of synchronization and related issues. Nothing terribly complicated, though.
The logger gives to ability to define different levels of importance of the logged messages and the ability to use different sink for the output - the console, a file, etc.
Also it's easy to enable or disable only some type of message when using a logger - for example you don't want to see every debug message in production.
A logging framework allows you specify logging levels (e.g. log only critical messages, log only debug messages etc.). It also allows you to log to multiple destinations (e.g. to a file, to syslog etc.) and you can do this even after your application is fully built by just changing a config file and not changing any code. It can also format your logs easily depending on various parameters.
There are numerous other advantages since proper logging is a rather involved problem and these packages have been written to solve them. I think the important question, why would you not use them?
Well I would always prefer tested thing and approved by community over something which still need a lot of test. Logger allows you many things which will consume you some time to implement and to test the robustness of your solution. A big plus will be the know-how of the next person who will do something with your code, in case it will be your logger, normally it would take more time to learn how its working out, since there is much more examples and documentation for java.util.logger.
Like all others mention, there are more advantages to using a more common logging system over writing your own. To be honest, the Java util logging api is not nearly as extensive and configurable as other libraries you might find out there on the internet.
Bare in mind that rolling your own always has the disadvantage of being less tested and therefore more prone to break or skip some potentially crucial messages.
Personally I prefer using SLF4J since it allows me to plug in adapters for more commonly used logging frameworks and then let's me pick my own actual logging implementation, this solves most of the problems with different library writers preferring different logging frameworks. And if you consider yourself up for the task you could writer an implementation for SLF4J yourself ;)
Related
I've written a console app in Java, that uses Google Protocol Buffers for serialization.
However, when that code is used, during library loading, it outputs some warnings about illegal reflective access operations.
AFAIK, that's some minor Google annoyance that doesn't really affect anything, so I would like my app not to dump that trash to output.
At the same time, I obviously want my app to output its own stuff as normal.
How does one generally go about things like this?
What would be a good way to handle this concrete situation?
The best way would be to add a logger and not use the standard console output. You can read about slf4j. It has many advantages over the standard output. You can have different levels of the log you want to see - info,debug,warn,error etc. So you can limit the amount of information you read. Also you will keep previous outputs in files and also you can configure different appenders - so different classes write their outputs into different files.
Basically this is the preferred way for most java applications and there is a reason why
Why is it a good practice to use logger.debug() instead of System.out.println()?
I understand that log4j allows you to control what you wish to print (DEBUG,FATAL,INFO, etc), but apart from that, is there any other benefit?
A Logger adds so much more value to your logging.
Log levels: In a production environment you don't care about some levels (ex: debug info), only serious errors and system crashes.
Log filtering: Filter what components are allowed to log.
Log formatting: Control the information and its format contained in the log. You can setup defaults (like time and thread id) or add more specific ones per statement.
The log destination: You can set up your logger to write to a file, to emails, to databases, etc.
A policy for keeping and archiving logs: Let the logger manage the logs, keep some history, delete older
Also, Loggers are usually synchronized, so your print statements aren't written over eachother. You cannot guarantee that with System.out.
You can implement all this with System.out, but it would be so complex and tedious.
If your code is ever used in a web service or a system service, using debug statements will ensure that they appear in the services logs. If not you risk them being printed to a hidden console window and being lost.
Specialized loggers offer a number of benefits over plain standard output:
logical separation of logging, in at least two orthogonal areas: subsystem and importance
flexibility - there are many predefined ways to output and store log data, and you can roll you own, if you really want
configurability - you can precisely control what and where to log, and all of this is external to the code that actually uses logging, making it simple and inobtrusive
formatting - you don't need to manually append all the bookkeeping information, such as the class name, time etc. Logger does that for you, in an entirely configurable way, allowing you to write simple, clear logging code and retain all the benefits, like filtering and precise information.
speed - loggers are optimized not to introduce much overhead
In apache-tomcat are there any performance benefits of using some logging framework like log4j or java.util.logging over printing to stdout which gets dumped to catalina.out (which is the default behavior)?
Functionally both are same for my use-case since I don't need any extra formatting for logged messages.
I would like to know the benefits of using a logging framework here.
Thanks in advance!
You won't see performance benefits, from that perspective just go with whatever provides your functionality.
Adding something like log4j is so easy anyway though, and provides so much more future flexibility, that I'd never even think of relying on stdout for a webapp output, no matter how limited my current requirement.
Edit: it's not just formatting of messages, stuff like including class-that-wrote-the-log-entry, line of code, thread name, etc - all of these can be included in logs "free" once you're using a logging framework, and they're just not available with stdout.
besides formatting there are many advantages to using logger instead print to console. And perfomance too. For example you can simple switch before log levels to achive better perfomance. You can achive additional perfomance when use right logger like logback.
For example logback has feature use placeholders in log message
log.debug ("Result of big function = {}", bigAndLongMethod())
this will be faster then
log.debug("Result of big function = " + bigAndLongMethod())
because in first case bigAndLongMethod() willn't be executed if your loglevel higher then debug.
Using some additional appenders can increase perfomance to, i.e. redirect log to other host or log into db.
As additional benefit you will get more standart-comliant log support in you project, and you be more sotisfacted with it in future, even you don't see any difference right now.
The program I'm building seems to freeze at some points on the user's system. When I test the very same steps, I see no problem. Even though Java is supposed to be a platform-independent VM, my guess is it has to do with the systems we're using (I'm on linux, the user on Mac), maybe something with file access.
I cannot access the user's system, and the user has no idea what debugging means. In order to test where the problem is, I was thinking of writing the program's progress to a file, and having him send me the file when there's a problem. Therefore my question:
Is there some kind of library which allows writing the line by line execution of a program to a file? Ideally, the values of certain variables would also be included.
edit: I'm familiar with Logger, but (like one answer says), that would require writing a lot of log statements. Is there some way to do this automatic? Maybe line by line is overkill, but something like log each method entry/exit would definitely work.
Thanks a lot!
This might be a good use case for aspect-oriented programming. Specifically, the AspectJ library for Java might suit your needs (there are others, but this is the one I'm most familiar with). You could define a logging aspect that would automatically insert method entry/exit log messages into the methods you wish to trace, without having to modify the code for those methods. The aspect can be included or excluded as you wish whenever you build the application (eg, include it just for this user until you resolve the issue).
Something like the following might be a good start:
aspect LogAllMethods {
Log log = new Log(); // pseudocode -- replace with whatever logging mechanism you like
before(): call(public * com.mycompany.*.*(..)) {
log.log("Entered method: " + thisJoinPoint);
}
after(): call(public * com.mycomapny.*.*(..)) {
log.log("Leaving method: " + thisJoinPoint);
}
}
This basically says that, before and after any public method call in the package com.mycompany, log the entry/exit and the name of the method (thisJoinPoint is a special variable in AspectJ that refers to the point in the program's execution that the aspect is being applied to). The AspectJ documentation has some nice tutorials and examples of defining aspects and how they can be used, as well as instructions on how to introduce aspects into your application.
This might be overkill for your situation and underutilization of AspectJ, but it should allow you to do some fine-grained debugging without having to add logging calls to every method in your code.
Typically the debug information you want would be included in a log file. Logging frameworks like Java's built in Logging API allow you to configure what severity of messages to produce when the program is run. In other words, you could have it normally report severe errors only, but enable debug output selectively when you need more information.
However, logging frameworks normally require you, the programmer, to explicitly tell it what to log. It doesn't simply log everything (that would be a lot of data too!).
It sounds like what you want is logging in your application. See the Wikipedia article for Java Logging Frameworks for details.
Some of the more common logging frameworks, all mentioned in the aforementioned article, are:
Log4J
Java Logging API
Apache Commons Logging
SLF4J
I'm currently looking at upgrading the logging mechanism in a medium-to-large-sized Java codebase. Messages are currently logged using static methods on a Debug class, and I have recommended switching from this to something like SLF4J or commons-logging.
The application architect prefers that I encapsulate the dependency on SLF4J (possibly by wrapping it up in the aforementioned Debug class). This will make it easier to change the logging implementation in the future.
This seems like overkill to me, as SLF4J is already abstracting the concrete logging implementation.
Is it worth wrapping a 3rd-party logging abstraction like SLF4J in another home-grown abstraction?
I entirely agree with you: wrappers of wrappers of wrappers are getting out of hand. I suspect that architect doesn't realize how SLF4J in particular can easily wrap any other logging system, so that "changing implementation" is perfectly feasible without yet another layer of wrappage.
I guess the motivation behind the architect's desire to wrap the wrapper (i.e. SLF4J), is to isolate your application from SLF4J. Clearly, invoking the SLF4J API from within your application creates a dependency on SLF4J. However, it is equally legitimate to want to apply the isolation principle repeatedly as discussed below. It reminds me of Richard Dawkins' question: If God created the universe, then who created God?
Indeed, you could also apply the isolation principle on the wrapper that wraps SLF4J. The cause of isolation would be ill served if the SLF4J-wrapper was somehow inferior to SLF4J. Although possible, it is rather rare for a wrapper to equal or surpass the original. SWT can be cited as a noteworthy counter-example. However, SWT is a sizable project with a significant cost. More to the point, an SLF4J-wrapper by definition depends on SLF4J. It is bound to have the same general API. If in the future a new and significantly different logging API comes along, code that uses the wrapper will be equally difficult to migrate to the new API as code that used SLF4J directly. Thus, the wrapper is not likely to future-proof your code, but to make it heavier by adding an additional indirection.
In short, even if you didn't have anything better to do, you shouldn't waste your time wrapping SLF4J because the added value of your wrapper is guaranteed to be near zero.
The topic is also broached in an SLF4J FAQ entry.
I would prefer to wrap it, but not for the stated reason. If the concern is the ability to swap out for another framework, use java.util.logging or SLF (java.util.logging isn't as easy to use as a wrapper, but it is quite doable), and swap away. The reason to use (yet another) wrapper is to codify in code the appropriate way of logging. Generally an application wants a subset, such as all system errors come with an exception, or have specific guidance about when to use the standard logging levels. Those decisions can be encapsulated in a few methods creating more consistent logging decisions over a large code base.
If, however, the motivation is just to make it possible to swap out implementations, don't reinvent the wheel. SLF is perfect for the job, just use it.
There is one exception to this. If your code is meant to be deployed into many possible app servers seemlessly, you do have to make sure that your logging choice doesn't risk conflicting with potentially older or newer versions of whatever the framework is using.
Explain to your Architecture Astronaut that slf4j already can act as a wrapper for other logging implementations, like log4j. So if you need to use some other logger in the future and there is no adapter for slf4j, you can write it when the need arises, but it will just be the adapter, instead of writing a whole logging framework that will just wrap some other logging framework and you need to design your framework for that and write your own adapter.
The problem with every wrapper is the decision of how you'll actually wrap and which functionality you'll provide:
commons.logging is providing a minimal set of logging functionality, hiding away additional functionality that the underlying framework might provide. You won't get advanced features like parameterized logging or the MDC.
SLF4J works the other way around. It handles advanced features like parameterized logging by implementing them on top of frameworks that aren't implementing them natively. This is the better way, IMHO.
I don't know your current Debug class but I guess it's pretty basic.
You probably won't have features like
the location of the logging message, i.e. name of the source file + line number
different logging levels
the ability to selectively set the level of different loggers, i.e. you don't have one logger per class, having the ability to set that logger to a certain level of interest, e.g. INFO, WARN. This is pretty crucial.
If your Debug class is pretty basic this is actually very nice for you :)
It means that you are likely able to switch over to SLF4J by performing a global search & destr... err... replace.
Make backups, though... ;)
See also Should new projects use logback instead of log4j?, What’s Up with Logging in Java?, Which log4j facade to choose?, Find a way in the java logging frameworks scene. and Do you find java.util.logging sufficient?. (Spoiler: You shouldn't use java.util.logging, pretty please)
If you're thinking of switching Logging frameworks in the future, it may be worthwhile to add an extra layer to where you can switch out the logger. Otherwise, if they provide everything that you will possibly need(using your crystal ball, of course) then it is probably ok to have a hard dependency on that framework.
If your current setup allows flexibility to change, you don't need a wrapper.