Logging Information
Log Levels
The default log level in our environments is WARN.
-
Trace - This is for Devs/Testers, used for "tracing" code execution through the stack. Generally this is never turned on in any environments.
-
Debug - This is also for Devs/Testers, used similarly as Trace, but with a more narrowed focus. Usually these are helpful for tracking conditionals/branches, rather than execution statements.
-
Info - This is for Ops (NOT Testers), usually for process monitoring. Rarely should this be an active log level output other than startup.
-
Warn - This is also for Ops, indicating something is not performing as expected, but the service can still function. Kinda like a "Hey, make sure to watch this, something might be wrong."
-
Error - this is for everyone, indicating something failed and needs to be looked at.
In the most optimal world, you would NEVER see "Error" logs, and we should always attempt to keep them from happening. Sometimes this is not totally possible if the error is because of another service in the stack, but an owning service should always shoot for "0" Error logs.
Warning logs should also take the same approach I mentioned for Error, in that we should look to have none in an optimal world, but should also shoot to keep them from happening. These are just a more "graceful" error, in that they may not prevent the service/app from functioning completely, but some behaviors may not work as intended.
Log Statements
Using the Fluent API for SLF4J is not really necessary in most scenarios. The 2 common that would qualify:
-
Determining the log message content requires some sort of logic execution (i.e. method call)
-
The log level is customized based on some logic: ErrorLogger (clone URI:
https://coderepo.mobilehealth.va.gov/scm/dhsss/mobile-framework.git;ErrorLogger.javais in themobile-libraries/mobile-core-webmodule on theRelease/2.5branch)
Here are some simple examples of "good", "unnecessary", and "bad" in regards to log statements with custom messages:
Good:
log.debug("My message");
// --------
log.debug("My message: {}", text);
// --------
SomeObject obj;
log.atDebug().log(() -> "My message: %s".formatted(obj.getText()));
Unnecessary:
log.atDebug().log("My message")
// --------
log.atDebug().log("My message: {}", text);
// --------
String text;
log.atDebug().log(() -> "My message: %s".formatted(text));
Bad:
SomeObject obj;
log.debug("My message: {}", obj.getText());