Our goal is to figure out how to quickly enable logging for some selected methods or for all methods in the class.

We already considered in one of our posts how to log method with parameters in Java with AspectJ

In this post we’re going to know how to do it easier with the open source library EasyLog (Site, Source code).

EasyLog uses a similar approach and suggests a lot of additional useful features.

Start logging methods

With EasyLog we can start logging by adding the @LogIt annotation to the method that we want to log

    @LogIt
    public Universe bigBang(int numberOfStars, int numberOfBlackHoles) {
        ...
    }

Easy, isn’t it?

If we annotate a class then we activate logging for all the methods that the class contains.

    @LogIt
    public class Universe {
    ...
    }

That’s it. Now we log every method call with all parameters passed and the result returned if any.

This is how our log will look like

2018-06-29 14:40:47.139  INFO 12128 --- [           main] UneasyLogger                             : 
-> public Universe Universe.bigBang(int numberOfStars, int numberOfBlackHoles)
"numberOfStars": 3,
"numberOfBlackHoles": 3

2018-06-29 14:40:47.141  INFO 12128 --- [           main] UneasyLogger                             : 
Execution/Response time:  1ms
<- Universe Universe.bigBang(int numberOfStars, int numberOfBlackHoles)
{
  "stars": [
    {
      "name": "Star-095f0bae-5641-4222-a0ce-bc16ea8915c7",
      "type": "RED_GIANT",
      "planets": []
    },
    {
      "name": "Star-2d2f8a18-3f4e-412b-8c80-c5a888136b20",
      "type": "WHITE_DWARF",
      "planets": [
        {
          "name": "Planet-07fda21d-dd47-47ef-b5e0-77c7e0ad6a4f",
          "haveSatellites": true
        },
        {
          "name": "Planet-543a6616-e7f6-437d-883c-dd6612a69707",
          "haveSatellites": false
        }
      ]
    },
    {
      "name": "Star-bbd54023-6776-4f5d-b5a6-7f7bfa961b21",
      "type": "SUPERGIANT",
      "planets": [
        {
          "name": "Planet-cba33a76-a2b8-4994-a7d9-1e5f487f1b4c",
          "haveSatellites": false
        }
      ]
    }
  ],
  "blackHoles": [
    {
      "name": "BlackHole-a6c1c065-ec95-4f75-aa3e-fb42479696f0"
    },
    {
      "name": "BlackHole-3a462579-d83d-492e-9ddf-7bbe2fcd2b43"
    },
    {
      "name": "BlackHole-d204dba0-9655-4a97-a144-a8de9ddaadf8"
    }
  ],
  "dateOfCreation": "Jun 29, 2018 2:40:47 PM"
}

Awesome!

LogIt annotation parameters

Let’s take a look at the parameters that @LogIt annotation contains

public @interface LogIt {

    String label() default "";

    Level level() default INFO;

    String[] ignoreParameters() default {};

    String[] maskFields() default {};

    boolean prettyPrint() default true;

    boolean logNulls() default true;

}


Level level

level parameter sets the logging level.

We can set different levels for different methods!

By default it’s INFO.

Available options: DEBUG, INFO, WARN, ERROR

@LogIt(level = INFO)


String label

Labels help you to simplify a search for specific entries in the logs. Just pass another annotation parameter String label.

By default it’s an empty String

@LogIt(label = "USER SERVICE CALL")


String[] ignoreParameters

The ignoreParameters parameter allows you to exclude some of parameters from logging

@LogIt(ignoreParameters = {"checksum"})


String[] maskFields

You can also mask some fields of the objects that you pass to a method and the object that the method returns.

Note: EasyLog doesn’t modify returned results or passed parameters, just changes how they look in the logs.

Might be used for:

  • masking any sensitive information that shouldn’t be logged

  • decreasing the amount of logged info. For example we can replace huge lists/arrays (in returned results) that are not important in terms of logging with "XXXMASKEDXXX"

@LogIt(maskFields = {"password"})

All the field values will be replaced with "XXXMASKEDXXX"

Logging Styles

Available values: PRETTY_PRINT_WITH_NULLS, PRETTY_PRINT_NO_NULLS, COMPACT_WITH_NULLS, MINIMAL, AS_IS. By default it’s PRETTY_PRINT_WITH_NULLS

Here PRETTY_PRINT means “pretty printed JSON”. COMPACT_WITH_NULLS and MINIMAL also mean JSON but not “pretty printed”

See the difference

COMPACT_WITH_NULLS and MINIMAL

@LogIt(style = COMPACT_WITH_NULLS, maskeFields = {"password"})

or

@LogIt(style = MINIMAL, maskeFields = {"password"})

These will give you

{"user":{"zipcode":"12345","firstName":"John","lastName":"Smith","password":"XXXMASKEDXXX","email":"myemail@mysite.com"}}

PRETTY_PRINT_WITH_NULLS and PRETTY_PRINT_NO_NULLS

@LogIt(style = PRETTY_PRINT_WITH_NULLS, maskeFields = {"password"})

or

@LogIt(style = PRETTY_PRINT_NO_NULLS, maskeFields = {"password"})

will give you

{  
   "user":{  
      "zipcode":"12345",
      "firstName":"John",
      "lastName":"Smith",
      "password":"XXXMASKEDXXX",
      "email":"myemail@mysite.com"
   }
}

Use PRETTY_PRINT_WITH_NULLS and COMPACT_WITH_NULLS if you want to log (serialize) null’s

Use PRETTY_PRINT_NO_NULLS and MINIMAL if you want to exclude nulls from logging.

AS_IS is used if you want to serialize the parameters and returned result with the toString method. In this case maskFields will be ignored

How to setup EasyLog

There are two example projects where you can get familiar with how to make all that beauty real

There is a difference because we setup our pom.xml differently and use different loggers EasyLogger and EasyLoggerNoSpring for Spring and non-Spring projects.

EasyLog Site | Source Code

Maven Central


You may also find these posts interesting: