Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to deal with logging in production code (logback/slf4j)

I've implemented an algorithmic framework consisting of several classes. For logging, I use slf4j and logback. So many of my classes have code like:

protected final Logger logger = LoggerFactory.getLogger(Myclass.class);
...
logger.debug("Some debug information");

Now I would like to package my code and make it production ready. What do I do with the logging code?

  1. When running the code, a developer would typically want to turn off the logging for performance reasons.
  2. While developing the code the debug information is very helpful so removing all debug statements would be a bad idea.

So ideally users should be able to enable/disable logging. I normally have a logback.xml configuration file which specifies the log level on a per-class basis. Should I include such a file in the package? Or should I expect users to write their own or supply a default configuration file?

I do have code to configure the algorithms:

/**
* Read algorithm confirguration from properties file
**/    
protected Configuration(Properties properties){...}

This function reads a properties file and sets a number of algorithmic parameters accordingly. Could this be of use to enable/disable logging for various classes?

like image 207
Joris Kinable Avatar asked May 14 '15 22:05

Joris Kinable


2 Answers

SLF4J and logback have very little performance impact if logging to a level that is turned off. I've never come across a problem with just leaving the logging code in. It also has the added benefit of you being able to turn on debug logging in production environment to get more information about a sporadically happening problem.

Since you create the loggers with the classes, you can simply configure those loggers not to have an appender if you do not want any logging output from your framework. Or set the level to a value you are comfortable with in a productive environment - just remember to turn off additivity, so events aren't propagated to the root logger. The syntax is described here: http://logback.qos.ch/manual/configuration.html#syntax

Another simple idea to enable your user to turn off logging from your framework with an easy switch is to use a marker with an appropriate filter. You can change all your logging calls to start with a marker:

private Marker MY_MARKER = MarkerFactory.getMarker("FrameworkMarker");

logger.debug(MY_MARKER, "Some debug information");

That allows you to suppress all logging output marked with this specific marker with a single TurboFilter defined in your application's logback.xml:

http://logback.qos.ch/manual/filters.html#TurboFilter

<turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
    <Marker>FrameworkMarker</Marker>
    <OnMatch>DENY</OnMatch>
</turboFilter>

The MarkerFilter has the added benefit of not caring about the level. Any logging event with the specified marker is filtered out (and in an efficient way, as described in the documentation).

Personally, I would go with both. That way you can use all the logging levels in your framework and deactivate its logging completely via the MarkerFilter if needed, but can also reap the benefits of detailed and level-specific logging when you need it.

like image 159
sheltem Avatar answered Sep 24 '22 18:09

sheltem


You can turn Logback OFF at runtime by calling:

logger.setLevel(Level.OFF);

This will turn OFF all levels for the calling logger (TRACE, DEBUG, INFO WARN, ERROR will be turned off)

Logback manual states:

Logging performance when logging is turned off entirely

You can turn off logging entirely by setting the level of the root logger to Level.OFF, the highest possible level. When logging is turned off entirely, the cost of a log request consists of a method invocation plus an integer comparison. On a 3.2Ghz Pentium D machine this cost is typically around 20 nanoseconds.

Read more about this at the Logback manual architechture page

Advanced: A good practice will be to have gradle set the build level according to build type. development or production etc. (setting a variable that runtime code can read later on)

like image 21
Mercury Avatar answered Sep 25 '22 18:09

Mercury