Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Java is assumed, but conventions may also be implemented by non-Java components. 

...

Log4j 2.X is somewhat less common than Logback, but equivalent. It is generally configured by an XML document named log4j.xml. See Configuration.

Log4j 1.X

AvoidStrongly discouraged from Beijing onwards, since 1.X is EOL, and since it does not support escaping, so its output may not be machine-readable. See https://logging.apache.org/log4j/1.2/.

This affects existing OpenDaylight-based components like SDNC and APPC, since ODL releases prior to Carbon bundle bundled Log4j 1.X, and make it difficult to replace. The Common Controller SDK Project project targets ODL Carbon, so the problem should resolve in timeremaining instances of Log4j 1.X should disappear by the time of the Beijing release.

What to Log

The purpose of logging is to capture diagnostic information.

...

A Mapped Diagnostic Context (MDC) allows an arbitrary string-valued attribute to be attached to a Java thread. The MDC's value is then emitted with each log message logged by that thread. The set of MDCs associated with a log message is serialized as unordered name-value pairs (see Text Output).

...

EELF doesn't directly support MDCs, but SLF4J will receive any MDC that is set its default provider (where com.att.eelf.configuration.SLF4jWrapper is the configured EELF provider)normally logs via SLF4J, and SLF4J will receive any MDC that is set:

Code Block
languagejava
linenumberstrue
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
// ...
final EELFLogger logger = EELFManager.getInstance().getLogger(this.getClass());
MDC.put("SomeUUID", UUID.randomUUID().toString());
try {
    logger.info("This message will have a UUID-valued 'SomeUUID' MDC attached.");
    // ...
}
finally {
    MDC.clear();
}

...

Code Block
languagejava
titleEELF
linenumberstrue
//TODO

SLF4J:

final EELFLogger logger = EELFManager.getAuditLogger();
logger.auditEvent("Entering.");

SLF4J:

Code Block
languagejava
titleSLF4J
linenumberstrue
public static final 
Code Block
languagejava
titleSLF4J
linenumberstrue
public static final Marker ENTRY = MarkerFactory.getMarker("ENTRY");
// ... 
final Logger logger = LoggerFactory.getLogger(this.getClass());
logger.debug(ENTRY, "Entering.");

...

Code Block
languagejava
titleEELF
linenumberstrue
//TODOfinal EELFLogger logger = EELFManager.getMetricsLogger();
logger.metricsEvent("Exiting.");

SLF4J:

Code Block
languagejava
titleSLF4J
linenumberstrue
public static final Marker EXIT = MarkerFactory.getMarker("EXIT");
// ... 
final Logger logger = LoggerFactory.getLogger(this.getClass());
logger.debug(EXIT, "Exiting.");

...

Code Block
languagejava
titleSLF4J
linenumberstrue
public static final Marker INVOKE = MarkerFactory.getMarker("INVOKE");
// ...

// Generate and report invocation ID. 

final String invocationID = UUID.randomUUID().toString();
MDC.put(MDC_INVOCATION_ID, invocationID);
try {
    logger.debug(INVOKE_SYNCHRONOUS, "Invoking synchronously ... ");
}
finally {
    MDC.remove(MDC_INVOCATION_ID);
}

// Pass invocationID as HTTP X-InvocationID header.

callDownstreamSystem(invocationID, ... );

TODO: EELF examples of INVOCATION_ID reporting, without changing published APIs.

...

Code Block
languagejava
titleSLF4J
linenumberstrue
public static final Marker INVOKE_SYNCHRONOUS;
static {
    INVOKE_SYNCHRONOUS = MarkerFactory.getMarker("INVOKE");
    INVOKE_SYNCHRONOUS.add(MarkerFactory.getMarker("SYNCHRONOUS"));
}
// ...

// Generate and report invocation ID. 

final String invocationID = UUID.randomUUID().toString();
MDC.put(MDC_INVOCATION_ID, invocationID);
try {
    logger.debug(INVOKE_SYNCHRONOUS, "Invoking synchronously ... ");
}
finally {
    MDC.remove(MDC_INVOCATION_ID);
}

// Pass invocationID as HTTP X-InvocationID header.

callDownstreamSystem(invocationID, ... );

TODO: EELF example of SYNCHRONOUS reporting, without changing published APIs. 

...

Code Block
languagetext
linenumberstrue
/var/log/ONAP/<component>[/<subcomponent>]/*.log

For the duration of Beijing, logs  will be written to a separate directory, /var/log/ONAP_EELF:

Code Block
languagetext
linenumberstrue
/var/log/ONAP_EELF/<component>[/<subcomponent>]/*.log

Configuration

Logging providers should be configured by file. Files should be at a predictable, static location, so that they can be written by deployment automation. Ideally this should be under /etc/ONAP, but compliance is low.

...

Code Block
languagetext
linenumberstrue
/etc/onapONAP/<component>[/<subcomponent>]/<provider>.xml

...