Java conditional logging with the logging API - java

I understand that I can use
Logger.setLevel(<level here>);
To set the level of logging (turn it off, turn it on, etc). However, I'm not sure how I can conditionally log based on the log level the user specifies.
In essence, I have a class that uses the logging API. I wish to give the user of the class the power to configure the log level how they please. I've seen this done with log4j but not with the logging API.
Is there a best practice for this? Should I just have some function
setLogLevel()
that the user can pass a Level.INFO or whatever to? Or is there a better way?
Thank you!

I'm not sure, if understand this question correctly, but you shouldn't set the logging level from the code, which calls the logger. The idea behind logging is, that the developer logs all messages at the appropriate level. For example "Started to compute xyz" at DEBUG level, "New user have been set into DB" at INFO level and "Caught exception from..." at ERROR level. The logger will print the message only if it has the same or higher logging level. The logging level should be set according to environment, for example DEBUG for development and INFO for production, from outside the application.
Conditional logging is useful if the creation of the message is time consuming and you don't want to create the log message unless it will be really logged (check out this link). If you want to check, that the logger from the java.util.logging will actually log at given level, you can use this method.

However, I'm not sure how I can conditionally log based on the log level the user specifies.
Your question is unclear, but I think you are asking how log stuff depending on the log level that the user sets. The answer to that is that you just write your log statements normally; e.g.
logger.warning("Danger Will Robinson");
...
anotherLogger.info("It's good to be alive");
... and let the user specify what logging to capture using the logging configuration. Generally speaking the logging configuration is specified by a config file that is loaded at runtime, and can be altered by the user. It is also possible to create or alter the logging configuration programmatically, though presenting this functionality to the user via some kind of user-friendly UI is going to be something of a challenge.
In theory, it is also possible to a given log events at different levels depending on some condition. However, you are probably taking control away from the user by doing that.

Related

Functionality level configurable logger enable in Log4j2

I want to implement a logger at a functionality level in my application. so when and where log needed for debugging I can turn on and start logged activities. For example, i want to enable logging for registration functionality only.
I am not sure that this is possible or not but my requirement is like that. If possible please give a solution or any insight on that is appreciatable.
If you use the slf4j/log4j API, this is a feature you get pretty much "for free". If you follow the standard practice of creating a logger for each of your classes, via a line like:
static Logger log = LoggerFactory.getLogger(UserRegistration.class);
and use that logger for all logging in that class. You also choose the appropriate log level for each of your logging calls (WARN, INFO, DEBUG, etc.). Then you can turn the log level up/down in your logging configuration file for just one class with a line like this:
<logger name="com.mycompany.util.registration.UserRegistration"><level value="DEBUG"/></logger>
You can also turn the logging level up/down for the whole module that this class comes from with a line like:
<logger name="com.mycompany.util.registration"><level value="DEBUG"/></logger>
You use config lines like these to turn on certain log calls by raising them above the default log level you've set. You set the default log level with something like this:
<root><level value="WARN" /></root>
So with just these lines, you would only get WARN level logging for most of your code, but for that one module or class file, you'd also get INFO and DEBUG level logging.
You can do more complicated things, like send logging for certain parts of your code to a special log file. Maybe that's what you're talking about when you say you only want to log "registration functionality". You could set up your logging config so that only classes involved in "registration" are sent to a special file.
The main point of this is that you don't need to think about this too much in advance. You just attach the name of each class to all the logging calls made in that class, and choose the appropriate log level (WARN, INFO, DEBUG) for each of your logging calls, and you can decide later via your logging config file what you want to see or not see, and where you want logging information to go.
You can use API calls to configure logging more dynamically when your program first starts, or even while it is running. The main point, again, is that you don't think ahead about which parts of your code you want to see detailed logging for. You just put logging calls everywhere, and then decide which ones you actually see the output from later on.

When to use log4j over system out

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

How to use log levels in java

I am developing an application where i need to use the logger functionality. I have read about different levels of logger which are:
SEVERE (highest)
WARNING
INFO
CONFIG
FINE
FINER
FINEST
I am not able to understand the usage of each logging level.
Can someone give me a good example showing all the logging levels and their usage?
Generally, you don't need all those levels, SEVERE, WARNING, INFO, FINE might be enough. We're using Log4J (not java.util.logging directly) and the following levels (which might differ in name from other logging frameworks):
ERROR: Any error/exception that is or might be critical. Our Logger automatically sends an email for each such message on our servers (usage: logger.error("message"); )
WARN: Any message that might warn us of potential problems, e.g. when a user tried to log in with wrong credentials - which might indicate an attack if that happens often or in short periods of time (usage: logger.warn("message"); )
INFO: Anything that we want to know when looking at the log files, e.g. when a scheduled job started/ended (usage: logger.info("message"); )
DEBUG: As the name says, debug messages that we only rarely turn on. (usage: logger.debug("message"); )
The beauty of this is that if you set the log level to WARN, info and debug messages have next to no performance impact. If you need to get additional information from a production system you just can lower the level to INFO or DEBUG for a short period of time (since you'd get much more log entries which make your log files bigger and harder to read). Adjusting log levels etc. can normally be done at runtime (our JBoss instance checks for changes in that config every minute or so).
This excerpt is from the following awesome post.
ERROR – something terribly wrong had happened, that must be
investigated immediately. No system can tolerate items logged on this
level. Example: NPE, database unavailable, mission critical use case
cannot be continued.
WARN – the process might be continued, but take extra caution.
Actually I always wanted to have two levels here: one for obvious
problems where work-around exists (for example: “Current data
unavailable, using cached values”) and second (name it: ATTENTION) for
potential problems and suggestions. Example: “Application running in
development mode” or “Administration console is not secured with a
password”. The application can tolerate warning messages, but they
should always be justified and examined.
INFO – Important business process has finished. In ideal world,
administrator or advanced user should be able to understand INFO
messages and quickly find out what the application is doing. For
example if an application is all about booking airplane tickets, there
should be only one INFO statement per each ticket saying “[Who] booked
ticket from [Where] to [Where]“. Other definition of INFO message:
each action that changes the state of the application significantly
(database update, external system request).
DEBUG – Developers stuff. I will discuss later what sort of
information deserves to be logged.
TRACE – Very detailed information, intended only for development. You
might keep trace messages for a short period of time after deployment
on production environment, but treat these log statements as
temporary, that should or might be turned-off eventually. The
distinction between DEBUG and TRACE is the most difficult, but if you
put logging statement and remove it after the feature has been
developed and tested, it should probably be on TRACE level.
PS: Read TRACE as VERBOSE
The java.util.logging.Level documentation does a good job of defining when to use a log level and the target audience of that log level.
Most of the confusion with java.util.logging is in the tracing methods. It should be in the class level documentation but instead the Level.FINE field provides a good overview:
FINE is a message level providing tracing information.
All of FINE, FINER, and FINEST are intended for relatively detailed tracing. The exact meaning of the three levels will vary between subsystems, but in general, FINEST should be used for the most voluminous detailed output, FINER for somewhat less detailed output, and FINE for the lowest volume (and most important) messages.
In general the FINE level should be used for information that will be broadly interesting to developers who do not have a specialized interest in the specific subsystem.
FINE messages might include things like minor (recoverable) failures. Issues indicating potential performance problems are also worth logging as FINE.
One important thing to understand which is not mentioned in the level documentation is that call-site tracing information is logged at FINER.
Logger#entering A LogRecord with message "ENTRY", log level FINER, ...
Logger#throwing The logging is done using the FINER level...The LogRecord's message is set to "THROW"
Logger#exiting A LogRecord with message "RETURN", log level FINER...
If you log a message as FINE you will be able to configure logging system to see the log output with or without tracing log records surrounding the log message. So use FINE only when tracing log records are not required as context to understand the log message.
FINER indicates a fairly detailed tracing message. By default logging calls for entering, returning, or throwing an exception are traced at this level.
In general, most use of FINER should be left to call of entering, exiting, and throwing. That will for the most part reserve FINER for call-site tracing when verbose logging is turned on.
When swallowing an expected exception it makes sense to use FINER in some cases as the alternative to calling trace throwing method since the exception is not actually thrown. This makes it look like a trace when it isn't a throw or an actual error that would be logged at a higher level.
FINEST indicates a highly detailed tracing message.
Use FINEST when the tracing log message you are about to write requires context information about program control flow. You should also use FINEST for tracing messages that produce large amounts of output data.
CONFIG messages are intended to provide a variety of static configuration information, to assist in debugging problems that may be associated with particular configurations. For example, CONFIG message might include the CPU type, the graphics depth, the GUI look-and-feel, etc.
The CONFIG works well for assisting system admins with the items listed above.
Typically INFO messages will be written to the console or its equivalent. So the INFO level should only be used for reasonably significant messages that will make sense to end users and system administrators.
Examples of this are tracing program startup and shutdown.
In general WARNING messages should describe events that will be of interest to end users or system managers, or which indicate potential problems.
An example use case could be exceptions thrown from AutoCloseable.close implementations.
In general SEVERE messages should describe events that are of considerable importance and which will prevent normal program execution. They should be reasonably intelligible to end users and to system administrators.
For example, if you have transaction in your program where if any one of the steps fail then all of the steps voided then SEVERE would be appropriate to use as the log level.
Here is a good introduction to logging in Java:
http://www.javapractices.com/topic/TopicAction.do?Id=143
Java comes with a logging API since it's 1.4.2 version:
http://download.oracle.com/javase/1.4.2/docs/guide/util/logging/overview.html
You can also use other logging frameworks like Apache Log4j which is the most popular one:
http://logging.apache.org/log4j
I suggest you to use a logging abstraction framework which allows you to change your logging framework without re-factoring you code. So you can starts by using Jul (Java Util Logging) then swith to Log4j without changing you code. The most popular logging facade is slf4j: http://www.slf4j.org/
Regards,
Those are the levels. You'd consider the severity of the message you're logging, and use the appropriate levels.
It's basically a watermark; the higher the level, the more likely you want to retain the information in the log entry. FINEST would be for messages that are of very little importance, so you'd use it for things you usually don't care about but might want to see in some rare circumstance.
The use of levels is really up tp you. You need to decide what is severe in your application, what is a warning and what is just information. You need to split your logging so that your users can easily set up a level of logging that doesn't kill the system with excessing IO but which will report serious errors so you can fix them.
Logging has different levels such as :
Trace – A fine-grained debug message, typically capturing the flow through the application.
Debug- A general debugging event should be logged under this.
ALL – All events could be logged.
INFO- An informational purpose, information written in plain english.
Warn- An event that might possible lead to an error.
Error- An error in the application, possibly recoverable.
Logging captured with debug level is information helpful to developers as well as other personnel, so it captures in broad range. If your code doesn't have exception or errors then you should be alright to use DEBUG level of logging, otherwise you should carefully choose options.
I can't see ANY answers according java.util.logging.Logger, so there are 9 levels you can use under your needs:
ALL indicates that all messages should be logged.
CONFIG is a message level for static configuration messages.
FINE is a message level providing tracing information.
FINER indicates a fairly detailed tracing message.
FINEST indicates a highly detailed tracing message.
INFO is a message level for informational messages.
OFF is a special level that can be used to turn off logging.
SEVERE is a message level indicating a serious failure.
WARNING is a message level indicating a potential problem.
the different log levels are helpful for tools, whose can anaylse you log files. Normally a logfile contains lots of information. To avoid an information overload (or here an stackoverflow^^) you can use the log levels for grouping the information.
This tip shows how to use Logger in any java application. Logger needs to configure Formatter and Handler. There are many types of handlers and formatters present. In this example FileHandler is used to store all the log messages in a log file. And Simple formatter is used to format the log messages in human readable form.
package MyProject;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class MyLogger {
public static void main(String[] args) {
Logger logger = Logger.getLogger("MyLog");
FileHandler fh;
try {
// This block configure the logger with handler and formatter
fh = new FileHandler("c:\\MyLogFile.log", true);
logger.addHandler(fh);
logger.setLevel(Level.ALL);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
// the following statement is used to log any messages
logger.log(Level.WARNING,"My first log");
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
some more examples you can find here
https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html

What information to include at each log level? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Where/what level should logging code go?
Debug Levels
Is there a convention, a standard, or a widely used guide which will help with logging in Java? Specifically, what to include at each level (verbose, debug, ... etc.) rather than the actual mechanism of logging.
There are many guides out there of what to include at each log level, but none of them are specific; they're all vague, and this makes it hard to "follow orders".
Any tips would be appreciated.
It's subject to personal interpretation, but mine is (in order from finest to coursest):
Trace - The finest logging level. Can be used to log very specific information that is only relevant in a true debugging scenario, e.g., log every database access or every HTTP call etc.
Debug - Information to primary help you to debug your program. E.g., log every time a batching routine empties its batch or a new file is created on disk etc.
Info - General application flow, such as "Starting app", "connecting to db", "registering ...". In short, information which should help any observer understand what the application is doing in general.
Warn - Warns of errors that can be recovered. Such as failing to parse a date or using an unsafe routine. Note though that we should still try to obey the fail fast principle and not hide e.g., configuration errors using warning message, even though we a default value might be provided by the application.
Error - Denotes an often unrecoverable error. Such as failing to open a database connection.
Fatal/Critical Used to log an error the application cannot recover from, which might lead to an immediate program termination.
In the end it's up to you to define what suits you best. Personally, I run most production system with logging level of Info, where I'm mostly interested in following the applications main logic, and of course catch all warnings/errors.
Except for code cluttering, there is no such thing as too much logging. All logging which helps you reproduce or understand problems better are good logging. On a performance note, most logging systems (e.g., log4j) allows configuring which level to actually append to the physical log which is a great thing.
For what it's worth, we're using the following log levels:
DEBUG level messages give highly-detailed and/or specific information, only useful for tracking down problems.
INFORMATION messages give general information about what the system is doing. (e.g. processing file X)
WARNING messages warn the user about things which are not ideal, but should not affect the system. (e.g. configuration X missed out, using default value)
ERROR messages inform the user that something has gone wrong, but the system should be able to cope. (e.g. connection lost, but will try again)
CRITICAL messages inform the user when an un-recoverable error occurs. (i.e. I am about to abort the current task or crash)
I think the most important thing with log levels is to figure out a scheme, document it, and stick with it. Although making log level consistent between programs would be nice, as long as you've used common sense in defining your log levels, users will tolerate a certain amount of variance between programs.
Simple log what yuo think is important if you were to come back later and need to read the logs. This of course means that your Object.toStrings now need to be nice and readable and not a dump of crap thats impossible to read. This also means you need to do sensible things like quoting strings etc..

log4j vs. System.out.println - logger advantages?

I'm using log4j for the first time in a project. A fellow programmer told me that using System.out.println is considered a bad style and that log4j is something like standard for logging matters nowadays.
We do lots of JUnit testing - System.out stuff turns out to be harder to test.
Therefore I began utilizing log4j for a Console controller class, that's just handling command-line parameters.
// log4j logger config
org.apache.log4j.BasicConfigurator.configure();
Logger logger = LoggerFactory.getLogger(Console.class);
Category cat = Category.getRoot();
Seems to work:
logger.debug("String");
Produces:
1 [main] DEBUG project.prototype.controller.Console - String
I got two questions regarding this:
From my basic understanding using this logger should provide me comfortable options to write a logfile with timestamps - instead of spamming the console - if debug mode is enabled at the logger?
Why is System.out.println harder to test? I searched stackoverflow and found a testing recipe. So I wonder what kind of advantage I really get by using log4j.
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.
I don't think that using loggers offers any significant advantages in unit tests, but I'd prefer it even there anyways. In unit tests asserts are usually my primary concern.
Btw you should really consider using something like Commons Logging or SLF4J as a log framework facade - it's bad style to tie your code to a specific logging framework. Common Logging and SLF4J make it easy to switch logging frameworks if you choose to.
Anything that you print to System.out will go to "standard out", and while you can redirect standard out to a file and compare it, what have you, that is very inflexible. Additionally, you cannot filter what goes to standard out if you use System.out... everything will be printed. With log4j, you can set different logging levels, so that logging messages that are below a certain severity/importance threshold are not printed (e.g. if you change the logging level to WARN, then DEBUG and INFO messages will not be displayed anymore).
Additionally, log4j allows logging to be controlled on a class-by-class basis, whereas System.out can only be controlled at the granularity of the entire application (if you redirect System.out, you redirect it for the entire program). By contrast, each logger in log4j can be given a different appender. In addition, you can give a log4j logger multiple appenders (so that it goes the system logger, and over the network, for example). You can even have a log4j logger append to a StringBuilder, so that you can easily read what was written. And while System.out can be redirected, this redirection tends to be fairly limited; System.out can be redirected to a file or to a pipe (to another program), but you wouldn't be able to redirect it to a URL, for example; by contrast, it would be very easy to create an appender that transmits logging messages using HTTP POST.
Use e.g.
org.apache.log4j.BasicConfigurator.configure(new FileAppender(
new PatternLayout("%d{ISO8601} %-5p %t: %m%n"), // see e.g. http://en.wikipedia.org/wiki/Log4j#TTCC
"log/mainWhatever.log"));
Using logger.setLevel(...) you can easily choose whether to display logger.debug(..) messages, e.g. set it to level warn and any trace, debug and info statements will not be printed. This saves you the time of having to comment out only occasionally needed debug statements.
Also have a look at Wikipedia.
Using logger.setLevel(...) you can easily choose whether to display logger.debug(..) messages, e.g. set it to level warn and any trace, debug and info statements will not be printed. This saves you the time of having to comment out only occasionally needed debug statements
In the case of log4j,It provide a middle ware service where you can manage logging levels like DEBUG,INFO,ERROR etc. And you can enable and disable logging.But in the case of System.out.println() you have to manage every thing.

Categories

Resources