LibJF/libjf-base/src/main/java/io/gitlab/jfronny/libjf/log/SLF4JPlatformLogger.java

119 lines
4.3 KiB
Java

package io.gitlab.jfronny.libjf.log;
import io.gitlab.jfronny.commons.StringFormatter;
import io.gitlab.jfronny.commons.logger.CompactLogger;
import io.gitlab.jfronny.commons.logger.impl.Formatter;
import org.slf4j.Logger;
import org.slf4j.spi.CallerBoundaryAware;
import org.slf4j.spi.LoggingEventBuilder;
import java.text.MessageFormat;
import java.util.Objects;
import java.util.ResourceBundle;
/**
* A {@link System.Logger} implementation that delegates to SLF4J.
* Adapted from slf4j-jdk-platform-logging for use in LibJF.
*
* @author Ceki Gülcü
* @author JFronny
*/
public class SLF4JPlatformLogger implements CompactLogger {
private static final String PRESUMED_CALLER_BOUNDARY = System.Logger.class.getName();
private final Logger slf4jLogger;
public SLF4JPlatformLogger(Logger logger) {
slf4jLogger = Objects.requireNonNull(logger);
}
@Override
public String getName() {
return slf4jLogger.getName();
}
@Override
public Level getLevel() {
if (slf4jLogger.isTraceEnabled()) return Level.TRACE;
else if (slf4jLogger.isDebugEnabled()) return Level.DEBUG;
else if (slf4jLogger.isInfoEnabled()) return Level.INFO;
else if (slf4jLogger.isWarnEnabled()) return Level.WARNING;
else if (slf4jLogger.isErrorEnabled()) return Level.ERROR;
else return Level.INFO; // should not happen, but if it does, INFO is a reasonable default
}
@Override
public boolean isLoggable(Level level) {
if (level == Level.ALL) return true;
if (level == Level.OFF) return false;
return slf4jLogger.isEnabledForLevel(jplLevelToSLF4JLevel(level));
}
private org.slf4j.event.Level jplLevelToSLF4JLevel(Level jplLevel) {
return switch (jplLevel) {
case TRACE -> org.slf4j.event.Level.TRACE;
case DEBUG -> org.slf4j.event.Level.DEBUG;
case INFO -> org.slf4j.event.Level.INFO;
case WARNING -> org.slf4j.event.Level.WARN;
case ERROR -> org.slf4j.event.Level.ERROR;
// should not happen, but if it does, INFO is a reasonable default
default -> org.slf4j.event.Level.INFO;
};
}
@Override
public void log(Level level, String message) {
log(level, null, message, null, null);
}
@Override
public void log(Level level, String message, Throwable throwable) {
log(level, null, message, throwable, null);
}
@Override
public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
log(level, bundle, msg, thrown, null);
}
@Override
public void log(Level level, ResourceBundle bundle, String format, Object[] params) {
log(level, bundle, format, null, params);
}
@Override
public void log(Level jplLevel, ResourceBundle bundle, String msg, Throwable thrown, Object[] params) {
if (jplLevel == Level.OFF) return;
if (jplLevel == Level.ALL) {
performLog(org.slf4j.event.Level.TRACE, bundle, msg, thrown, params);
return;
}
org.slf4j.event.Level slf4jLevel = jplLevelToSLF4JLevel(jplLevel);
if (slf4jLogger.isEnabledForLevel(slf4jLevel)) {
performLog(slf4jLevel, bundle, msg, thrown, params);
}
}
private void performLog(org.slf4j.event.Level slf4jLevel, ResourceBundle bundle, String msg, Throwable thrown, Object[] params) {
String message = Formatter.getResourceStringOrMessage(bundle, msg);
LoggingEventBuilder leb = slf4jLogger.makeLoggingEventBuilder(slf4jLevel);
if (thrown != null) {
leb = leb.setCause(thrown);
}
if (params != null && params.length > 0) {
// add the arguments to the logging event for possible processing by the backend
String[] strings = new String[params.length];
for (int i = 0; i < params.length; i++) {
leb = leb.addArgument(params[i]);
strings[i] = StringFormatter.toString(params[i]);
}
// The JDK uses a different formatting convention. We must invoke it now.
message = new MessageFormat(message).format(strings);
}
if (leb instanceof CallerBoundaryAware cba) {
cba.setCallerBoundary(PRESUMED_CALLER_BOUNDARY);
}
leb.log(message);
}
}