Skip to content

Commit

Permalink
+ elf4j version bump
Browse files Browse the repository at this point in the history
+ tinylog version bump
  • Loading branch information
q3769 committed Apr 13, 2024
1 parent 62f13e0 commit f85e01f
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 66 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ provider. With the ELF4J facade, opting for tinylog as the logging implementatio
The usual [tinylog configuration](https://tinylog.org/v2/configuration/) applies.

Note: Only one logging provider such as this should be in effect at run-time. If multiple providers end up in the final
build of an application, somehow, then the `elf4j.logger.factory.fqcn` system property will have to be used to select
build of an application, somehow, then the `elf4j.service.provider.fqcn` system property will have to be used to select
the desired provider. For example,

```
java -Delf4j.logger.factory.fqcn="elf4j.tinylog.TinylogLoggerFactory" -jar MyApplication.jar
java -Delf4j.service.provider.fqcn="elf4j.tinylog.TinylogLoggerFactory" -jar MyApplication.jar
```
29 changes: 27 additions & 2 deletions 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-tinylog</artifactId>
<version>12.0.0</version>
<version>13.0.0</version>

<packaging>jar</packaging>
<name>elf4j-tinylog</name>
Expand Down Expand Up @@ -68,7 +68,7 @@
<dependency>
<groupId>io.github.elf4j</groupId>
<artifactId>elf4j</artifactId>
<version>3.0.3</version>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.tinylog</groupId>
Expand Down Expand Up @@ -130,6 +130,31 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.43.0</version>
<executions>
<execution>
<id>spotless-apply-id</id>
<phase>process-sources</phase>
<goals>
<goal>apply</goal>
</goals>
</execution>
</executions>
<configuration>
<java>
<palantirJavaFormat>
<version>2.43.0</version>
<style>PALANTIR</style> <!-- or AOSP/GOOGLE (optional) -->
<formatJavadoc>true
</formatJavadoc> <!-- defaults to false (optional, requires at least Palantir 2.39.0) -->
</palantirJavaFormat>
<formatAnnotations/>
</java>
</configuration>
</plugin>
</plugins>
</build>

Expand Down
57 changes: 30 additions & 27 deletions src/main/java/elf4j/tinylog/TinylogLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,18 @@

package elf4j.tinylog;

import static elf4j.Level.*;

import elf4j.Level;
import elf4j.Logger;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
Expand All @@ -36,24 +46,11 @@
import org.tinylog.provider.ProviderRegistry;
import org.tinylog.runtime.RuntimeProvider;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

import static elf4j.Level.*;

/**
* Adapt tinylog capabilities to cater an ELF4J Logger
*/
/** Adapt tinylog capabilities to cater an ELF4J Logger */
@Immutable
@ToString
@EqualsAndHashCode
final class TinylogLogger implements Logger {
public final class TinylogLogger implements Logger {
private static final LoggingProvider LOGGING_PROVIDER = ProviderRegistry.getLoggingProvider();
private static final MessageFormatter MESSAGE_FORMATTER = new LegacyMessageFormatter();
private static final EnumMap<Level, Map<String, TinylogLogger>> LOGGER_CACHE;
Expand Down Expand Up @@ -87,8 +84,12 @@ final class TinylogLogger implements Logger {
ENABLEMENT_CACHE = new ConcurrentHashMap<>();
}

@EqualsAndHashCode.Include @NonNull private final String callerClassName;
@EqualsAndHashCode.Include @NonNull private final Level level;
@EqualsAndHashCode.Include
@NonNull private final String callerClassName;

@EqualsAndHashCode.Include
@NonNull private final Level level;

@NonNull private final org.tinylog.Level tinylogLevel;

TinylogLogger(@NonNull String callerClassName, @NonNull Level level) {
Expand Down Expand Up @@ -130,8 +131,8 @@ public Logger atLevel(Level level) {

@Override
public boolean isEnabled() {
return ENABLEMENT_CACHE.computeIfAbsent(this,
logger -> LOGGING_PROVIDER.isEnabled(CALLER_DEPTH_ENABLED_CHECK, null, logger.tinylogLevel));
return ENABLEMENT_CACHE.computeIfAbsent(
this, logger -> LOGGING_PROVIDER.isEnabled(CALLER_DEPTH_ENABLED_CHECK, null, logger.tinylogLevel));
}

@Override
Expand Down Expand Up @@ -159,23 +160,25 @@ public void log(Throwable t, String message, Object... args) {
tinylog(t, message, args);
}

public @NonNull String getCallerClassName() {
@NonNull String getCallerClassName() {
return callerClassName;
}

private void tinylog(@Nullable final Throwable exception,
@Nullable final Object message,
@Nullable final Object[] args) {
if (Boolean.FALSE.equals((ENABLEMENT_CACHE.computeIfAbsent(this,
logger -> LOGGING_PROVIDER.isEnabled(CALLER_DEPTH_ENABLED_LOG, null, logger.tinylogLevel))))) {
private void tinylog(
@Nullable final Throwable exception, @Nullable final Object message, @Nullable final Object[] args) {
if (Boolean.FALSE.equals((ENABLEMENT_CACHE.computeIfAbsent(
this, logger -> LOGGING_PROVIDER.isEnabled(CALLER_DEPTH_ENABLED_LOG, null, logger.tinylogLevel))))) {
return;
}
LOGGING_PROVIDER.log(CALLER_DEPTH_LOG,
LOGGING_PROVIDER.log(
CALLER_DEPTH_LOG,
null,
this.tinylogLevel,
exception,
args == null ? null : MESSAGE_FORMATTER,
resolve(message),
args == null ? null : Arrays.stream(args).map(TinylogLogger::resolve).toArray());
args == null
? null
: Arrays.stream(args).map(TinylogLogger::resolve).toArray());
}
}
9 changes: 5 additions & 4 deletions src/main/java/elf4j/tinylog/TinylogLoggerFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@

package elf4j.tinylog;

import elf4j.spi.LoggerFactory;
import elf4j.spi.LogServiceProvider;

/**
* Provider class implementation of ELF4J SPI, loadable via {@link java.util.ServiceLoader}.
*
* @see <a href="https://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html">Javadoc of
* ServiceLoader</a>
* @see <a href="https://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html">Javadoc of ServiceLoader</a>
*/
public final class TinylogLoggerFactory implements LoggerFactory {
public final class TinylogLoggerFactory implements LogServiceProvider {
/** A default constructor is required by the JDK Service Loader framework */
public TinylogLoggerFactory() {}

@Override
public TinylogLogger logger() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@
#
#

elf4j.tinylog.TinylogLoggerFactory
#elf4j.util.NoopLoggerFactory
elf4j.tinylog.TinylogLoggerFactory
65 changes: 36 additions & 29 deletions src/test/java/elf4j/tinylog/TinylogLoggerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,16 @@

package elf4j.tinylog;

import static elf4j.Level.*;
import static org.junit.jupiter.api.Assertions.*;

import elf4j.Level;
import elf4j.Logger;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static elf4j.Level.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

class TinylogLoggerTest {

Expand All @@ -52,7 +51,8 @@ void cacheLoggerWithSameNameAndLevel() {

@Test
void defaultNameAndLevel() {
logger.log("no-arg logger instance {} in class {} has default logger name: {}, and default level: {}",
logger.log(
"no-arg logger instance {} in class {} has default logger name: {}, and default level: {}",
logger,
this.getClass().getName(),
((TinylogLogger) logger).getCallerClassName(),
Expand All @@ -77,47 +77,53 @@ void exceptionMessageAndArgs() {
TinylogLogger error = (TinylogLogger) defaultLogger.atError();
Throwable ex = new Exception("ex message");
error.log(ex);
error.atInfo()
.log("{} is an immutable Logger instance whose name is {}, and level is {}",
error,
error.getCallerClassName(),
error.getLevel());
error.atInfo().log(
"{} is an immutable Logger instance whose name is {}, and level is {}",
error,
error.getCallerClassName(),
error.getLevel());
assertEquals(Level.ERROR, error.getLevel());
error.atError()
.log(ex,
.log(
ex,
"here the {} call is unnecessary because a Logger instance is immutable, and the {} instance's log level is already and will always be {}",
"atError()",
error,
ERROR);
error.log(ex,
error.log(
ex,
"now at Level.ERROR, together with the exception stack trace, logging some items expensive to compute: 1. {} 2. {} 3. {} 4. {}",
"usually an Object-type argument's Object.toString result is used for the final log message, except that...",
(Supplier) () -> "the Supplier.get result will be used instead for a Supplier-type argument",
"this allows for a mixture of Supplier and other Object types of arguments to compute to a sensible final log message",
(Supplier) () -> Arrays.stream(new Object[] {
"suppose this is an expensive message argument coming as a Supplier" })
(Supplier) () -> Arrays.stream(
new Object[] {"suppose this is an expensive message argument coming as a Supplier"})
.collect(Collectors.toList()));
}

@Test
void messagesAndArgs() {
defaultLogger.log("default logger name is usually the same as the API caller class name");
assertEquals(ReadmeSample.class.getName(), defaultLogger.getCallerClassName());
defaultLogger.log("default log level is {}, which depends on the individual logging provider",
defaultLogger.log(
"default log level is {}, which depends on the individual logging provider",
defaultLogger.getLevel());
TinylogLogger info = (TinylogLogger) defaultLogger.atInfo();
info.log("level set omitted here but we know the level is {}", INFO);
assertEquals(INFO, info.getLevel());
info.log("Supplier and other Object args can be mixed: Object arg1 {}, Supplier arg2 {}, Object arg3 {}",
info.log(
"Supplier and other Object args can be mixed: Object arg1 {}, Supplier arg2 {}, Object arg3 {}",
"a11111",
(Supplier) () -> "a22222",
"a33333");
info.atWarn()
.log("switched to WARN level on the fly. that is, {} is a different Logger instance from {}",
.log(
"switched to WARN level on the fly. that is, {} is a different Logger instance from {}",
"`info.atWarn()`",
"`info`");
assertNotSame(info, info.atWarn());
assertEquals(info.getCallerClassName(),
assertEquals(
info.getCallerClassName(),
((TinylogLogger) info.atWarn()).getCallerClassName(),
"same name, only level is different");
assertEquals(WARN, info.atWarn().getLevel());
Expand All @@ -132,15 +138,16 @@ class ReadmeSample2 {
@Test
void levelGuard() {
if (logger.atDebug().isEnabled()) {
logger.atDebug()
.log("a {} message guarded by a {}, so that no {} is created unless this logger instance - name and level combined - is {}",
"long and expensive-to-construct",
"level check",
"message object",
"enabled by system configuration of the logging provider");
logger.atDebug().log(
"a {} message guarded by a {}, so that no {} is created unless this logger instance - name and level combined - is {}",
"long and expensive-to-construct",
"level check",
"message object",
"enabled by system configuration of the logging provider");
}
logger.atDebug()
.log((Supplier) () -> "alternative to the level guard, using a Supplier<?> function like this should achieve the same goal of avoiding unnecessary message creation, pending quality of the logging provider");
logger.atDebug().log(
() ->
"alternative to the level guard, using a Supplier<?> function like this should achieve the same goal of avoiding unnecessary message creation, pending quality of the logging provider");
}
}
}
}

0 comments on commit f85e01f

Please sign in to comment.