Send asciidoctor log entries as notifications and forward these to JUL
MODIFY
.gitignore
.gitignore
@@ -8,3 +8,9 @@ target/
*.ipr
*.iws
.idea/
+*/out/production/
+*/out/test/
+*/.asciidoctor
+
+
+

MODIFY
asciidoctorj-core/src/main/java/org/asciidoctor/Asciidoctor.java
asciidoctorj-core/src/main/java/org/asciidoctor/Asciidoctor.java
@@ -17,6 +17,7 @@ import org.asciidoctor.extension.ExtensionGroup;
import org.asciidoctor.extension.JavaExtensionRegistry;
import org.asciidoctor.extension.RubyExtensionRegistry;
import org.asciidoctor.internal.JRubyAsciidoctor;
+import org.asciidoctor.log.LogHandler;
/**
*
@@ -749,5 +750,8 @@ public interface Asciidoctor {
*/
Document loadFile(File file, Map<String, Object> options);
+ void registerLogHandler(LogHandler logHandler);
+
+ void unregisterLogHandler(LogHandler logHandler);
}

MODIFY
asciidoctorj-core/src/main/java/org/asciidoctor/internal/JRubyAsciidoctor.java
asciidoctorj-core/src/main/java/org/asciidoctor/internal/JRubyAsciidoctor.java
package org.asciidoctor.internal;
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.logging.Logger;
-
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.Attributes;
import org.asciidoctor.DirectoryWalker;
@@ -32,6 +18,10 @@ import org.asciidoctor.extension.ExtensionGroup;
import org.asciidoctor.extension.JavaExtensionRegistry;
import org.asciidoctor.extension.RubyExtensionRegistry;
import org.asciidoctor.extension.internal.ExtensionRegistryExecutor;
+import org.asciidoctor.log.LogHandler;
+import org.asciidoctor.log.LogRecord;
+import org.asciidoctor.log.internal.JULLogHandler;
+import org.asciidoctor.log.internal.JavaLogger;
import org.jruby.CompatVersion;
import org.jruby.Ruby;
import org.jruby.RubyHash;
@@ -41,7 +31,22 @@ import org.jruby.embed.ScriptingContainer;
import org.jruby.exceptions.RaiseException;
import org.jruby.javasupport.JavaEmbedUtils;
-public class JRubyAsciidoctor implements Asciidoctor {
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class JRubyAsciidoctor implements Asciidoctor, LogHandler {
private static final Logger logger = Logger.getLogger(JRubyAsciidoctor.class.getName());
@@ -53,11 +58,16 @@ public class JRubyAsciidoctor implements Asciidoctor {
protected RubyGemsPreloader rubyGemsPreloader;
protected Ruby rubyRuntime;
+ private List<LogHandler> logHandlers = new ArrayList<>();
+
+ private final static Logger LOGGER = Logger.getLogger("asciidoctorj");
+
private JRubyAsciidoctor(AsciidoctorModule asciidoctorModule, Ruby rubyRuntime) {
super();
this.asciidoctorModule = asciidoctorModule;
this.rubyRuntime = rubyRuntime;
this.rubyGemsPreloader = new RubyGemsPreloader(this.rubyRuntime);
+ this.logHandlers.add(new JULLogHandler());
}
public static Asciidoctor create() {
@@ -118,6 +128,8 @@ public class JRubyAsciidoctor implements Asciidoctor {
AsciidoctorModule asciidoctorModule = jRubyAsciidoctorModuleFactory.createAsciidoctorModule();
JRubyAsciidoctor jRubyAsciidoctor = new JRubyAsciidoctor(asciidoctorModule, rubyRuntime);
+ JavaLogger.install(rubyRuntime, jRubyAsciidoctor);
+
return jRubyAsciidoctor;
}
@@ -126,7 +138,7 @@ public class JRubyAsciidoctor implements Asciidoctor {
RubyInstanceConfig config = createOptimizedConfiguration();
injectEnvironmentVariables(config, environmentVars);
- Ruby rubyRuntime = JavaEmbedUtils.initialize(Collections.EMPTY_LIST, config);
+ Ruby rubyRuntime = JavaEmbedUtils.initialize(Collections.<String>emptyList(), config);
JRubyRuntimeContext.set(rubyRuntime);
@@ -134,7 +146,10 @@ public class JRubyAsciidoctor implements Asciidoctor {
AsciidoctorModule asciidoctorModule = jRubyAsciidoctorModuleFactory.createAsciidoctorModule();
+
JRubyAsciidoctor jRubyAsciidoctor = new JRubyAsciidoctor(asciidoctorModule, rubyRuntime);
+
+ JavaLogger.install(rubyRuntime, jRubyAsciidoctor);
return jRubyAsciidoctor;
}
@@ -155,6 +170,8 @@ public class JRubyAsciidoctor implements Asciidoctor {
AsciidoctorModule asciidoctorModule = jRubyAsciidoctorModuleFactory.createAsciidoctorModule();
JRubyAsciidoctor jRubyAsciidoctor = new JRubyAsciidoctor(asciidoctorModule, rubyRuntime);
+ JavaLogger.install(rubyRuntime, jRubyAsciidoctor);
+
return jRubyAsciidoctor;
}
@@ -603,6 +620,18 @@ public class JRubyAsciidoctor implements Asciidoctor {
return new Document(this.asciidoctorModule.load_file(file.getAbsolutePath(), rubyHash), this.rubyRuntime);
}
+ @Override
+ public void registerLogHandler(final LogHandler logHandler) {
+ if (!this.logHandlers.contains(logHandler)) {
+ this.logHandlers.add(logHandler);
+ }
+ }
+
+ @Override
+ public void unregisterLogHandler(final LogHandler logHandler) {
+ this.logHandlers.remove(logHandler);
+ }
+
Ruby getRubyRuntime() {
return this.rubyRuntime;
}
@@ -620,4 +649,15 @@ public class JRubyAsciidoctor implements Asciidoctor {
public ExtensionGroup createGroup(String groupName) {
return new ExtensionGroupImpl(groupName, this);
}
+
+ @Override
+ public void log(LogRecord logRecord) {
+ for (LogHandler logHandler: logHandlers) {
+ try {
+ logHandler.log(logRecord);
+ } catch (Exception e) {
+ LOGGER.log(Level.WARNING, "Unexpected exception while logging Asciidoctor log entry", e);
+ }
+ }
+ }
}

MODIFY
asciidoctorj-core/src/main/java/org/asciidoctor/internal/JRubyAsciidoctorModuleFactory.java
asciidoctorj-core/src/main/java/org/asciidoctor/internal/JRubyAsciidoctorModuleFactory.java
@@ -22,8 +22,6 @@ class JRubyAsciidoctorModuleFactory {
String script = loadAsciidoctorRubyClass();
evaler.eval(runtime, script);
- JavaLogger.install(runtime);
-
Object rfj = evaler.eval(runtime, "AsciidoctorModule.new()");
return RubyUtils.rubyToJava(runtime, (org.jruby.runtime.builtin.IRubyObject) rfj, AsciidoctorModule.class);

ADD
asciidoctorj-core/src/main/java/org/asciidoctor/log/LogHandler.java
+package org.asciidoctor.log;
+
+import org.asciidoctor.ast.Cursor;
+
+public interface LogHandler {
+
+ void log(LogRecord logRecord);
+}

ADD
asciidoctorj-core/src/main/java/org/asciidoctor/log/LogRecord.java
+package org.asciidoctor.log;
+
+import org.asciidoctor.ast.Cursor;
+
+public class LogRecord {
+
+ private final Severity severity;
+
+ private final Cursor cursor;
+
+ private final String message;
+
+ private final String sourceFileName;
+
+ private final String sourceMethodName;
+
+ public LogRecord(Severity severity, Cursor cursor, String message, String sourceFileName, String sourceMethodName) {
+ this.severity = severity;
+ this.cursor = cursor;
+ this.message = message;
+ this.sourceFileName = sourceFileName;
+ this.sourceMethodName = sourceMethodName;
+ }
+
+ public Severity getSeverity() {
+ return severity;
+ }
+
+ public Cursor getCursor() {
+ return cursor;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String getSourceFileName() {
+ return sourceFileName;
+ }
+
+ public String getSourceMethodName() {
+ return sourceMethodName;
+ }
+}

ADD
asciidoctorj-core/src/main/java/org/asciidoctor/log/Severity.java
+package org.asciidoctor.log;
+
+public enum Severity {
+ DEBUG(0),
+ INFO(1),
+ WARN(2),
+ ERROR(3),
+ FATAL(4),
+ UNKNOWN(5);
+
+ private int rubyId;
+
+ private Severity(final int rubyId) {
+ this.rubyId = rubyId;
+ }
+
+ public int getRubyId() {
+ return rubyId;
+ }
+}

ADD
asciidoctorj-core/src/main/java/org/asciidoctor/log/internal/JULLogHandler.java
+package org.asciidoctor.log.internal;
+
+import org.asciidoctor.log.LogHandler;
+import org.asciidoctor.log.LogRecord;
+import org.asciidoctor.log.Severity;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class JULLogHandler implements LogHandler {
+
+ private final static Logger LOGGER = Logger.getLogger("asciidoctor");
+
+ @Override
+ public void log(LogRecord logRecord) {
+ final java.util.logging.LogRecord julLogRecord =
+ new java.util.logging.LogRecord(
+ mapSeverity(logRecord.getSeverity()),
+ logRecord.getCursor() != null ? logRecord.getCursor().toString() + ": " + logRecord.getMessage() : logRecord.getMessage());
+
+ julLogRecord.setSourceClassName(logRecord.getSourceFileName());
+ julLogRecord.setSourceMethodName(logRecord.getSourceMethodName());
+
+ LOGGER.log(julLogRecord);
+ }
+
+ private static Level mapSeverity(Severity severity) {
+ switch (severity) {
+ case DEBUG:
+ return Level.FINEST;
+ case INFO:
+ return Level.INFO;
+ case WARN:
+ return Level.WARNING;
+ case ERROR:
+ return Level.SEVERE;
+ case FATAL:
+ return Level.SEVERE;
+ case UNKNOWN:
+ default:
+ return Level.INFO;
+ }
+ }
+
+}

RENAME
asciidoctorj-core/src/main/java/org/asciidoctor/internal/JavaLogger.java
asciidoctorj-core/src/main/java/org/asciidoctor/log/internal/JavaLogger.java
-package org.asciidoctor.internal;
+package org.asciidoctor.log.internal;
+import org.asciidoctor.log.LogHandler;
import org.asciidoctor.ast.Cursor;
import org.asciidoctor.ast.impl.CursorImpl;
+import org.asciidoctor.log.LogRecord;
+import org.asciidoctor.log.Severity;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyHash;
@@ -16,24 +19,15 @@ import org.jruby.runtime.backtrace.BacktraceElement;
import org.jruby.runtime.builtin.IRubyObject;
import java.util.Objects;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.Logger;
public class JavaLogger extends RubyObject {
-
- private static final int DEBUG = 0;
- private static final int INFO = 1;
- private static final int WARN = 2;
- private static final int ERROR = 3;
- private static final int FATAL = 4;
- private static final int UNKNOWN = 5;
+ private final LogHandler rootLogHandler;
private static final String LOG_PROPERTY_SOURCE_LOCATION = "source_location";
private static final String LOG_PROPERTY_TEXT = "text";
- static void install(final Ruby runtime) {
+ public static void install(final Ruby runtime, final LogHandler logHandler) {
final RubyModule asciidoctorModule = runtime.getModule("Asciidoctor");
final RubyModule loggerManager = asciidoctorModule.defineOrGetModuleUnder("LoggerManager");
@@ -44,7 +38,7 @@ public class JavaLogger extends RubyObject {
.defineClassUnder("JavaLogger", loggerBaseClass, new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
- return new JavaLogger(runtime, klazz);
+ return new JavaLogger(runtime, klazz, logHandler);
}
});
@@ -56,8 +50,9 @@ public class JavaLogger extends RubyObject {
}
- private JavaLogger(final Ruby runtime, final RubyClass metaClass) {
+ private JavaLogger(final Ruby runtime, final RubyClass metaClass, final LogHandler rootLogHandler) {
super(runtime, metaClass);
+ this.rootLogHandler = rootLogHandler;
}
@JRubyMethod(name = "initialize", required = 1, optional = 2)
@@ -84,68 +79,46 @@ public class JavaLogger extends RubyObject {
progname = args[2].asJavaString();
} else if (block.isGiven()) {
rubyMessage = block.yield(threadContext, getRuntime().getNil());
- progname = this.getInstanceVariable("@progname").asJavaString();
} else {
rubyMessage = args[2];
- progname = this.getInstanceVariable("@progname").asJavaString();
}
final Cursor cursor = getSourceLocation(rubyMessage);
- final String message = formatMessage(cursor, rubyMessage);
- final Level javaLogLevel = mapRubyLogLevel(args[0]);
+ final String message = formatMessage(rubyMessage);
+ final Severity severity = mapRubyLogLevel(args[0]);
- final LogRecord record = createLogRecord(threadContext, javaLogLevel, cursor, message);
+ final LogRecord record = createLogRecord(threadContext, severity, cursor, message);
- Logger logger = Logger.getLogger(progname);
- logger.log(record);
+ rootLogHandler.log(record);
return getRuntime().getNil();
}
private LogRecord createLogRecord(final ThreadContext threadContext,
- final Level logLevel,
+ final Severity severity,
final Cursor cursor,
final String message) {
- final LogRecord record = new LogRecord(logLevel, message);
BacktraceElement[] backtrace = threadContext.getBacktrace();
- record.setSourceClassName(backtrace[2].getFilename());
- record.setSourceMethodName(backtrace[2].getMethod());
- record.setParameters(new Object[] { cursor });
+ final String sourceFileName = backtrace[2].getFilename();
+ final String sourceMethodName = backtrace[2].getMethod();
+ final LogRecord record = new LogRecord(severity, cursor, message, sourceFileName, sourceMethodName);
return record;
}
- private Level mapRubyLogLevel(IRubyObject arg) {
- final Level javaLevel;
- final int level = arg.convertToInteger().getIntValue();
- switch (level) {
- case DEBUG:
- javaLevel = Level.FINEST;
- break;
- case INFO:
- javaLevel = Level.INFO;
- break;
- case WARN:
- javaLevel = Level.WARNING;
- break;
- case ERROR:
- javaLevel = Level.SEVERE;
- break;
- case FATAL:
- javaLevel = Level.SEVERE;
- break;
- case UNKNOWN:
- default:
- javaLevel = Level.INFO;
- break;
+ private Severity mapRubyLogLevel(IRubyObject arg) {
+ final int rubyId = arg.convertToInteger().getIntValue();
+ for (Severity severity: Severity.values()) {
+ if (severity.getRubyId() == rubyId) {
+ return severity;
+ }
}
- return javaLevel;
+ return Severity.UNKNOWN;
}
- private String formatMessage(final Cursor cursor, final IRubyObject msg) {
+ private String formatMessage(final IRubyObject msg) {
if (getRuntime().getString().equals(msg.getType())) {
return msg.asJavaString();
} else if (getRuntime().getHash().equals(msg.getType())) {
final RubyHash hash = (RubyHash) msg;
- final String text = Objects.toString(hash.get(getRuntime().newSymbol(LOG_PROPERTY_TEXT)));
- return cursor != null ? cursor.toString() + ": " + text : text;
+ return Objects.toString(hash.get(getRuntime().newSymbol(LOG_PROPERTY_TEXT)));
}
throw new IllegalArgumentException(Objects.toString(msg));
}

MODIFY
asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciidoctorLogsToConsole.java
asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciidoctorLogsToConsole.java
@@ -2,21 +2,25 @@ package org.asciidoctor;
import org.asciidoctor.ast.Cursor;
import org.asciidoctor.internal.JRubyAsciidoctor;
+import org.asciidoctor.log.LogHandler;
+import org.asciidoctor.log.LogRecord;
import org.asciidoctor.util.ClasspathResources;
import org.junit.After;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import static org.asciidoctor.OptionsBuilder.options;
import static org.hamcrest.Matchers.both;
import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
@@ -29,7 +33,12 @@ public class WhenAsciidoctorLogsToConsole {
@Rule
public TemporaryFolder testFolder = new TemporaryFolder();
- private Asciidoctor asciidoctor = JRubyAsciidoctor.create();
+ private Asciidoctor asciidoctor;
+
+ @Before
+ public void before() {
+ asciidoctor = JRubyAsciidoctor.create();
+ }
@After
public void cleanup() throws IOException {
@@ -37,25 +46,25 @@ public class WhenAsciidoctorLogsToConsole {
}
@Test
- public void shouldBeRedirectToAsciidoctorJLoggerSystem() throws Exception {
+ public void shouldRedirectToJUL() throws Exception {
final MemoryLogHandler memoryLogHandler = registerMemoryLogHandler();
File inputFile = classpath.getResource("documentwithnotexistingfile.adoc");
- String renderContent = asciidoctor.renderFile(inputFile, options()
- .inPlace(true).safe(SafeMode.SERVER).asMap());
+ String renderContent = asciidoctor.renderFile(inputFile,
+ options()
+ .inPlace(true)
+ .safe(SafeMode.SERVER)
+ .attributes(
+ AttributesBuilder.attributes().allowUriRead(true))
+ .asMap());
File expectedFile = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
expectedFile.delete();
- assertEquals(1, memoryLogHandler.getLogRecords().size());
+ assertEquals(4, memoryLogHandler.getLogRecords().size());
assertThat(memoryLogHandler.getLogRecords().get(0).getMessage(),
both(containsString("include file not found"))
.and(containsString("documentwithnotexistingfile.adoc: line 3")));
- assertThat(memoryLogHandler.getLogRecords().get(0).getParameters()[0], instanceOf(Cursor.class));
- final Cursor cursor = (Cursor) memoryLogHandler.getLogRecords().get(0).getParameters()[0];
- assertThat(cursor.getDir(), is(inputFile.getParent()));
- assertThat(cursor.getFile(), is(inputFile.getName()));
- assertThat(cursor.getLineNumber(), is(3));
}
private MemoryLogHandler registerMemoryLogHandler() {
@@ -65,4 +74,133 @@ public class WhenAsciidoctorLogsToConsole {
return handler;
}
+ @Test
+ public void shouldNotifyLogHandler() throws Exception {
+
+ final List<LogRecord> logRecords = new ArrayList<>();
+
+
+ final LogHandler logHandler = new LogHandler() {
+ @Override
+ public void log(LogRecord logRecord) {
+ logRecords.add(logRecord);
+ }
+ };
+ asciidoctor.registerLogHandler(logHandler);
+
+ File inputFile = classpath.getResource("documentwithnotexistingfile.adoc");
+ String renderContent = asciidoctor.renderFile(inputFile,
+ options()
+ .inPlace(true)
+ .safe(SafeMode.SERVER)
+ .attributes(
+ AttributesBuilder.attributes().allowUriRead(true))
+ .asMap());
+
+ File expectedFile = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
+ expectedFile.delete();
+
+ assertEquals(4, logRecords.size());
+ assertThat(logRecords.get(0).getMessage(), containsString("include file not found"));
+ final Cursor cursor = (Cursor) logRecords.get(0).getCursor();
+ assertThat(cursor.getDir().replace('\\', '/'), is(inputFile.getParent().replace('\\', '/')));
+ assertThat(cursor.getFile(), is(inputFile.getName()));
+ assertThat(cursor.getLineNumber(), is(3));
+ }
+
+ @Test
+ public void shouldOnlyNotifyFromRegisteredAsciidoctor() throws Exception {
+
+ final List<LogRecord> logRecords = new ArrayList<>();
+
+ final Asciidoctor secondInstance = Asciidoctor.Factory.create();
+
+ final LogHandler logHandler = new LogHandler() {
+ @Override
+ public void log(LogRecord logRecord) {
+ logRecords.add(logRecord);
+ }
+ };
+ // Register at first instance!
+ asciidoctor.registerLogHandler(logHandler);
+
+ // Now render via second instance and check that there is no notification
+ File inputFile = classpath.getResource("documentwithnotexistingfile.adoc");
+ String renderContent1 = secondInstance.renderFile(inputFile,
+ options()
+ .inPlace(true)
+ .safe(SafeMode.SERVER)
+ .attributes(
+ AttributesBuilder.attributes().allowUriRead(true))
+ .asMap());
+
+ File expectedFile1 = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
+ expectedFile1.delete();
+
+ assertEquals(0, logRecords.size());
+
+ // Now render via first instance and check that notifications appeared.
+ String renderContent = asciidoctor.renderFile(inputFile,
+ options()
+ .inPlace(true)
+ .safe(SafeMode.SERVER)
+ .attributes(
+ AttributesBuilder.attributes().allowUriRead(true))
+ .asMap());
+
+ File expectedFile2 = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
+ expectedFile2.delete();
+
+ assertEquals(4, logRecords.size());
+ assertThat(logRecords.get(0).getMessage(), containsString("include file not found"));
+ final Cursor cursor = (Cursor) logRecords.get(0).getCursor();
+ assertThat(cursor.getDir().replace('\\', '/'), is(inputFile.getParent().replace('\\', '/')));
+ assertThat(cursor.getFile(), is(inputFile.getName()));
+ assertThat(cursor.getLineNumber(), is(3));
+ }
+
+ @Test
+ public void shouldNoLongerNotifyAfterUnregisterOnlyNotifyFromRegisteredAsciidoctor() throws Exception {
+
+ final List<LogRecord> logRecords = new ArrayList<>();
+
+ final LogHandler logHandler = new LogHandler() {
+ @Override
+ public void log(LogRecord logRecord) {
+ logRecords.add(logRecord);
+ }
+ };
+ asciidoctor.registerLogHandler(logHandler);
+
+ File inputFile = classpath.getResource("documentwithnotexistingfile.adoc");
+ String renderContent = asciidoctor.renderFile(inputFile,
+ options()
+ .inPlace(true)
+ .safe(SafeMode.SERVER)
+ .attributes(
+ AttributesBuilder.attributes().allowUriRead(true))
+ .asMap());
+
+ File expectedFile = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
+ expectedFile.delete();
+
+ assertEquals(4, logRecords.size());
+ logRecords.clear();
+
+ asciidoctor.unregisterLogHandler(logHandler);
+
+ asciidoctor.renderFile(inputFile,
+ options()
+ .inPlace(true)
+ .safe(SafeMode.SERVER)
+ .attributes(
+ AttributesBuilder.attributes().allowUriRead(true))
+ .asMap());
+
+ File expectedFile2 = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
+ expectedFile2.delete();
+ assertEquals(0, logRecords.size());
+
+ }
+
}

MODIFY
asciidoctorj-core/src/test/resources/documentwithnotexistingfile.adoc
asciidoctorj-core/src/test/resources/documentwithnotexistingfile.adoc
= My Document
include::unexistingdoc.adoc[]
+
+include::unexistingdoc.adoc[]
+
+include::https://raw.githubusercontent.com/asciidoctor/asciidoctor-maven-plugin/master/src/test/resources/src/asciidoctor/github-include.adoc[]
+
+include::unexistingdoc.adoc[]

Send asciidoctor log entries as notifications and forward these to JUL