Advanced Java - IX - Java Logging

Jalaz Kumar · September 19, 2020

Logging means some way by which we can get indication about the state of the system at runtime.

These log messages are written during program execution to a central place.

Logging allows us to record and persist system states as messages (e.g., runtime statistics) so that they can later be retrieved and analyzed.

Requirements for good logging:

  • logs must provide sufficient information for understanding the appliation internal processing
  • log writing process should be efficient & must not affect the performance.
  • logging needs to be modified and adapted as per different deployment environments.

Advantages of logging:

  • Quick debugging
  • Diagnosis of problems precisely and quickly
  • Easy maintenance comes along with quick debugging feature.
  • Cost anf time savings

Disadvantages of logging:

  • logging adds runtime overhead for generation and writing of log information using device IO.
  • logging increase size of code and adds programming overhead.
  • bad logging causes confusion.
  • logging requires proper planning beforehand.

Frameworks for logging:

  • SLF4J
  • Log4J
  • java.util.logging

Java.Util.logging package

Java JRE implicitly contains the Java Logging API. This logging API allows you to configure which message types are written. The java.util.logging package provides the logging capabilities via the Logger class.

The basic logging levels are:

Level Value Usage
SEVERE 1000 Indicates some serious failure
WARNING 900 Potential Problem
INFO 800 General Info
CONFIG 700 Configuration Info
FINE 500 General developer info
FINER 400 Detailed developer info
FINEST 300 Specialized Developer Info
OFF Integer.MAX_VALUE Capturing nothing
ALL Integer.MIN_VALUE Capturing Everything

LogManager class

  • Provides single global instance to interact with log files.

  • Has static method: getLogManager()

  • The log system is centrally managed. There is only one application wide log manager which manages both the configuration of the log system and the objects that do the actual logging.

Logger class

  • Provides methods for logging

  • LogManager is the one doing actual logging, its instances are accessed using the getLogger() method of LogManager class.

  • Has a static field GLOBAL_LOGGER_NAME, which accesses global logger instance.

  import java.io.IOException;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import java.util.logging.*;

  class DemoLogger {
      private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);

      public void makeSomeLog() {
          LOGGER.log(Level.INFO, "Log generated from the logger class");
      }
  }

  public class LoggerExample {
      public static void main(String[] args)
      {
          DemoLogger obj = new DemoLogger();
          obj.makeSomeLog();

          LogManager lgmngr = LogManager.getLogManager();
          Logger log = lgmngr.getLogger(Logger.GLOBAL_LOGGER_NAME);
          log.log(Level.INFO, "Log generated from the main class");
      }
  }

OUTPUT

  Sep 19, 2020 7:56:33 PM DemoLogger makeSomeLog
  INFO: Log generated from the logger class
  Sep 19, 2020 7:56:33 AM LoggerExample main
  INFO: Log generated from the major class

Log4J logging

Introduction

  • Fast, reliable & flexible logging framework
  • Written in Java
  • Open-source logging API
  • Allows storage of logs in a file or DB
  • Works well with large or small projects

Features

  • Thread-safe
  • Optimised for speed
  • Uses named logger hierachy as base
  • Supports multiple outputs of appenders per logger
  • log formatting can be easily altered
  • Specially designed to manage java exceptions
  • logging behavior can be set at runtime using configuration file.

Setup & Usage

Add the following entry to the pom.xml file:

<dependency>  
    <groupId>log4j</groupId>  
    <artifactId>log4j</artifactId>  
    <version>1.2.17</version>  
</dependency>

Running with most basic configuration:

import org.apache.log4j.BasicConfigurator;  
import org.apache.log4j.LogManager;  
import org.apache.log4j.Logger;  

public class Log4JBasic {  
    private static final Logger logger  = LogManager.getLogger(HelloWorld.class);  
    public static void main(String[] args) {
        BasicConfigurator.configure();  
        logger.info("Basic logging of information");
    }    
}

Log4J Architecture

Follows layered architecture where each layer provides different objects for doing different tasks.

2 types of objects:

  • Core Objects
    • Mandatory objects of the framwork
    • Are: Logger, Appender, Layout
  • Support Objects
    • Optional objects of the framework
    • Supports core objects in performing additional but important tasks
    • Are: Level, Filter, ObjectRenderer, LogManager

Logger object:

  • Core object
  • This forms the top-level layer of the framework
  • Responsible for taking logging info and storing in namespace hierarchy
  • For each class, one Logger object is created which enables log4j there.
      static Logger log = Logger.getLogger(ClassName.class.getName())
    
  • Methods of Logger are used to generate log statements.
    • debug()
    • info()
    • warn()
    • error()
    • fatal()

Priority order: debug < info < warn < error < fatal

Appender object:

  • Core object
  • Responsible for publishing logging info to preferred destination which may be a file, database, console etc.
  • Appender is an interface not a class. Different implementation classes are:
    • FileAppender
    • ConsoleAppender
    • JDBCAppender
    • SMTPAppender
    • SocketAppender
    • SyslogAppender

Layout object:

  • Core object
  • Used to format logging info in different styles.
  • Supports appender objects before publishing of logs.
  • Helps in publishing logs in human-readable manner.
  • Various layout classes:
    • SimpleLayout
    • PatternLayout
    • HTMLLayout
    • XMLLayout

logging-architecture

Level object:

  • Support object
  • Defines the priority and granularity of logging info.
  • 7 levels of logging: OFF, DEBUG, INFO, ERROR, WARN, FATAL, ALL

Filter object:

  • Support object
  • Analyses logging info and decides whether info should be logged or not

ObjectRenderer object:

  • Support object
  • Specialised in providing string representation of objects.
  • Used by the Layout object for preparing the final logging info.

LogManager object:

  • Support object
  • Manages the logging framework
  • Used for reading configuration from system-wide file or configuarion class.

Configuration file

  • log4j.properties stores properties in key-value pair.
  • Contains the entire runtime configuration used by log4j.
  • By default, LogManager searches for this file name in CLASSPATH.
  # Root logger option  
  log4j.rootLogger=INFO, file, stdout  

  # Direct log messages to a log file  
  log4j.appender.FILE=org.apache.log4j.FileAppender  
  log4j.appender.file.File=${catalina.home}/logs/api.log  
  log4j.appender.file.layout=org.apache.log4j.PatternLayout  
  log4j.appender.file.layout.ConversionPattern=%m%n

  # Direct log messages to stdout  
  log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
  log4j.appender.stdout.Target=System.out
  log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
  log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n  

Logging levels - Used for categorizing entries in the log file in a manner of urgency. - Using these, filtering is possible during search. - Using these, amount of info to be logged can be managed. - Each log message is prefixed by the level. - They are an instance of org.apache.log4j.Level class.

```bash
log4j.rootLogger=ERROR, serviceAppender
log4j.appender.serviceAppender=org.apache.log4j.ConsoleAppender  
log4j.appender.serviceAppender.layout=org.apache.log4j.PatternLayout  
log4j.appender.serviceAppender.layout.ConversionPattern=[%t] %-5p %c %x - %m%n  

log4j.logger.tech.jaykay12.group-search=INFO, serviceAppender  
log4j.logger.tech.jaykay12.group-search.logic=DEBUG, serviceAppender
```

![logging-levels](../assets/images/JA-24.png)

Logging methods - Logger class has methods to handle logging activities.

- Supports 2 static methods for obtaining Logger object:
   - _public static Logger getRootLogger();_
   - _public static Logger getLogger(String name);_

- Methods for printing log info:
   - _public void debug(Object message)_
   - _public void error(Object message)_
   - _public void fatal(Object message)_
   - _public void info(Object message)_
   - _public void warn(Object message)_
   - _public void trace(Object message)_

Twitter, Facebook