Skip to content

Commit

Permalink
Fix compatibility with legacy SLF4J 1
Browse files Browse the repository at this point in the history
LoggerFactory failed to load org.slf4j.spi.LoggingEventAware.

Fixes #397
  • Loading branch information
pmwmedia committed Mar 9, 2023
1 parent c6be131 commit 6d851d9
Show file tree
Hide file tree
Showing 13 changed files with 847 additions and 234 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

import org.slf4j.ILoggerFactory;
import org.slf4j.spi.LoggerFactoryBinder;
import org.tinylog.slf4j.TinylogLoggerFactory;
import org.tinylog.slf4j.LegacyTinylogLoggerFactory;

/**
* Logger factory binder for using tinylog for logging via SLF4J.
Expand All @@ -36,7 +36,7 @@ public final class StaticLoggerBinder implements LoggerFactoryBinder {

/** */
private StaticLoggerBinder() {
factory = new TinylogLoggerFactory();
factory = new LegacyTinylogLoggerFactory();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,38 @@

package org.tinylog.slf4j;

import java.util.List;

import org.slf4j.Marker;
import org.slf4j.event.LoggingEvent;
import org.slf4j.spi.LocationAwareLogger;
import org.slf4j.spi.LoggingEventAware;
import org.tinylog.Level;
import org.tinylog.format.LegacyMessageFormatter;
import org.tinylog.format.MessageFormatter;
import org.tinylog.provider.LoggingProvider;
import org.tinylog.provider.ProviderRegistry;

/**
* Location aware logger for tinylog's {@link LoggingProvider}.
* Abstract location aware logger for tinylog's {@link LoggingProvider}.
*/
public final class TinylogLogger implements LocationAwareLogger, LoggingEventAware {
public abstract class AbstractTinylogLogger implements LocationAwareLogger {

private static final int STACKTRACE_DEPTH = 2;
protected static final int STACKTRACE_DEPTH = 2;

private static final MessageFormatter formatter = new LegacyMessageFormatter();
private static final LoggingProvider provider = ProviderRegistry.getLoggingProvider();
protected static final MessageFormatter formatter = new LegacyMessageFormatter();
protected static final LoggingProvider provider = ProviderRegistry.getLoggingProvider();

// @formatter:off
private static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_TRACE = isCoveredByGlobalMinimumLevel(Level.TRACE);
private static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_DEBUG = isCoveredByGlobalMinimumLevel(Level.DEBUG);
private static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_INFO = isCoveredByGlobalMinimumLevel(Level.INFO);
private static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_WARN = isCoveredByGlobalMinimumLevel(Level.WARN);
private static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_ERROR = isCoveredByGlobalMinimumLevel(Level.ERROR);
protected static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_TRACE = isCoveredByGlobalMinimumLevel(Level.TRACE);
protected static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_DEBUG = isCoveredByGlobalMinimumLevel(Level.DEBUG);
protected static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_INFO = isCoveredByGlobalMinimumLevel(Level.INFO);
protected static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_WARN = isCoveredByGlobalMinimumLevel(Level.WARN);
protected static final boolean MINIMUM_GLOBAL_LEVEL_COVERS_ERROR = isCoveredByGlobalMinimumLevel(Level.ERROR);
// @formatter:on

// @formatter:off
private static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_TRACE = isCoveredByDefaultMinimumLevel(Level.TRACE);
private static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_DEBUG = isCoveredByDefaultMinimumLevel(Level.DEBUG);
private static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_INFO = isCoveredByDefaultMinimumLevel(Level.INFO);
private static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_WARN = isCoveredByDefaultMinimumLevel(Level.WARN);
private static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_ERROR = isCoveredByDefaultMinimumLevel(Level.ERROR);
protected static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_TRACE = isCoveredByDefaultMinimumLevel(Level.TRACE);
protected static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_DEBUG = isCoveredByDefaultMinimumLevel(Level.DEBUG);
protected static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_INFO = isCoveredByDefaultMinimumLevel(Level.INFO);
protected static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_WARN = isCoveredByDefaultMinimumLevel(Level.WARN);
protected static final boolean MINIMUM_DEFAULT_LEVEL_COVERS_ERROR = isCoveredByDefaultMinimumLevel(Level.ERROR);
// @formatter:on

private final String name;
Expand All @@ -57,7 +53,7 @@ public final class TinylogLogger implements LocationAwareLogger, LoggingEventAwa
* @param name
* Name for logger
*/
public TinylogLogger(final String name) {
AbstractTinylogLogger(final String name) {
this.name = name;
}

Expand Down Expand Up @@ -506,23 +502,24 @@ public void log(final Marker marker, final String fqcn, final int level, final S
}
}

@Override
public void log(final LoggingEvent event) {
Level severityLevel = translateLevel(event.getLevel().toInt());
List<Marker> markers = event.getMarkers();
Marker marker = markers == null || markers.isEmpty() ? null : markers.get(0);
String tag = marker == null ? null : marker.getName();

if (provider.getMinimumLevel(tag).ordinal() <= severityLevel.ordinal()) {
provider.log(
event.getCallerBoundary(),
tag,
severityLevel,
event.getThrowable(),
formatter,
event.getMessage(),
event.getArgumentArray()
);
/**
* Translate SLF4J severity level codes.
*
* @param level
* Severity level code from SLF4J
* @return Responding severity level of tinylog
*/
protected static Level translateLevel(final int level) {
if (level <= TRACE_INT) {
return Level.TRACE;
} else if (level <= DEBUG_INT) {
return Level.DEBUG;
} else if (level <= INFO_INT) {
return Level.INFO;
} else if (level <= WARN_INT) {
return Level.WARN;
} else {
return Level.ERROR;
}
}

Expand All @@ -548,27 +545,6 @@ private static boolean isCoveredByDefaultMinimumLevel(final Level level) {
return provider.getMinimumLevel(null).ordinal() <= level.ordinal();
}

/**
* Translate SLF4J severity level codes.
*
* @param level
* Severity level code from SLF4J
* @return Responding severity level of tinylog
*/
private static Level translateLevel(final int level) {
if (level <= TRACE_INT) {
return Level.TRACE;
} else if (level <= DEBUG_INT) {
return Level.DEBUG;
} else if (level <= INFO_INT) {
return Level.INFO;
} else if (level <= WARN_INT) {
return Level.WARN;
} else {
return Level.ERROR;
}
}

/**
* Returns a throwable if the last argument is one.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2023 Martin Winandy
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package org.tinylog.slf4j;

/**
* Location aware logger for legacy SLF4J 1.
*/
public final class LegacyTinylogLogger extends AbstractTinylogLogger {

/**
* @param name
* Name for logger
*/
public LegacyTinylogLogger(final String name) {
super(name);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@
import org.slf4j.ILoggerFactory;

/**
* Logging factory implementation for providing {@link TinylogLogger} instances.
* Logging factory implementation for providing {@link LegacyTinylogLogger} instances.
*/
public final class TinylogLoggerFactory implements ILoggerFactory {
public final class LegacyTinylogLoggerFactory implements ILoggerFactory {

private final ConcurrentMap<String, TinylogLogger> loggers;
private final ConcurrentMap<String, LegacyTinylogLogger> loggers;

/** */
public TinylogLoggerFactory() {
loggers = new ConcurrentHashMap<String, TinylogLogger>();
public LegacyTinylogLoggerFactory() {
loggers = new ConcurrentHashMap<String, LegacyTinylogLogger>();
}

@Override
public TinylogLogger getLogger(final String name) {
TinylogLogger logger = loggers.get(name);
public LegacyTinylogLogger getLogger(final String name) {
LegacyTinylogLogger logger = loggers.get(name);
if (logger == null) {
TinylogLogger newLogger = new TinylogLogger(name);
TinylogLogger existingLogger = loggers.putIfAbsent(name, newLogger);
LegacyTinylogLogger newLogger = new LegacyTinylogLogger(name);
LegacyTinylogLogger existingLogger = loggers.putIfAbsent(name, newLogger);
return existingLogger == null ? newLogger : existingLogger;
} else {
return logger;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2023 Martin Winandy
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package org.tinylog.slf4j;

import java.util.List;

import org.slf4j.Marker;
import org.slf4j.event.LoggingEvent;
import org.slf4j.spi.LoggingEventAware;
import org.tinylog.Level;

/**
* Location and event aware logger for modern SLF4J 2.
*/
public final class ModernTinylogLogger extends AbstractTinylogLogger implements LoggingEventAware {

/**
* @param name
* Name for logger
*/
public ModernTinylogLogger(final String name) {
super(name);
}

@Override
public void log(final LoggingEvent event) {
Level severityLevel = translateLevel(event.getLevel().toInt());
List<Marker> markers = event.getMarkers();
Marker marker = markers == null || markers.isEmpty() ? null : markers.get(0);
String tag = marker == null ? null : marker.getName();

if (provider.getMinimumLevel(tag).ordinal() <= severityLevel.ordinal()) {
provider.log(
event.getCallerBoundary(),
tag,
severityLevel,
event.getThrowable(),
formatter,
event.getMessage(),
event.getArgumentArray()
);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2023 Martin Winandy
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package org.tinylog.slf4j;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.slf4j.ILoggerFactory;

/**
* Logging factory implementation for providing {@link ModernTinylogLogger} instances.
*/
public final class ModernTinylogLoggerFactory implements ILoggerFactory {

private final ConcurrentMap<String, ModernTinylogLogger> loggers;

/** */
public ModernTinylogLoggerFactory() {
loggers = new ConcurrentHashMap<String, ModernTinylogLogger>();
}

@Override
public ModernTinylogLogger getLogger(final String name) {
ModernTinylogLogger logger = loggers.get(name);
if (logger == null) {
ModernTinylogLogger newLogger = new ModernTinylogLogger(name);
ModernTinylogLogger existingLogger = loggers.putIfAbsent(name, newLogger);
return existingLogger == null ? newLogger : existingLogger;
} else {
return logger;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public String getRequestedApiVersion() {

@Override
public void initialize() {
loggerFactory = new TinylogLoggerFactory();
loggerFactory = new ModernTinylogLoggerFactory();
markerFactory = new BasicMarkerFactory();
mdcAdapter = new TinylogMdcAdapter();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
package org.slf4j.impl;

import org.junit.Test;
import org.tinylog.slf4j.TinylogLoggerFactory;
import org.tinylog.slf4j.LegacyTinylogLoggerFactory;

import static org.assertj.core.api.Assertions.assertThat;

Expand All @@ -28,24 +28,27 @@ public final class StaticLoggerBinderTest {
*/
@Test
public void singleton() {
assertThat(StaticLoggerBinder.getSingleton()).isSameAs(StaticLoggerBinder.getSingleton());
assertThat(StaticLoggerBinder.getSingleton())
.isSameAs(StaticLoggerBinder.getSingleton());
}

/**
* Verifies that {@link TinylogLoggerFactory} is returned as logger factory.
* Verifies that {@link LegacyTinylogLoggerFactory} is returned as logger factory.
*/
@Test
public void instance() {
assertThat(StaticLoggerBinder.getSingleton().getLoggerFactory()).isInstanceOf(TinylogLoggerFactory.class);
assertThat(StaticLoggerBinder.getSingleton().getLoggerFactory())
.isInstanceOf(LegacyTinylogLoggerFactory.class);
}

/**
* Verifies that the fully-qualified class name of {@link TinylogLoggerFactory} is returned as logger factory class
* Verifies that the fully-qualified class name of {@link LegacyTinylogLoggerFactory} is returned as logger factory class
* name.
*/
@Test
public void className() {
assertThat(StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr()).isEqualTo(TinylogLoggerFactory.class.getName());
assertThat(StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr())
.isEqualTo(LegacyTinylogLoggerFactory.class.getName());
}

}
Loading

0 comments on commit 6d851d9

Please sign in to comment.