Skip to content

Commit

Permalink
+ fixed caller threshold output level handling
Browse files Browse the repository at this point in the history
  • Loading branch information
q3769 committed Oct 29, 2023
1 parent c2981d1 commit 0046e27
Show file tree
Hide file tree
Showing 11 changed files with 50 additions and 45 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

<groupId>io.github.elf4j</groupId>
<artifactId>elf4j-engine</artifactId>
<version>13.0.11</version>
<version>13.0.12</version>
<packaging>jar</packaging>
<name>elf4j-engine</name>
<description>A stand-alone Java log engine implementing the ELF4J (Easy Logging Facade for Java) API</description>
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/elf4j/engine/NativeLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@
import elf4j.Level;
import elf4j.Logger;
import elf4j.engine.service.LogService;
import lombok.NonNull;
import javax.annotation.concurrent.ThreadSafe;
import lombok.EqualsAndHashCode;
import lombok.NonNull;

/**
* Any instance of this class is thread-safe; it can be safely used as static, instance, or local variables. However,
Expand All @@ -38,6 +39,7 @@
* of variables.
*/
@ThreadSafe
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class NativeLogger implements Logger {
/**
* Name of this logger's declaring class - the logging service client class that first requested this logger
Expand All @@ -53,6 +55,7 @@ public class NativeLogger implements Logger {
* requires only the caller class name, this field will be used in liu of checking the stack trace; i.e. the stack
* trace walking is needed only when more caller details (e.g. method name, file name, line number) are required.
*/
@EqualsAndHashCode.Include
private final @NonNull String declaringClassName;

private final @NonNull Level level;
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/elf4j/engine/service/EventingLogService.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import elf4j.Level;
import elf4j.engine.NativeLogger;
import elf4j.engine.service.configuration.LogServiceConfiguration;
import elf4j.engine.service.configuration.OverridingCallerLevels;
import elf4j.engine.service.configuration.LoggerOutputLevelThreshold;
import elf4j.engine.service.util.StackTraceUtils;
import elf4j.engine.service.writer.ConseqWriterGroup;
import elf4j.engine.service.writer.LogWriter;
Expand All @@ -42,19 +42,19 @@
public class EventingLogService implements LogService {
private final boolean noop;
private final LogWriter logWriter;
private final OverridingCallerLevels overridingCallerLevels;
private final LoggerOutputLevelThreshold loggerOutputLevelThreshold;
private final Map<NativeLogger, Boolean> loggerEnabled = new ConcurrentHashMap<>();

public EventingLogService(@NonNull LogServiceConfiguration logServiceConfiguration) {
if (logServiceConfiguration.isAbsent() || logServiceConfiguration.isTrue("noop")) {
noop = true;
logWriter = null;
overridingCallerLevels = null;
loggerOutputLevelThreshold = null;
return;
}
noop = false;
logWriter = ConseqWriterGroup.from(logServiceConfiguration);
overridingCallerLevels = OverridingCallerLevels.from(logServiceConfiguration);
loggerOutputLevelThreshold = LoggerOutputLevelThreshold.from(logServiceConfiguration);
}

@Override
Expand All @@ -67,10 +67,10 @@ public boolean isEnabled(NativeLogger nativeLogger) {
if (noop) {
return false;
}
return loggerEnabled.computeIfAbsent(nativeLogger, k -> {
Level level = k.getLevel();
return level.compareTo(overridingCallerLevels.getMinimumOutputLevel(k)) >= 0
&& level.compareTo(logWriter.getMinimumOutputLevel()) >= 0;
return loggerEnabled.computeIfAbsent(nativeLogger, logger -> {
Level level = logger.getLevel();
return level.compareTo(loggerOutputLevelThreshold.getThresholdOutputLevel(logger)) >= 0
&& level.compareTo(logWriter.getThresholdOutputLevel()) >= 0;
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/elf4j/engine/service/LogService.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
public interface LogService extends PerformanceSensitive {
/**
* @param nativeLogger to check for enablement
* @return true if the logger's level is at or above configured minimum
* @return true if the logger's level is at or above configured threshold
*/
boolean isEnabled(NativeLogger nativeLogger);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@
*
*/
@ToString
public class OverridingCallerLevels {
private static final String DEFAULT_OVERRIDING_CALLER_CLASS_NAME_SPACE = "";
public class LoggerOutputLevelThreshold {
private static final String CONFIGURED_ROOT_LOGGER_NAME_SPACE = "";
private static final Level DEFAULT_THRESHOLD_OUTPUT_LEVEL = Level.TRACE;
private final Map<String, Level> configuredLevels;
private final List<String> sortedCallerClassNameSpaces;

private OverridingCallerLevels(@NonNull Map<String, Level> configuredLevels) {
private LoggerOutputLevelThreshold(@NonNull Map<String, Level> configuredLevels) {
this.configuredLevels = new ConcurrentHashMap<>(configuredLevels);
this.sortedCallerClassNameSpaces = configuredLevels.keySet().stream()
.sorted(new ByClassNameSpace())
Expand All @@ -52,19 +53,19 @@ private OverridingCallerLevels(@NonNull Map<String, Level> configuredLevels) {
}

/**
* @param logServiceConfiguration configuration source of all minimum output levels for caller classes
* @param logServiceConfiguration configuration source of all threshold output levels for caller classes
* @return the overriding caller levels
*/
public static @NonNull OverridingCallerLevels from(@NonNull LogServiceConfiguration logServiceConfiguration) {
public static @NonNull LoggerOutputLevelThreshold from(@NonNull LogServiceConfiguration logServiceConfiguration) {
Map<String, Level> configuredLevels = new HashMap<>();
Properties properties = logServiceConfiguration.getProperties();
getAsLevel("level", properties)
.ifPresent(level -> configuredLevels.put(DEFAULT_OVERRIDING_CALLER_CLASS_NAME_SPACE, level));
.ifPresent(level -> configuredLevels.put(CONFIGURED_ROOT_LOGGER_NAME_SPACE, level));
configuredLevels.putAll(properties.stringPropertyNames().stream()
.filter(name -> name.trim().startsWith("level@"))
.collect(Collectors.toMap(name -> name.split("@", 2)[1].trim(), name -> getAsLevel(name, properties)
.orElseThrow(NoSuchElementException::new))));
return new OverridingCallerLevels(configuredLevels);
return new LoggerOutputLevelThreshold(configuredLevels);
}

private static Optional<Level> getAsLevel(String levelKey, @NonNull Properties properties) {
Expand All @@ -77,16 +78,16 @@ private static Optional<Level> getAsLevel(String levelKey, @NonNull Properties p
/**
* Assuming the declaring and caller class of the specified logger is the same
*
* @param nativeLogger to search for configured minimum output level
* @return If overriding level is configured for the nativeLogger's caller class, return the overriding min level.
* Otherwise, if no overriding level configured, return the nativeLogger's level.
* @param nativeLogger to search for configured threshold output level
* @return If the threshold level is configured for the nativeLogger's caller class, return the configured level.
* Otherwise, if no threshold level configured, return the default threshold level.
*/
public Level getMinimumOutputLevel(@NonNull NativeLogger nativeLogger) {
public Level getThresholdOutputLevel(@NonNull NativeLogger nativeLogger) {
return this.sortedCallerClassNameSpaces.stream()
.filter(sortedNameSpace -> nativeLogger.getDeclaringClassName().startsWith(sortedNameSpace))
.findFirst()
.map(this.configuredLevels::get)
.orElse(nativeLogger.getLevel());
.orElse(DEFAULT_THRESHOLD_OUTPUT_LEVEL);
}

static class ByClassNameSpace implements Comparator<String> {
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/elf4j/engine/service/writer/ConseqWriterGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class ConseqWriterGroup implements LogWriter, LogServiceManager.Stoppable
private static final int DEFAULT_CONSEQ_CONCURRENCY = Runtime.getRuntime().availableProcessors();
private final List<LogWriter> writers;
private final ConseqExecutor conseqExecutor;
private Level minimumLevel;
private Level thresholdOutputLevel;

@ToString.Exclude
private Boolean includeCallerDetail;
Expand Down Expand Up @@ -113,15 +113,15 @@ private static List<LogWriterType> getLogWriterTypes(@NonNull LogServiceConfigur
}

@Override
public Level getMinimumOutputLevel() {
if (minimumLevel == null) {
minimumLevel = Level.values()[
public Level getThresholdOutputLevel() {
if (thresholdOutputLevel == null) {
thresholdOutputLevel = Level.values()[
writers.stream()
.mapToInt(writer -> writer.getMinimumOutputLevel().ordinal())
.mapToInt(writer -> writer.getThresholdOutputLevel().ordinal())
.min()
.orElseThrow(NoSuchElementException::new)];
}
return minimumLevel;
return thresholdOutputLevel;
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/elf4j/engine/service/writer/LogWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
@ThreadSafe
public interface LogWriter extends PerformanceSensitive {
/**
* @return the minimum output level of this writer
* @return the threshold output level of this writer
*/
Level getMinimumOutputLevel();
Level getThresholdOutputLevel();

/**
* @param logEvent the log data entry to write out
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,23 @@
@Builder
@ToString
public class StandardStreamWriter implements LogWriter {
private static final String DEFAULT_MINIMUM_LEVEL = "trace";
private static final String DEFAULT_THRESHOLD_OUTPUT_LEVEL = "trace";
private static final String DEFAULT_PATTERN = "{timestamp} {level} {class} - {message}";
private static final OutStreamType DEFAULT_OUT_STREAM_TYPE = OutStreamType.STDOUT;
private static final String LINE_FEED = System.lineSeparator();
private final StandardOutput standardOutput = new FileStreamStandardOutput();
private final Level minimumLevel;
private final Level thresholdOutputLevel;
private final PatternElement logPattern;
private final OutStreamType outStreamType;

@Override
public Level getMinimumOutputLevel() {
return minimumLevel;
public Level getThresholdOutputLevel() {
return thresholdOutputLevel;
}

@Override
public void write(@NonNull LogEvent logEvent) {
if (logEvent.getNativeLogger().getLevel().compareTo(this.minimumLevel) < 0) {
if (logEvent.getNativeLogger().getLevel().compareTo(this.thresholdOutputLevel) < 0) {
return;
}
StringBuilder target = new StringBuilder();
Expand Down Expand Up @@ -141,8 +141,8 @@ static class Type implements LogWriterType {
private static StandardStreamWriter getDefaultWriter(@NonNull LogServiceConfiguration logServiceConfiguration) {
Properties properties = logServiceConfiguration.getProperties();
return StandardStreamWriter.builder()
.minimumLevel(Level.valueOf(properties
.getProperty("level", DEFAULT_MINIMUM_LEVEL)
.thresholdOutputLevel(Level.valueOf(properties
.getProperty("level", DEFAULT_THRESHOLD_OUTPUT_LEVEL)
.trim()
.toUpperCase()))
.logPattern(LogPattern.from(properties.getProperty("pattern", DEFAULT_PATTERN)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ void callWriter() {
LogWriter mockLogWriter = mock(LogWriter.class);
ReflectionTestUtils.setField(logService, "logWriter", mockLogWriter);
NativeLogger stubLogger = mock(NativeLogger.class);
given(mockLogWriter.getMinimumOutputLevel()).willReturn(Level.INFO);
given(mockLogWriter.getThresholdOutputLevel()).willReturn(Level.INFO);
given(stubLogger.getLevel()).willReturn(Level.INFO);

logService.log(stubLogger, this.getClass(), null, null, null);
Expand All @@ -89,7 +89,7 @@ void whenCallerDetailRequired() {
ReflectionTestUtils.setField(sut, "logWriter", logWriter);
given(logWriter.includeCallerDetail()).willReturn(true);
given(nativeLogger.getLevel()).willReturn(Level.INFO);
given(logWriter.getMinimumOutputLevel()).willReturn(Level.INFO);
given(logWriter.getThresholdOutputLevel()).willReturn(Level.INFO);
ArgumentCaptor<LogEvent> logEvent = ArgumentCaptor.forClass(LogEvent.class);

sut.log(nativeLogger, this.getClass(), null, null, null);
Expand All @@ -113,7 +113,7 @@ void whenCallerDetailNotRequired() {
ReflectionTestUtils.setField(sut, "logWriter", logWriter);
given(logWriter.includeCallerDetail()).willReturn(false);
given(nativeLogger.getLevel()).willReturn(Level.INFO);
given(logWriter.getMinimumOutputLevel()).willReturn(Level.INFO);
given(logWriter.getThresholdOutputLevel()).willReturn(Level.INFO);
ArgumentCaptor<LogEvent> logEvent = ArgumentCaptor.forClass(LogEvent.class);

sut.log(nativeLogger, this.getClass(), null, null, null);
Expand All @@ -138,7 +138,7 @@ void onlyLogWhenEnabled() {
Level loggerLevel = Level.TRACE;
given(nativeLogger.getLevel()).willReturn(loggerLevel);
Level writerLevel = Level.INFO;
given(logWriter.getMinimumOutputLevel()).willReturn(writerLevel);
given(logWriter.getThresholdOutputLevel()).willReturn(writerLevel);

sut.log(nativeLogger, this.getClass(), null, null, null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
class ByClassNameSpaceTest {
@Nested
class compare {
OverridingCallerLevels.ByClassNameSpace byClassNameSpace = new OverridingCallerLevels.ByClassNameSpace();
LoggerOutputLevelThreshold.ByClassNameSpace byClassNameSpace =
new LoggerOutputLevelThreshold.ByClassNameSpace();

@Test
void whenMorePackageLevels_thenGoesFirst() {
Expand Down
4 changes: 2 additions & 2 deletions src/test/resources/elf4j-test.properties
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
#
### global no-op flag, overriding if set true
#noop=true
### This overrides the default minimum level
level=trace
### This overrides the default threshold output level
#level=info
### These override all caller classes under the specified package
level@org.springframework=warn
level@org.apache=error
Expand Down

0 comments on commit 0046e27

Please sign in to comment.