Logs Handling API

This API is inspired by Java Logging API (JUL). If you are familiar with java.util.logging.* you will see familiar analogies with some of its components.

AsciidoctorJ (v1.5.7+) offers the possibility to capture messages generated during document rendering. While the API described here explains how to forward these messages to any receiver, AsciidoctorJ already logs all messages to the java.util.logging Logger with the name asciidoctor.

The default log level of java.util.logging is INFO. That means you might see messages for provisional messages about possible invalid xrefs which could be valid xrefs that Asciidoctor just can’t resolve.

The behavior of the java.util.logging logger can be configured with a properties file. For other ways to configure this behavior please check the documentation of java.util.logging.LogManager. To restrict the logger to only log messages with severity WARNING or higher create this file:

logging.properties
handlers = java.util.logging.ConsoleHandler
.level = WARNING
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format = %3$

To use this configuration when running asciidoctorj via the CLI pass the location of the file like this:

# JAVA_OPTS="-Djava.util.logging.config.file=$PWD/logging.properties" asciidoctorj document.adoc

Logs Handling API

The easiest way to capture messages is registering a LogHandler through the Asciidoctor instance.

Registering a LogHandler
Asciidoctor asciidoctor = Asciidoctor.Factory.create();

asciidoctor.registerLogHandler(new LogHandler() { (1)
    @Override
    public void log(LogRecord logRecord) {
        System.out.println(logRecord.getMessage());
    }
});
1 Use registerLogHandler to register one or more handlers.

The log method in the org.asciidoctor.log.LogHandler interface provides a org.asciidoctor.log.LogRecord that exposes the following information:

Severity severity

Severity level of the current record. A log record always has one of the 6 severity levels:

  1. DEBUG

  2. INFO

  3. WARN

  4. ERROR

  5. FATAL

  6. UNKNOWN

Cursor cursor

Information about the location of the event, contains:

  • LineNumber: relative to the file where the message occurred.

  • Path: source file simple name, or <stdin> value when converting from a String.

  • Dir: absolute path to the source file parent directory, or the execution path when converting from a String.

  • File: absolute path to the source file, or null when converting from a String.
    These will point to the correct source file, even when this is included from another.

String message

Descriptive message about the event.

String sourceFileName

Contains the value <script>.
For the source filename see Cursor above.

String sourceMethodName

The Asciidoctor Ruby engine method used to convert the file; convertFile or convert whether you are converting a File or a String.

Logs Handling SPI

Similarly to AsciidoctorJ extensions, the Log Handling API provides an alternate method to register Handlers without accessing Asciidoctor instance.

Start creating a normal LogHandler implementation.

package my.asciidoctor.log.MemoryLogHandler;

import java.util.ArrayList;
import java.util.List;
import org.asciidoctor.log.LogHandler;
import org.asciidoctor.log.LogRecord;

/**
 * Stores LogRecords in memory for later analysis.
 */
public class MemoryLogHandler implements LogHandler {

  private List<LogRecord> logRecords = new ArrayList<>();

  @Override
  public void log(LogRecord logRecord) {
    logRecords.add(record);
  }

  public List<LogRecord> getLogRecords() {
    return logRecords;
  }
}

Next, create a file called org.asciidoctor.log.LogHandler inside META-INF/services with the implementation’s full qualified name.

META-INF/services/org.asciidoctor.log.LogHandler
my.asciidoctor.log.MemoryLogHandler

And that’s all. Now when a .jar file containing the previous structure is dropped inside classpath of AsciidoctorJ, the handler will be registered automatically.