Search This Blog

Wednesday, September 22, 2021

SailPoint logging best practice

Logging Best Practices for SailPoint Implementations

Logging Best Practices for SailPoint Implementations

SailPoint recommends using log4j for all logging operations. Although some legacy code uses Apache Commons Logging, log4j is the preferred and more efficient approach. Commons Logging ultimately delegates to log4j, creating an unnecessary abstraction layer.

Recommended Logger Construction (log4j)

import org.apache.log4j.Logger;
Logger alog = Logger.getLogger("com.sailpoint.class.module");

Not Recommended (Commons Logging)

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Log alog = LogFactory.getLog("com.sailpoint.class.module");

Using Commons Logging works, but it introduces avoidable complexity. Additionally, logger objects defined outside a method cannot mix classes without causing conflicts.

Importance of Proper Logging

Logging is essential in web applications because traditional debugging tools cannot pause execution or inspect runtime variables. Effective logging provides visibility into application behavior and accelerates troubleshooting.

A common anti-pattern is using vague statements such as:

log.error("I am here");
log.error("Now I am here");

This approach is ineffective because:

  • Use of an out-of-the-box logger instance
  • Incorrect use of the error level for basic debugging
  • No indication of program location or context
  • No meaningful information in the log output

Best Practices

1. Always Create a Dedicated Logger

Never rely on the default log object. Create your own logger instance. Avoid naming it log.

2. Use Log Levels Correctly

Understanding log levels is critical:

  • TRACE — Highly verbose; use only in tight loops or deep logic analysis
  • DEBUG — Primary level for development and troubleshooting
  • INFO — Suitable for method-entry statements
  • WARN — Use for non-fatal issues that should appear in production logs
  • ERROR — Use in catch blocks or severe failures

Configure levels in log4j2.properties (or log4j.properties for older versions).

3. Use Structured Prefixes (“Tags”)

Each log entry should include a standardized prefix identifying the client, module code, and a unique number.

String fileNumber = (String) object.getAttribute("FILENUMBER");
alog.debug("ACM-WDC-001 Entered WorkDay Customization rule for user " + fileNumber);

4. Provide Meaningful Log Content

Avoid empty statements like "I am here". Include relevant data and null-check before printing. This improves SIEM analysis and accelerates root-cause identification.

Update 2026 — Avoid Logging Wrapper Methods

Some implementations introduce wrapper methods such as:

void logx(Logger xlog, String level, String message) {
  if ("debug".equals(level)) xlog.debug(message);
  else if ("info".equals(level)) xlog.info(message);
  else if ("trace".equals(level)) xlog.trace(message);
  else if ("warn".equals(level)) xlog.warn(message);
  else if ("error".equals(level)) xlog.error(message);
}

This pattern defeats log4j’s built-in level filtering. For example:

logx(xlogger, "debug", plan.toXml());

Even if the log level is set to WARN, the system still evaluates plan.toXml(), causing unnecessary overhead.

Correct Approach

if (alog.isDebugEnabled()) {
  alog.debug("ACM-WDC-100 The provisioning plan is " + plan.toXml());
}

Use isDebugEnabled() and isTraceEnabled() for DEBUG and TRACE statements that require object evaluation. These checks are generally not required for INFO, WARN, or ERROR. They are also not required when the text being printed does not need evaluation, such as printing Strings or numbers.

Logging Errors

Use WARN when the issue is important enough to appear in production logs but does not stop execution. Inside catch blocks use error. Below is a way to print the class and message for a general exception.

catch (Exception ex) {
  alog.error("ACM-WDC-901 Error evaluating expression: " + ex.getClass().getName() + ":" + ex.getMessage());
}

TLDR : Logging Best Practices

  • Always use log4j classes and methods.
  • Do not name your logger log.
  • Define loggers inside method bodies.
  • Enclose the main body of every rule in { } to ensure proper garbage collection. Anything defined outside is effectively global; use CustomGlobal for truly global objects.
  • Tag each log line with a structured prefix.
  • Use isDebugEnabled() or isTraceEnabled() for DEBUG/TRACE and never wrap log calls in custom logging methods.

No comments:

Post a Comment