From 502f1b5fc9e53cf8bff7a45390059fd1c3858b97 Mon Sep 17 00:00:00 2001 From: Anton Kurako Date: Sun, 13 Mar 2022 10:51:05 +0300 Subject: [PATCH 1/7] [0.13.0-SNAPSHOT] Dev ver up --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 2e7a170..07d5b1d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ groupId=io.goodforgod artifactId=slf4j-simple-logger -artifactVersion=0.12.0 +artifactVersion=0.13.0-SNAPSHOT ##### GRADLE ##### From 929608e28b8f2494a044103b74ba914fbe57c6a7 Mon Sep 17 00:00:00 2001 From: Anton Kurako Date: Tue, 15 Mar 2022 00:28:29 +0300 Subject: [PATCH 2/7] [0.13.0-SNAPSHOT] Layout interface to represent part of logger message to be printed SimpleLoggerLayouts default layout implementations SimpleLogger#write and SimpleLogger#log refactored to use Layout SimpleLoggerConfiguration Layout configure added --- .../goodforgod/slf4j/simplelogger/Layout.java | 27 ++ .../slf4j/simplelogger/SimpleLogger.java | 218 ++---------- .../SimpleLoggerConfiguration.java | 100 +++++- .../simplelogger/SimpleLoggerLayouts.java | 336 ++++++++++++++++++ 4 files changed, 482 insertions(+), 199 deletions(-) create mode 100644 src/main/java/io/goodforgod/slf4j/simplelogger/Layout.java create mode 100644 src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/Layout.java b/src/main/java/io/goodforgod/slf4j/simplelogger/Layout.java new file mode 100644 index 0000000..6740f72 --- /dev/null +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/Layout.java @@ -0,0 +1,27 @@ +package io.goodforgod.slf4j.simplelogger; + +/** + * Used to print part of logger layout + * + * @author Anton Kurako (GoodforGod) + * @since 14.03.2022 + */ +interface Layout extends Comparable { + + /** + * @param loggerName of the logger invoked + * @param level of the logger invoked + * @param builder to append layout + */ + void print(String loggerName, int level, StringBuilder builder); + + /** + * @return order layout compared to all others layouts + */ + int order(); + + @Override + default int compareTo(Layout o) { + return Integer.compare(order(), o.order()); + } +} diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java index e5a56db..822f75a 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java @@ -3,8 +3,6 @@ import static io.goodforgod.slf4j.simplelogger.SimpleLoggerProperties.PREFIX_LOG; import java.io.*; -import java.time.LocalDateTime; -import java.time.LocalTime; import org.slf4j.Logger; import org.slf4j.event.LoggingEvent; import org.slf4j.helpers.FormattingTuple; @@ -155,18 +153,15 @@ static void init() { /** * The short name of this simple log instance */ - private final transient String logName; - private final transient String logNameShort; + final String logName; /** * Package access allows only {@link SimpleLoggerFactory} to instantiate SimpleLogger instances. */ SimpleLogger(String name) { this.name = name; - this.logNameShort = computeShortName() + " - "; - this.logName = (CONFIG.logNameLength == null) - ? name + " - " - : ClassNameAbbreviator.abbreviate(name, CONFIG.logNameLength) + " - "; + this.logName = computeLogName(); + final String levelString = recursivelyComputeLevelString(); this.currentLogLevel = (levelString != null) ? SimpleLoggerConfiguration.tryStringToLevel(levelString).orElse(LOG_LEVEL_INFO) @@ -203,60 +198,9 @@ private void log(int level, String message, Throwable throwable) { return; } - final String threadName = (CONFIG.showThreadName) - ? Thread.currentThread().getName() - : null; - - final int length = predictBuilderLength(message, threadName, throwable); - final StringBuilder builder = new StringBuilder(length); - - // Append date-time if so configured - if (CONFIG.showDateTime) { - switch (CONFIG.dateTimeOutputType) { - case DATE_TIME: - builder.append(getFormattedDateTime()); - break; - case TIME: - builder.append(getFormattedTime()); - break; - case UNIX_TIME: - builder.append(System.currentTimeMillis()); - break; - case MILLIS_FROM_START: - builder.append(System.currentTimeMillis() - CONFIG.initializeTime); - break; - } - - builder.append(' '); - } - - // Append package implementation version - if (CONFIG.showImplementationVersion) { - builder.append('['); - builder.append(CONFIG.implementationVersion); - builder.append("] "); - } - - // Append a readable representation of the log level - final String levelStr = (CONFIG.levelInBrackets) - ? renderLevelInBrackets(level) - : renderLevel(level); - builder.append(levelStr); - - logEnvironment(builder); - - // Append current thread name if so configured - if (CONFIG.showThreadName) { - builder.append('['); - builder.append(threadName); - builder.append("] "); - } - - // Append the name of the log instance if so configured - if (CONFIG.showShortLogName) { - builder.append(logNameShort); - } else if (CONFIG.showLogName) { - builder.append(logName); + final StringBuilder builder = new StringBuilder(); + for (Layout layout : CONFIG.layouts) { + layout.print(logName, level, builder); } // Append the message @@ -270,139 +214,33 @@ private void log(int level, String message, Throwable throwable) { throwable.printStackTrace(printWriter); } - write(builder); - } - - private void logEnvironment(StringBuilder builder) { - if (CONFIG.environments.isEmpty()) { - return; - } - - if (CONFIG.environmentsOnStart != null) { - builder.append(CONFIG.environmentsOnStart); - } else { - boolean bracketUsed = false; - for (String envName : CONFIG.environments) { - final String envValue = System.getenv(envName); - if (envValue == null && !CONFIG.environmentShowNullable) { - continue; - } - - if (!bracketUsed) { - builder.append('['); - bracketUsed = true; - } else { - builder.append(", "); - } - - if (CONFIG.environmentShowName) { - builder.append(envName); - builder.append('='); - } - - builder.append(envValue); - } - - if (bracketUsed) { - builder.append("] "); - } - } - } - - private int predictBuilderLength(String message, String threadName, Throwable throwable) { - int length = 14; - - if (message != null) - length += message.length(); - if (throwable != null) - length += 2048; - if (threadName != null) - length += threadName.length(); - if (CONFIG.showDateTime) - length += 24; - - if (CONFIG.environmentsOnStart != null) { - length += CONFIG.environmentsOnStart.length(); - } else { - for (String env : CONFIG.environments) { - length += (CONFIG.environmentShowName) - ? env.length() + 6 - : 10; - } - } - - if (CONFIG.showImplementationVersion) - length += CONFIG.implementationVersion.length() + 4; - if (CONFIG.showShortLogName) { - length += logNameShort.length(); - } else if (CONFIG.showLogName) { - length += logName.length(); - } - - return length; - } - - protected String renderLevel(int level) { - switch (level) { - case LOG_LEVEL_INFO: - return "INFO "; - case LOG_LEVEL_WARN: - return "WARN "; - case LOG_LEVEL_ERROR: - return "ERROR "; - case LOG_LEVEL_DEBUG: - return "DEBUG "; - case LOG_LEVEL_TRACE: - return "TRACE "; - default: - throw new IllegalStateException("Unrecognized level [" + level + "]"); - } - } - - protected String renderLevelInBrackets(int level) { - switch (level) { - case LOG_LEVEL_INFO: - return "[INFO] "; - case LOG_LEVEL_WARN: - return "[WARN] "; - case LOG_LEVEL_ERROR: - return "[ERROR] "; - case LOG_LEVEL_DEBUG: - return "[DEBUG] "; - case LOG_LEVEL_TRACE: - return "[TRACE] "; - default: - throw new IllegalStateException("Unrecognized level [" + level + "]"); - } + write(builder.toString()); } /** * To avoid intermingling of log messages and associated stack traces, the two operations are done * in a synchronized block. * - * @param builder of logging message + * @param message of logging message */ - void write(StringBuilder builder) { - final String message = builder.toString(); + void write(String message) { final byte[] bytes = (CONFIG.charset == null) ? message.getBytes() : message.getBytes(CONFIG.charset); final PrintStream printStream = getOutputStream(); - synchronized (printStream) { - try { - printStream.write(bytes); - printStream.flush(); - } catch (IOException e) { - // do nothing - } + CONFIG.lock.lock(); + try { + printStream.write(bytes); + printStream.flush(); + } catch (IOException e) { + // do nothing + } finally { + CONFIG.lock.unlock(); } } private PrintStream getOutputStream() { - if (CONFIG.sameOutputChoice) - return CONFIG.outputChoice.getTargetPrintStream(); - switch (currentLogLevel) { case LOG_LEVEL_WARN: return CONFIG.outputChoiceWarn.getTargetPrintStream(); @@ -413,16 +251,18 @@ private PrintStream getOutputStream() { } } - private String getFormattedDateTime() { - return CONFIG.dateTimeFormatter.format(LocalDateTime.now()); - } - - private String getFormattedTime() { - return CONFIG.dateTimeFormatter.format(LocalTime.now()); - } - - private String computeShortName() { - return name.substring(name.lastIndexOf('.') + 1); + private String computeLogName() { + if (CONFIG.showShortLogName) { + return name.substring(name.lastIndexOf('.') + 1) + " - "; + } else if (CONFIG.showLogName) { + if (CONFIG.logNameLength == null) { + return name + " - "; + } else { + return ClassNameAbbreviator.abbreviate(name, CONFIG.logNameLength) + " - "; + } + } else { + return null; + } } /** diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java index e14c9dc..d60d25d 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java @@ -12,6 +12,7 @@ import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; import org.slf4j.event.Level; import org.slf4j.helpers.Util; @@ -36,7 +37,7 @@ public class SimpleLoggerConfiguration { private static final String SYSTEM_OUT = "System.out"; private static final String BOOLEAN_TRUE = "true"; - private static final String DATE_TIME_FORMAT_DEFAULT = "uuuu-MM-dd'T'HH:mm:ss.SSS"; + private static final String DATE_TIME_FORMAT_DEFAULT = "yyyy-MM-dd'T'HH:mm:ss.SSS"; private static final String TIME_FORMAT_DEFAULT = "HH:mm:ss.SSS"; private static final DateTimeFormatter DATE_TIME_FORMATTER_DEFAULT = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT_DEFAULT); private static final DateTimeFormatter TIME_FORMATTER_DEFAULT = DateTimeFormatter.ofPattern(TIME_FORMAT_DEFAULT); @@ -51,32 +52,35 @@ public class SimpleLoggerConfiguration { private static final boolean SHOW_DATE_TIME_DEFAULT = true; - boolean sameOutputChoice = false; final long initializeTime = System.currentTimeMillis(); + ReentrantLock lock = new ReentrantLock(false); Charset charset = StandardCharsets.UTF_8; OutputChoice outputChoice = null; OutputChoice outputChoiceWarn = null; OutputChoice outputChoiceError = null; int defaultLogLevel = SimpleLogger.LOG_LEVEL_INFO; - boolean levelInBrackets = LEVEL_IN_BRACKETS_DEFAULT; - boolean showThreadName = SHOW_THREAD_NAME_DEFAULT; + private boolean showThreadName = SHOW_THREAD_NAME_DEFAULT; + private boolean showImplementationVersion = SHOW_IMPLEMENTATION_VERSION_DEFAULT; + boolean showLogName = SHOW_LOG_NAME_DEFAULT; - boolean showImplementationVersion = SHOW_IMPLEMENTATION_VERSION_DEFAULT; Integer logNameLength = null; boolean showShortLogName = SHOW_SHORT_LOG_NAME_DEFAULT; - boolean showDateTime = SHOW_DATE_TIME_DEFAULT; - DateTimeOutputType dateTimeOutputType = DateTimeOutputType.DATE_TIME; + private boolean showDateTime = SHOW_DATE_TIME_DEFAULT; + private DateTimeOutputType dateTimeOutputType = DateTimeOutputType.DATE_TIME; DateTimeFormatter dateTimeFormatter; - String implementationVersion = SimpleLoggerConfiguration.class.getPackage().getImplementationVersion(); + String implementationVersion; List environments; boolean environmentShowNullable = false; boolean environmentShowName = true; String environmentsOnStart = null; + int predictedBuilderLength; + List layouts; + private final Properties properties = new Properties(); void init() { @@ -90,7 +94,8 @@ void init() { this.showImplementationVersion = getBooleanProperty(SHOW_IMPLEMENTATION_VERSION, SHOW_IMPLEMENTATION_VERSION_DEFAULT) && implementationVersion != null && !"null".equalsIgnoreCase(implementationVersion); - this.levelInBrackets = getBooleanProperty(LEVEL_IN_BRACKETS, LEVEL_IN_BRACKETS_DEFAULT); + this.implementationVersion = "[" + SimpleLoggerConfiguration.class.getPackage().getImplementationVersion() + "] "; + boolean levelInBrackets = getBooleanProperty(LEVEL_IN_BRACKETS, LEVEL_IN_BRACKETS_DEFAULT); this.showLogName = getBooleanProperty(SHOW_LOG_NAME, SimpleLoggerConfiguration.SHOW_LOG_NAME_DEFAULT); this.showShortLogName = getBooleanProperty(SHOW_SHORT_LOG_NAME, SHOW_SHORT_LOG_NAME_DEFAULT); this.showThreadName = getBooleanProperty(SHOW_THREAD_NAME, SHOW_THREAD_NAME_DEFAULT); @@ -101,7 +106,6 @@ void init() { final String logFile = getStringProperty(LOG_FILE, LOG_FILE_DEFAULT); final String logFileWarn = getStringProperty(LOG_FILE_WARN, LOG_FILE_DEFAULT); final String logFileError = getStringProperty(LOG_FILE_ERROR, LOG_FILE_DEFAULT); - this.sameOutputChoice = logFile.equals(logFileWarn) && logFileWarn.equals(logFileError); this.charset = Optional.ofNullable(getStringProperty(CHARSET, null)) .map(charset -> ("null".equals(charset)) @@ -143,6 +147,82 @@ void init() { || DateTimeOutputType.TIME.equals(this.dateTimeOutputType)) { this.dateTimeFormatter = getDateTimeFormatter(this.dateTimeOutputType); } + + this.predictedBuilderLength = predictBuilderLength(); + + final List layouts = new ArrayList<>(); + if (showThreadName) { + layouts.add(new SimpleLoggerLayouts.ThreadLayout()); + } + + if (showImplementationVersion) { + layouts.add(new SimpleLoggerLayouts.ImplementationLayout(this)); + } + + if (environmentsOnStart != null) { + layouts.add(new SimpleLoggerLayouts.EnvironmentOnStartLayout(this)); + } else if (!environments.isEmpty()) { + layouts.add(new SimpleLoggerLayouts.EnvironmentLayout(this)); + } + + if (showDateTime) { + switch (dateTimeOutputType) { + case TIME: + layouts.add(new SimpleLoggerLayouts.TimeLayout(this)); + break; + case DATE_TIME: + layouts.add(new SimpleLoggerLayouts.DateTimeLayout(this)); + break; + case UNIX_TIME: + layouts.add(new SimpleLoggerLayouts.UnixTimeLayout()); + break; + case MILLIS_FROM_START: + layouts.add(new SimpleLoggerLayouts.MillisFromStartLayout(this)); + break; + default: + throw new IllegalStateException("Unknown DateTimeOutputType: " + dateTimeOutputType); + } + } + + if (levelInBrackets) { + layouts.add(new SimpleLoggerLayouts.LevelInBracketLayout()); + } else { + layouts.add(new SimpleLoggerLayouts.LevelLayout()); + } + + if (showThreadName || showLogName) { + layouts.add(new SimpleLoggerLayouts.LoggerNameLayout()); + } + + Collections.sort(layouts); + this.layouts = layouts; + } + + private int predictBuilderLength() { + int length = 14; + + if (showThreadName) + length += 20; + if (showDateTime) + length += 24; + + if (environmentsOnStart != null) { + length += environmentsOnStart.length(); + } else { + for (String env : environments) { + length += (environmentShowName) + ? env.length() + 6 + : 10; + } + } + + if (showImplementationVersion) + length += implementationVersion.length() + 4; + if (showLogName) { + length += 70; + } + + return length; } private List getEnvironments() { diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java new file mode 100644 index 0000000..b31615f --- /dev/null +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java @@ -0,0 +1,336 @@ +package io.goodforgod.slf4j.simplelogger; + +import java.time.*; + +/** + * Default SimpleLogger layout implementations + * + * @author Anton Kurako (GoodforGod) + * @since 14.03.2022 + */ +final class SimpleLoggerLayouts { + + private static final long NANOS_PER_SECOND = 1000_000_000L; + private static final int SECONDS_PER_DAY = 60 * 60 * 24; + + private SimpleLoggerLayouts() {} + + private enum LayoutOrder { + DATE_TIME, + IMPLEMENTATION, + LEVEL, + ENVIRONMENT, + THREAD, + LOGGER_NAME + } + + private static final class DateTimeCache { + + private final long epochMillis; + private final String formatted; + + private DateTimeCache(long epochMillis, String formatted) { + this.epochMillis = epochMillis; + this.formatted = formatted; + } + } + + static final class DateTimeLayout implements Layout { + + private final Clock clock = Clock.systemDefaultZone(); + private final SimpleLoggerConfiguration configuration; + + private volatile DateTimeCache cache = new DateTimeCache(-1, null); + + DateTimeLayout(SimpleLoggerConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + builder.append(getFormattedDateTime()); + builder.append(' '); + } + + /** + * @see LocalDateTime#ofEpochSecond(long, int, ZoneOffset) + * @return formatter date time + */ + private String getFormattedDateTime() { + final DateTimeCache localCache = this.cache; + final long epochMilli = System.currentTimeMillis(); + + if (localCache.epochMillis == epochMilli) { + return localCache.formatted; + } else { + final Instant now = Instant.ofEpochMilli(epochMilli); + final ZoneOffset offset = clock.getZone().getRules().getOffset(now); + final long localSecond = now.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later + final long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY); + final int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY); + final LocalDate date = LocalDate.ofEpochDay(localEpochDay); + final LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + now.getNano()); + final LocalDateTime dateTime = LocalDateTime.of(date, time); + + final String formatted = configuration.dateTimeFormatter.format(dateTime); + this.cache = new DateTimeCache(epochMilli, formatted); + return formatted; + } + } + + @Override + public int order() { + return LayoutOrder.DATE_TIME.ordinal(); + } + } + + static final class TimeLayout implements Layout { + + private final Clock clock = Clock.systemDefaultZone(); + private final SimpleLoggerConfiguration configuration; + + private volatile DateTimeCache cache = new DateTimeCache(-1, null); + + TimeLayout(SimpleLoggerConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + builder.append(getFormattedTime()); + builder.append(' '); + } + + /** + * @see LocalTime#ofNanoOfDay(long) (long, int, ZoneOffset) + * @return formatter date time + */ + private String getFormattedTime() { + final DateTimeCache localCache = this.cache; + final long epochMilli = System.currentTimeMillis(); + + if (localCache.epochMillis == epochMilli) { + return localCache.formatted; + } else { + final Instant now = Instant.ofEpochMilli(epochMilli); + final ZoneOffset offset = clock.getZone().getRules().getOffset(now); + final long localSecond = now.getEpochSecond() + offset.getTotalSeconds(); + final int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY); + final LocalTime localTime = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + now.getNano()); + + final String formatted = configuration.dateTimeFormatter.format(localTime); + this.cache = new DateTimeCache(epochMilli, formatted); + return formatted; + } + } + + @Override + public int order() { + return LayoutOrder.DATE_TIME.ordinal(); + } + } + + static final class UnixTimeLayout implements Layout { + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + builder.append(System.currentTimeMillis()); + builder.append(' '); + } + + @Override + public int order() { + return LayoutOrder.DATE_TIME.ordinal(); + } + } + + static final class MillisFromStartLayout implements Layout { + + private final SimpleLoggerConfiguration configuration; + + MillisFromStartLayout(SimpleLoggerConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + builder.append(System.currentTimeMillis() - configuration.initializeTime); + builder.append(' '); + } + + @Override + public int order() { + return LayoutOrder.DATE_TIME.ordinal(); + } + } + + static final class ImplementationLayout implements Layout { + + private final SimpleLoggerConfiguration configuration; + + ImplementationLayout(SimpleLoggerConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + builder.append(configuration.implementationVersion); + } + + @Override + public int order() { + return LayoutOrder.IMPLEMENTATION.ordinal(); + } + } + + static final class LevelLayout implements Layout { + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + builder.append(renderLevel(level)); + } + + private String renderLevel(int level) { + switch (level) { + case SimpleLogger.LOG_LEVEL_INFO: + return "INFO "; + case SimpleLogger.LOG_LEVEL_WARN: + return "WARN "; + case SimpleLogger.LOG_LEVEL_ERROR: + return "ERROR "; + case SimpleLogger.LOG_LEVEL_DEBUG: + return "DEBUG "; + case SimpleLogger.LOG_LEVEL_TRACE: + return "TRACE "; + default: + throw new IllegalStateException("Unrecognized level [" + level + "]"); + } + } + + @Override + public int order() { + return LayoutOrder.LEVEL.ordinal(); + } + } + + static final class LevelInBracketLayout implements Layout { + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + builder.append(renderLevel(level)); + } + + private String renderLevel(int level) { + switch (level) { + case SimpleLogger.LOG_LEVEL_INFO: + return "[INFO] "; + case SimpleLogger.LOG_LEVEL_WARN: + return "[WARN] "; + case SimpleLogger.LOG_LEVEL_ERROR: + return "[ERROR] "; + case SimpleLogger.LOG_LEVEL_DEBUG: + return "[DEBUG] "; + case SimpleLogger.LOG_LEVEL_TRACE: + return "[TRACE] "; + default: + throw new IllegalStateException("Unrecognized level [" + level + "]"); + } + } + + @Override + public int order() { + return LayoutOrder.LEVEL.ordinal(); + } + } + + static final class EnvironmentOnStartLayout implements Layout { + + private final SimpleLoggerConfiguration configuration; + + EnvironmentOnStartLayout(SimpleLoggerConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + builder.append(configuration.environmentsOnStart); + } + + @Override + public int order() { + return LayoutOrder.ENVIRONMENT.ordinal(); + } + } + + static final class EnvironmentLayout implements Layout { + + private final SimpleLoggerConfiguration configuration; + + EnvironmentLayout(SimpleLoggerConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + boolean bracketUsed = false; + for (String envName : configuration.environments) { + final String envValue = System.getenv(envName); + if (envValue == null && !configuration.environmentShowNullable) { + continue; + } + + if (!bracketUsed) { + builder.append('['); + bracketUsed = true; + } else { + builder.append(", "); + } + + if (configuration.environmentShowName) { + builder.append(envName); + builder.append('='); + } + + builder.append(envValue); + } + + if (bracketUsed) { + builder.append("] "); + } + } + + @Override + public int order() { + return LayoutOrder.ENVIRONMENT.ordinal(); + } + } + + static final class ThreadLayout implements Layout { + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + final String threadName = Thread.currentThread().getName(); + builder.append('['); + builder.append(threadName); + builder.append("] "); + } + + @Override + public int order() { + return LayoutOrder.THREAD.ordinal(); + } + } + + static final class LoggerNameLayout implements Layout { + + @Override + public void print(String loggerName, int level, StringBuilder builder) { + builder.append(loggerName); + } + + @Override + public int order() { + return LayoutOrder.LOGGER_NAME.ordinal(); + } + } +} From e8492cf89bdc06a2189f6f19d246bb9f39864170 Mon Sep 17 00:00:00 2001 From: Anton Kurako Date: Tue, 15 Mar 2022 19:25:51 +0300 Subject: [PATCH 3/7] [0.13.0-SNAPSHOT] SimpleLoggerConfiguration fields closed and minor refactoring --- .../slf4j/simplelogger/SimpleLogger.java | 51 ++-- .../SimpleLoggerConfiguration.java | 237 ++++++++++-------- .../simplelogger/SimpleLoggerLayouts.java | 29 ++- 3 files changed, 161 insertions(+), 156 deletions(-) diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java index 822f75a..46c187a 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java @@ -3,6 +3,9 @@ import static io.goodforgod.slf4j.simplelogger.SimpleLoggerProperties.PREFIX_LOG; import java.io.*; +import java.nio.charset.Charset; +import java.util.List; +import java.util.concurrent.locks.Lock; import org.slf4j.Logger; import org.slf4j.event.LoggingEvent; import org.slf4j.helpers.FormattingTuple; @@ -160,12 +163,12 @@ static void init() { */ SimpleLogger(String name) { this.name = name; - this.logName = computeLogName(); + this.logName = CONFIG.computeLogName(name); final String levelString = recursivelyComputeLevelString(); this.currentLogLevel = (levelString != null) ? SimpleLoggerConfiguration.tryStringToLevel(levelString).orElse(LOG_LEVEL_INFO) - : CONFIG.defaultLogLevel; + : CONFIG.getDefaultLogLevel(); this.originalLogLevel = this.currentLogLevel; } @@ -199,7 +202,8 @@ private void log(int level, String message, Throwable throwable) { } final StringBuilder builder = new StringBuilder(); - for (Layout layout : CONFIG.layouts) { + final List layouts = CONFIG.getLayouts(); + for (Layout layout : layouts) { layout.print(logName, level, builder); } @@ -214,7 +218,7 @@ private void log(int level, String message, Throwable throwable) { throwable.printStackTrace(printWriter); } - write(builder.toString()); + write(level, builder.toString()); } /** @@ -223,45 +227,22 @@ private void log(int level, String message, Throwable throwable) { * * @param message of logging message */ - void write(String message) { - final byte[] bytes = (CONFIG.charset == null) + void write(int level, String message) { + final Charset charset = CONFIG.getCharset(); + final byte[] bytes = (charset == null) ? message.getBytes() - : message.getBytes(CONFIG.charset); + : message.getBytes(charset); - final PrintStream printStream = getOutputStream(); - CONFIG.lock.lock(); + final PrintStream printStream = CONFIG.getOutputStream(level); + final Lock lock = CONFIG.getLock(); + lock.lock(); try { printStream.write(bytes); printStream.flush(); } catch (IOException e) { // do nothing } finally { - CONFIG.lock.unlock(); - } - } - - private PrintStream getOutputStream() { - switch (currentLogLevel) { - case LOG_LEVEL_WARN: - return CONFIG.outputChoiceWarn.getTargetPrintStream(); - case LOG_LEVEL_ERROR: - return CONFIG.outputChoiceError.getTargetPrintStream(); - default: - return CONFIG.outputChoice.getTargetPrintStream(); - } - } - - private String computeLogName() { - if (CONFIG.showShortLogName) { - return name.substring(name.lastIndexOf('.') + 1) + " - "; - } else if (CONFIG.showLogName) { - if (CONFIG.logNameLength == null) { - return name + " - "; - } else { - return ClassNameAbbreviator.abbreviate(name, CONFIG.logNameLength) + " - "; - } - } else { - return null; + lock.unlock(); } } diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java index d60d25d..c4fc720 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java @@ -12,6 +12,7 @@ import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; import org.slf4j.event.Level; @@ -35,77 +36,65 @@ public class SimpleLoggerConfiguration { private static final String SYSTEM_ERR = "System.err"; private static final String SYSTEM_OUT = "System.out"; - private static final String BOOLEAN_TRUE = "true"; - private static final String DATE_TIME_FORMAT_DEFAULT = "yyyy-MM-dd'T'HH:mm:ss.SSS"; - private static final String TIME_FORMAT_DEFAULT = "HH:mm:ss.SSS"; - private static final DateTimeFormatter DATE_TIME_FORMATTER_DEFAULT = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT_DEFAULT); - private static final DateTimeFormatter TIME_FORMATTER_DEFAULT = DateTimeFormatter.ofPattern(TIME_FORMAT_DEFAULT); - private static final String LOG_FILE_DEFAULT = SYSTEM_OUT; + private static final DateTimeFormatter DATE_TIME_FORMATTER_DEFAULT = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS"); + private static final DateTimeFormatter TIME_FORMATTER_DEFAULT = DateTimeFormatter.ofPattern("HH:mm:ss.SSS"); private static final boolean CACHE_OUTPUT_STREAM_DEFAULT = false; - private static final boolean LEVEL_IN_BRACKETS_DEFAULT = true; private static final boolean SHOW_THREAD_NAME_DEFAULT = false; private static final boolean SHOW_LOG_NAME_DEFAULT = true; private static final boolean SHOW_IMPLEMENTATION_VERSION_DEFAULT = false; private static final boolean SHOW_SHORT_LOG_NAME_DEFAULT = false; - private static final boolean SHOW_DATE_TIME_DEFAULT = true; - final long initializeTime = System.currentTimeMillis(); - - ReentrantLock lock = new ReentrantLock(false); - Charset charset = StandardCharsets.UTF_8; - OutputChoice outputChoice = null; - OutputChoice outputChoiceWarn = null; - OutputChoice outputChoiceError = null; - int defaultLogLevel = SimpleLogger.LOG_LEVEL_INFO; - - private boolean showThreadName = SHOW_THREAD_NAME_DEFAULT; - private boolean showImplementationVersion = SHOW_IMPLEMENTATION_VERSION_DEFAULT; + private long initializeTime; + private final ReentrantLock lock = new ReentrantLock(false); + private Charset charset = StandardCharsets.UTF_8; + private int defaultLogLevel = SimpleLogger.LOG_LEVEL_INFO; - boolean showLogName = SHOW_LOG_NAME_DEFAULT; - Integer logNameLength = null; - boolean showShortLogName = SHOW_SHORT_LOG_NAME_DEFAULT; + private OutputChoice outputChoice = null; + private OutputChoice outputChoiceWarn = null; + private OutputChoice outputChoiceError = null; - private boolean showDateTime = SHOW_DATE_TIME_DEFAULT; - private DateTimeOutputType dateTimeOutputType = DateTimeOutputType.DATE_TIME; - DateTimeFormatter dateTimeFormatter; + private boolean showLogName = SHOW_LOG_NAME_DEFAULT; + private Integer logNameLength = null; + private boolean showShortLogName = SHOW_SHORT_LOG_NAME_DEFAULT; - String implementationVersion; - List environments; - boolean environmentShowNullable = false; - boolean environmentShowName = true; - String environmentsOnStart = null; + private DateTimeFormatter dateTimeFormatter; + private String implementationVersion; - int predictedBuilderLength; - List layouts; + private List environments; + private boolean environmentShowNullable = false; + private boolean environmentShowName = true; + private String environmentsOnStart = null; + private List layouts; private final Properties properties = new Properties(); void init() { loadProperties(); + this.initializeTime = System.currentTimeMillis(); final String defaultLogLevelString = getStringProperty(DEFAULT_LOG_LEVEL, null); if (defaultLogLevelString != null) { this.defaultLogLevel = tryStringToLevel(defaultLogLevelString).orElse(SimpleLogger.LOG_LEVEL_INFO); } - this.showImplementationVersion = getBooleanProperty(SHOW_IMPLEMENTATION_VERSION, SHOW_IMPLEMENTATION_VERSION_DEFAULT) - && implementationVersion != null - && !"null".equalsIgnoreCase(implementationVersion); this.implementationVersion = "[" + SimpleLoggerConfiguration.class.getPackage().getImplementationVersion() + "] "; boolean levelInBrackets = getBooleanProperty(LEVEL_IN_BRACKETS, LEVEL_IN_BRACKETS_DEFAULT); this.showLogName = getBooleanProperty(SHOW_LOG_NAME, SimpleLoggerConfiguration.SHOW_LOG_NAME_DEFAULT); this.showShortLogName = getBooleanProperty(SHOW_SHORT_LOG_NAME, SHOW_SHORT_LOG_NAME_DEFAULT); - this.showThreadName = getBooleanProperty(SHOW_THREAD_NAME, SHOW_THREAD_NAME_DEFAULT); + boolean showThreadName = getBooleanProperty(SHOW_THREAD_NAME, SHOW_THREAD_NAME_DEFAULT); this.logNameLength = getIntProperty(SHOW_LOG_NAME_LENGTH) .filter(i -> i > 0) .orElse(null); - final String logFile = getStringProperty(LOG_FILE, LOG_FILE_DEFAULT); - final String logFileWarn = getStringProperty(LOG_FILE_WARN, LOG_FILE_DEFAULT); - final String logFileError = getStringProperty(LOG_FILE_ERROR, LOG_FILE_DEFAULT); + final String logFile = getStringProperty(LOG_FILE, SYSTEM_OUT); + final String logFileWarn = getStringProperty(LOG_FILE_WARN, SYSTEM_OUT); + final String logFileError = getStringProperty(LOG_FILE_ERROR, SYSTEM_OUT); + boolean showImplementationVersion = getBooleanProperty(SHOW_IMPLEMENTATION_VERSION, SHOW_IMPLEMENTATION_VERSION_DEFAULT) + && implementationVersion != null + && !"null".equalsIgnoreCase(implementationVersion); this.charset = Optional.ofNullable(getStringProperty(CHARSET, null)) .map(charset -> ("null".equals(charset)) @@ -127,13 +116,14 @@ void init() { this.outputChoiceError = computeOutputChoice(logFileError, cacheOutputStream); } - this.environments = getEnvironments(); + this.environments = computeEnvironments(); this.environmentShowNullable = getBooleanProperty(ENVIRONMENT_SHOW_NULLABLE, false); this.environmentShowName = getBooleanProperty(ENVIRONMENT_SHOW_NAME, false); - this.environmentsOnStart = getEnvironmentsOnStart(); + this.environmentsOnStart = computeEnvironmentsOnStart(this.environments, this.environmentShowNullable, + this.environmentShowName); - this.showDateTime = getBooleanProperty(SHOW_DATE_TIME, SHOW_DATE_TIME_DEFAULT); - this.dateTimeOutputType = Optional.ofNullable(getStringProperty(DATE_TIME_OUTPUT_TYPE)) + boolean showDateTime = getBooleanProperty(SHOW_DATE_TIME, SHOW_DATE_TIME_DEFAULT); + final DateTimeOutputType dateTimeOutputType = Optional.ofNullable(getStringProperty(DATE_TIME_OUTPUT_TYPE)) .map(s -> { try { return DateTimeOutputType.valueOf(s); @@ -143,21 +133,20 @@ void init() { }) .orElse(DateTimeOutputType.DATE_TIME); - if (DateTimeOutputType.DATE_TIME.equals(this.dateTimeOutputType) - || DateTimeOutputType.TIME.equals(this.dateTimeOutputType)) { - this.dateTimeFormatter = getDateTimeFormatter(this.dateTimeOutputType); + if (DateTimeOutputType.DATE_TIME.equals(dateTimeOutputType) || DateTimeOutputType.TIME.equals(dateTimeOutputType)) { + this.dateTimeFormatter = getDateTimeFormatter(dateTimeOutputType); } - this.predictedBuilderLength = predictBuilderLength(); - final List layouts = new ArrayList<>(); - if (showThreadName) { - layouts.add(new SimpleLoggerLayouts.ThreadLayout()); + if (showDateTime) { + layouts.add(getDateTimeLayout(dateTimeOutputType)); } - if (showImplementationVersion) { layouts.add(new SimpleLoggerLayouts.ImplementationLayout(this)); } + if (showThreadName) { + layouts.add(new SimpleLoggerLayouts.ThreadLayout()); + } if (environmentsOnStart != null) { layouts.add(new SimpleLoggerLayouts.EnvironmentOnStartLayout(this)); @@ -165,25 +154,6 @@ void init() { layouts.add(new SimpleLoggerLayouts.EnvironmentLayout(this)); } - if (showDateTime) { - switch (dateTimeOutputType) { - case TIME: - layouts.add(new SimpleLoggerLayouts.TimeLayout(this)); - break; - case DATE_TIME: - layouts.add(new SimpleLoggerLayouts.DateTimeLayout(this)); - break; - case UNIX_TIME: - layouts.add(new SimpleLoggerLayouts.UnixTimeLayout()); - break; - case MILLIS_FROM_START: - layouts.add(new SimpleLoggerLayouts.MillisFromStartLayout(this)); - break; - default: - throw new IllegalStateException("Unknown DateTimeOutputType: " + dateTimeOutputType); - } - } - if (levelInBrackets) { layouts.add(new SimpleLoggerLayouts.LevelInBracketLayout()); } else { @@ -198,58 +168,113 @@ void init() { this.layouts = layouts; } - private int predictBuilderLength() { - int length = 14; + List getEnvironments() { + return environments; + } - if (showThreadName) - length += 20; - if (showDateTime) - length += 24; + String getEnvironmentsOnStart() { + return environmentsOnStart; + } - if (environmentsOnStart != null) { - length += environmentsOnStart.length(); - } else { - for (String env : environments) { - length += (environmentShowName) - ? env.length() + 6 - : 10; + boolean isEnvironmentShowNullable() { + return environmentShowNullable; + } + + boolean isEnvironmentShowName() { + return environmentShowName; + } + + List getLayouts() { + return layouts; + } + + String getImplementationVersion() { + return implementationVersion; + } + + DateTimeFormatter getDateTimeFormatter() { + return dateTimeFormatter; + } + + long getInitializeTime() { + return initializeTime; + } + + int getDefaultLogLevel() { + return defaultLogLevel; + } + + Charset getCharset() { + return charset; + } + + String computeLogName(String name) { + if (showShortLogName) { + return name.substring(name.lastIndexOf('.') + 1) + " - "; + } else if (showLogName) { + if (logNameLength == null) { + return name + " - "; + } else { + return ClassNameAbbreviator.abbreviate(name, logNameLength) + " - "; } + } else { + return null; } + } + + Lock getLock() { + return lock; + } - if (showImplementationVersion) - length += implementationVersion.length() + 4; - if (showLogName) { - length += 70; + PrintStream getOutputStream(int logLevel) { + switch (logLevel) { + case SimpleLogger.LOG_LEVEL_WARN: + return outputChoiceWarn.getTargetPrintStream(); + case SimpleLogger.LOG_LEVEL_ERROR: + return outputChoiceError.getTargetPrintStream(); + default: + return outputChoice.getTargetPrintStream(); } + } - return length; + private Layout getDateTimeLayout(DateTimeOutputType dateTimeOutputType) { + switch (dateTimeOutputType) { + case TIME: + return new SimpleLoggerLayouts.TimeLayout(this); + case DATE_TIME: + return new SimpleLoggerLayouts.DateTimeLayout(this); + case UNIX_TIME: + return new SimpleLoggerLayouts.UnixTimeLayout(); + case MILLIS_FROM_START: + return new SimpleLoggerLayouts.MillisFromStartLayout(this); + default: + throw new IllegalStateException("Unknown DateTimeOutputType: " + dateTimeOutputType); + } } - private List getEnvironments() { + private List computeEnvironments() { return Optional.ofNullable(getStringProperty(ENVIRONMENTS)) .filter(envs -> !envs.isBlank()) - .map(envs -> { - final List envsToOutput = Arrays.stream(envs.split(",")) - .map(String::strip) - .filter(env -> !env.isBlank()) - .collect(Collectors.toList()); - - return List.copyOf(envsToOutput); - }) + .map(envs -> List.copyOf(Arrays.stream(envs.split(",")) + .map(String::strip) + .filter(env -> !env.isBlank()) + .collect(Collectors.toList()))) .orElse(Collections.emptyList()); } - private String getEnvironmentsOnStart() { + private String computeEnvironmentsOnStart(List environments, + boolean environmentShowNullable, + boolean environmentShowName) { final boolean rememberEnvsOnStart = getBooleanProperty(ENVIRONMENT_REMEMBER_ON_START, false); if (rememberEnvsOnStart) { - final String envsOnStart = this.environments.stream() + final String envsOnStart = environments.stream() .map(env -> { final String envValue = System.getenv(env); - if (envValue == null && !this.environmentShowNullable) { + if (envValue == null && !environmentShowNullable) { return null; } - return this.environmentShowName + return environmentShowName ? env + "=" + envValue : envValue; }) @@ -290,7 +315,7 @@ private DateTimeFormatter getDateTimeFormatter(DateTimeOutputType dateTimeOutput } else if (DateTimeOutputType.TIME.equals(dateTimeOutputType)) { return TIME_FORMATTER_DEFAULT; } else { - throw new UnsupportedOperationException("Unsupported Date Output Type formatter: " + this.dateTimeOutputType); + throw new UnsupportedOperationException("Unsupported Date Output Type formatter: " + dateTimeOutputType); } } @@ -321,14 +346,14 @@ String getStringProperty(String name, String defaultValue) { : prop; } - boolean getBooleanProperty(String name, boolean defaultValue) { + private boolean getBooleanProperty(String name, boolean defaultValue) { final String prop = getStringProperty(name); return (prop == null) ? defaultValue - : BOOLEAN_TRUE.equalsIgnoreCase(prop); + : "true".equalsIgnoreCase(prop); } - Optional getIntProperty(String name) { + private Optional getIntProperty(String name) { final String prop = getStringProperty(name); if (prop == null) return Optional.empty(); @@ -340,7 +365,7 @@ Optional getIntProperty(String name) { } } - String getStringProperty(String name) { + private String getStringProperty(String name) { String prop = null; try { prop = System.getProperty(name); diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java index b31615f..2902bd4 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java @@ -15,6 +15,9 @@ final class SimpleLoggerLayouts { private SimpleLoggerLayouts() {} + /** + * Uses {@link LayoutOrder#ordinal()} for ordering layouts between each other + */ private enum LayoutOrder { DATE_TIME, IMPLEMENTATION, @@ -37,9 +40,7 @@ private DateTimeCache(long epochMillis, String formatted) { static final class DateTimeLayout implements Layout { - private final Clock clock = Clock.systemDefaultZone(); private final SimpleLoggerConfiguration configuration; - private volatile DateTimeCache cache = new DateTimeCache(-1, null); DateTimeLayout(SimpleLoggerConfiguration configuration) { @@ -64,7 +65,7 @@ private String getFormattedDateTime() { return localCache.formatted; } else { final Instant now = Instant.ofEpochMilli(epochMilli); - final ZoneOffset offset = clock.getZone().getRules().getOffset(now); + final ZoneOffset offset = Clock.systemDefaultZone().getZone().getRules().getOffset(now); final long localSecond = now.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later final long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY); final int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY); @@ -72,7 +73,7 @@ private String getFormattedDateTime() { final LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + now.getNano()); final LocalDateTime dateTime = LocalDateTime.of(date, time); - final String formatted = configuration.dateTimeFormatter.format(dateTime); + final String formatted = configuration.getDateTimeFormatter().format(dateTime); this.cache = new DateTimeCache(epochMilli, formatted); return formatted; } @@ -86,9 +87,7 @@ public int order() { static final class TimeLayout implements Layout { - private final Clock clock = Clock.systemDefaultZone(); private final SimpleLoggerConfiguration configuration; - private volatile DateTimeCache cache = new DateTimeCache(-1, null); TimeLayout(SimpleLoggerConfiguration configuration) { @@ -102,7 +101,7 @@ public void print(String loggerName, int level, StringBuilder builder) { } /** - * @see LocalTime#ofNanoOfDay(long) (long, int, ZoneOffset) + * @see LocalTime#ofInstant(Instant, ZoneId) * @return formatter date time */ private String getFormattedTime() { @@ -113,12 +112,12 @@ private String getFormattedTime() { return localCache.formatted; } else { final Instant now = Instant.ofEpochMilli(epochMilli); - final ZoneOffset offset = clock.getZone().getRules().getOffset(now); + final ZoneOffset offset = Clock.systemDefaultZone().getZone().getRules().getOffset(now); final long localSecond = now.getEpochSecond() + offset.getTotalSeconds(); final int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY); final LocalTime localTime = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + now.getNano()); - final String formatted = configuration.dateTimeFormatter.format(localTime); + final String formatted = configuration.getDateTimeFormatter().format(localTime); this.cache = new DateTimeCache(epochMilli, formatted); return formatted; } @@ -154,7 +153,7 @@ static final class MillisFromStartLayout implements Layout { @Override public void print(String loggerName, int level, StringBuilder builder) { - builder.append(System.currentTimeMillis() - configuration.initializeTime); + builder.append(System.currentTimeMillis() - configuration.getInitializeTime()); builder.append(' '); } @@ -174,7 +173,7 @@ static final class ImplementationLayout implements Layout { @Override public void print(String loggerName, int level, StringBuilder builder) { - builder.append(configuration.implementationVersion); + builder.append(configuration.getImplementationVersion()); } @Override @@ -253,7 +252,7 @@ static final class EnvironmentOnStartLayout implements Layout { @Override public void print(String loggerName, int level, StringBuilder builder) { - builder.append(configuration.environmentsOnStart); + builder.append(configuration.getEnvironmentsOnStart()); } @Override @@ -273,9 +272,9 @@ static final class EnvironmentLayout implements Layout { @Override public void print(String loggerName, int level, StringBuilder builder) { boolean bracketUsed = false; - for (String envName : configuration.environments) { + for (String envName : configuration.getEnvironments()) { final String envValue = System.getenv(envName); - if (envValue == null && !configuration.environmentShowNullable) { + if (envValue == null && !configuration.isEnvironmentShowNullable()) { continue; } @@ -286,7 +285,7 @@ public void print(String loggerName, int level, StringBuilder builder) { builder.append(", "); } - if (configuration.environmentShowName) { + if (configuration.isEnvironmentShowName()) { builder.append(envName); builder.append('='); } From 73f6443df39186ae476f5ebb2a6d12cf14a12b6c Mon Sep 17 00:00:00 2001 From: Anton Kurako Date: Tue, 15 Mar 2022 19:32:51 +0300 Subject: [PATCH 4/7] [0.13.0-SNAPSHOT] SimpleLoggerConfiguration cleaned up --- .../SimpleLoggerConfiguration.java | 142 ++++++++++-------- 1 file changed, 77 insertions(+), 65 deletions(-) diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java index c4fc720..fdd377b 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java @@ -80,11 +80,11 @@ void init() { this.defaultLogLevel = tryStringToLevel(defaultLogLevelString).orElse(SimpleLogger.LOG_LEVEL_INFO); } - this.implementationVersion = "[" + SimpleLoggerConfiguration.class.getPackage().getImplementationVersion() + "] "; - boolean levelInBrackets = getBooleanProperty(LEVEL_IN_BRACKETS, LEVEL_IN_BRACKETS_DEFAULT); + final String impl = SimpleLoggerConfiguration.class.getPackage().getImplementationVersion(); + this.implementationVersion = (impl == null) + ? null + : "[" + impl + "] "; this.showLogName = getBooleanProperty(SHOW_LOG_NAME, SimpleLoggerConfiguration.SHOW_LOG_NAME_DEFAULT); - this.showShortLogName = getBooleanProperty(SHOW_SHORT_LOG_NAME, SHOW_SHORT_LOG_NAME_DEFAULT); - boolean showThreadName = getBooleanProperty(SHOW_THREAD_NAME, SHOW_THREAD_NAME_DEFAULT); this.logNameLength = getIntProperty(SHOW_LOG_NAME_LENGTH) .filter(i -> i > 0) .orElse(null); @@ -92,16 +92,8 @@ void init() { final String logFile = getStringProperty(LOG_FILE, SYSTEM_OUT); final String logFileWarn = getStringProperty(LOG_FILE_WARN, SYSTEM_OUT); final String logFileError = getStringProperty(LOG_FILE_ERROR, SYSTEM_OUT); - boolean showImplementationVersion = getBooleanProperty(SHOW_IMPLEMENTATION_VERSION, SHOW_IMPLEMENTATION_VERSION_DEFAULT) - && implementationVersion != null - && !"null".equalsIgnoreCase(implementationVersion); - - this.charset = Optional.ofNullable(getStringProperty(CHARSET, null)) - .map(charset -> ("null".equals(charset)) - ? null - : Charset.forName(charset)) - .orElse(StandardCharsets.UTF_8); + this.charset = computeCharset(); final boolean cacheOutputStream = getBooleanProperty(CACHE_OUTPUT_STREAM_STRING, CACHE_OUTPUT_STREAM_DEFAULT); this.outputChoice = computeOutputChoice(logFile, cacheOutputStream); this.outputChoiceWarn = (logFile.equals(logFileWarn)) @@ -122,28 +114,26 @@ void init() { this.environmentsOnStart = computeEnvironmentsOnStart(this.environments, this.environmentShowNullable, this.environmentShowName); - boolean showDateTime = getBooleanProperty(SHOW_DATE_TIME, SHOW_DATE_TIME_DEFAULT); - final DateTimeOutputType dateTimeOutputType = Optional.ofNullable(getStringProperty(DATE_TIME_OUTPUT_TYPE)) - .map(s -> { - try { - return DateTimeOutputType.valueOf(s); - } catch (IllegalArgumentException e) { - return DateTimeOutputType.DATE_TIME; - } - }) - .orElse(DateTimeOutputType.DATE_TIME); - + final DateTimeOutputType dateTimeOutputType = computeDateTimeOutputType(); if (DateTimeOutputType.DATE_TIME.equals(dateTimeOutputType) || DateTimeOutputType.TIME.equals(dateTimeOutputType)) { this.dateTimeFormatter = getDateTimeFormatter(dateTimeOutputType); } final List layouts = new ArrayList<>(); + final boolean showDateTime = getBooleanProperty(SHOW_DATE_TIME, SHOW_DATE_TIME_DEFAULT); if (showDateTime) { layouts.add(getDateTimeLayout(dateTimeOutputType)); } + + final boolean showImplementationVersion = getBooleanProperty(SHOW_IMPLEMENTATION_VERSION, + SHOW_IMPLEMENTATION_VERSION_DEFAULT) + && this.implementationVersion != null + && !"null".equalsIgnoreCase(this.implementationVersion); if (showImplementationVersion) { layouts.add(new SimpleLoggerLayouts.ImplementationLayout(this)); } + + final boolean showThreadName = getBooleanProperty(SHOW_THREAD_NAME, SHOW_THREAD_NAME_DEFAULT); if (showThreadName) { layouts.add(new SimpleLoggerLayouts.ThreadLayout()); } @@ -154,13 +144,15 @@ void init() { layouts.add(new SimpleLoggerLayouts.EnvironmentLayout(this)); } + final boolean levelInBrackets = getBooleanProperty(LEVEL_IN_BRACKETS, LEVEL_IN_BRACKETS_DEFAULT); if (levelInBrackets) { layouts.add(new SimpleLoggerLayouts.LevelInBracketLayout()); } else { layouts.add(new SimpleLoggerLayouts.LevelLayout()); } - if (showThreadName || showLogName) { + this.showShortLogName = getBooleanProperty(SHOW_SHORT_LOG_NAME, SHOW_SHORT_LOG_NAME_DEFAULT); + if (showShortLogName || showLogName) { layouts.add(new SimpleLoggerLayouts.LoggerNameLayout()); } @@ -168,44 +160,24 @@ void init() { this.layouts = layouts; } - List getEnvironments() { - return environments; - } - - String getEnvironmentsOnStart() { - return environmentsOnStart; - } - - boolean isEnvironmentShowNullable() { - return environmentShowNullable; - } - - boolean isEnvironmentShowName() { - return environmentShowName; - } - - List getLayouts() { - return layouts; - } - - String getImplementationVersion() { - return implementationVersion; - } - - DateTimeFormatter getDateTimeFormatter() { - return dateTimeFormatter; - } - - long getInitializeTime() { - return initializeTime; - } - - int getDefaultLogLevel() { - return defaultLogLevel; + private Charset computeCharset() { + return Optional.ofNullable(getStringProperty(CHARSET, null)) + .map(charset -> ("null".equals(charset)) + ? null + : Charset.forName(charset)) + .orElse(StandardCharsets.UTF_8); } - Charset getCharset() { - return charset; + private DateTimeOutputType computeDateTimeOutputType() { + return Optional.ofNullable(getStringProperty(DATE_TIME_OUTPUT_TYPE)) + .map(s -> { + try { + return DateTimeOutputType.valueOf(s); + } catch (IllegalArgumentException e) { + return DateTimeOutputType.DATE_TIME; + } + }) + .orElse(DateTimeOutputType.DATE_TIME); } String computeLogName(String name) { @@ -222,10 +194,6 @@ String computeLogName(String name) { } } - Lock getLock() { - return lock; - } - PrintStream getOutputStream(int logLevel) { switch (logLevel) { case SimpleLogger.LOG_LEVEL_WARN: @@ -319,6 +287,50 @@ private DateTimeFormatter getDateTimeFormatter(DateTimeOutputType dateTimeOutput } } + List getEnvironments() { + return environments; + } + + String getEnvironmentsOnStart() { + return environmentsOnStart; + } + + boolean isEnvironmentShowNullable() { + return environmentShowNullable; + } + + boolean isEnvironmentShowName() { + return environmentShowName; + } + + List getLayouts() { + return layouts; + } + + String getImplementationVersion() { + return implementationVersion; + } + + DateTimeFormatter getDateTimeFormatter() { + return dateTimeFormatter; + } + + long getInitializeTime() { + return initializeTime; + } + + int getDefaultLogLevel() { + return defaultLogLevel; + } + + Charset getCharset() { + return charset; + } + + Lock getLock() { + return lock; + } + private void loadProperties() { // Add props from the resource simplelogger.properties InputStream in = AccessController.doPrivileged((PrivilegedAction) () -> { From b20c991ba9bca64983459d834eec6b33bf750e84 Mon Sep 17 00:00:00 2001 From: Anton Kurako Date: Tue, 15 Mar 2022 21:01:02 +0300 Subject: [PATCH 5/7] [0.13.0] Release prepared --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 07d5b1d..9e0b426 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ groupId=io.goodforgod artifactId=slf4j-simple-logger -artifactVersion=0.13.0-SNAPSHOT +artifactVersion=0.13.0 ##### GRADLE ##### From 4fc8cae3d96b69ddcc96034568047bba2e22f578 Mon Sep 17 00:00:00 2001 From: Anton Kurako Date: Tue, 15 Mar 2022 21:04:34 +0300 Subject: [PATCH 6/7] [0.13.0] Some classes marked final --- README.md | 4 ++-- .../slf4j/simplelogger/SimpleLogger.java | 20 +++++++++---------- .../SimpleLoggerConfiguration.java | 2 +- .../simplelogger/SimpleLoggerFactory.java | 2 +- .../org/slf4j/impl/StaticLoggerBinder.java | 2 +- .../java/org/slf4j/impl/StaticMDCBinder.java | 2 +- .../org/slf4j/impl/StaticMarkerBinder.java | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 6cecef5..e185279 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Java 11+ compatible. [**Gradle**](https://mvnrepository.com/artifact/io.goodforgod/slf4j-simple-logger) ```groovy -implementation "io.goodforgod:slf4j-simple-logger:0.12.0" +implementation "io.goodforgod:slf4j-simple-logger:0.13.0" ``` [**Maven**](https://mvnrepository.com/artifact/io.goodforgod/slf4j-simple-logger) @@ -33,7 +33,7 @@ implementation "io.goodforgod:slf4j-simple-logger:0.12.0" io.goodforgod slf4j-simple-logger - 0.12.0 + 0.13.0 ``` diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java index 46c187a..cfe35f7 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLogger.java @@ -119,14 +119,14 @@ * @author Anton Kurako (GoodforGod) * @since 09.10.2021 */ -public class SimpleLogger extends MarkerIgnoringBase { +public final class SimpleLogger extends MarkerIgnoringBase { - protected static final int LOG_LEVEL_TRACE = LocationAwareLogger.TRACE_INT; - protected static final int LOG_LEVEL_DEBUG = LocationAwareLogger.DEBUG_INT; - protected static final int LOG_LEVEL_INFO = LocationAwareLogger.INFO_INT; - protected static final int LOG_LEVEL_WARN = LocationAwareLogger.WARN_INT; - protected static final int LOG_LEVEL_ERROR = LocationAwareLogger.ERROR_INT; - protected static final int LOG_LEVEL_OFF = LOG_LEVEL_ERROR + 10; + static final int LOG_LEVEL_TRACE = LocationAwareLogger.TRACE_INT; + static final int LOG_LEVEL_DEBUG = LocationAwareLogger.DEBUG_INT; + static final int LOG_LEVEL_INFO = LocationAwareLogger.INFO_INT; + static final int LOG_LEVEL_WARN = LocationAwareLogger.WARN_INT; + static final int LOG_LEVEL_ERROR = LocationAwareLogger.ERROR_INT; + static final int LOG_LEVEL_OFF = LOG_LEVEL_ERROR + 10; private static final SimpleLoggerConfiguration CONFIG = new SimpleLoggerConfiguration(); @@ -151,8 +151,8 @@ static void init() { /** * The current log level */ - protected int currentLogLevel; - protected final int originalLogLevel; + int currentLogLevel; + final int originalLogLevel; /** * The short name of this simple log instance */ @@ -302,7 +302,7 @@ private void formatAndLog(int level, String format, Object... arguments) { * @param logLevel is this level enabled? * @return true if enabled */ - protected boolean isLevelEnabled(int logLevel) { + boolean isLevelEnabled(int logLevel) { return (logLevel >= currentLogLevel); } diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java index fdd377b..344fa31 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java @@ -30,7 +30,7 @@ * @author Anton Kurako (GoodforGod) * @since 09.10.2021 */ -public class SimpleLoggerConfiguration { +public final class SimpleLoggerConfiguration { private static final String CONFIGURATION_FILE = "simplelogger.properties"; diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerFactory.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerFactory.java index 6fffc29..557c4dc 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerFactory.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerFactory.java @@ -14,7 +14,7 @@ * @author Anton Kurako (GoodforGod) * @since 09.10.2021 */ -public class SimpleLoggerFactory implements ILoggerFactory { +public final class SimpleLoggerFactory implements ILoggerFactory { private final ConcurrentMap loggerMap; diff --git a/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index 639c809..8b92fc1 100644 --- a/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -13,7 +13,7 @@ * @author Anton Kurako (GoodforGod) * @since 09.10.2021 */ -public class StaticLoggerBinder implements LoggerFactoryBinder { +public final class StaticLoggerBinder implements LoggerFactoryBinder { /** * The unique instance of this class. diff --git a/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/src/main/java/org/slf4j/impl/StaticMDCBinder.java index 59d33e0..181a5a8 100644 --- a/src/main/java/org/slf4j/impl/StaticMDCBinder.java +++ b/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -10,7 +10,7 @@ * @author Anton Kurako (GoodforGod) * @since 09.10.2021 */ -public class StaticMDCBinder { +public final class StaticMDCBinder { /** * The unique instance of this class. diff --git a/src/main/java/org/slf4j/impl/StaticMarkerBinder.java b/src/main/java/org/slf4j/impl/StaticMarkerBinder.java index 49af1b1..0a1739a 100644 --- a/src/main/java/org/slf4j/impl/StaticMarkerBinder.java +++ b/src/main/java/org/slf4j/impl/StaticMarkerBinder.java @@ -13,7 +13,7 @@ * @author Anton Kurako (GoodforGod) * @since 09.10.2021 */ -public class StaticMarkerBinder implements MarkerFactoryBinder { +public final class StaticMarkerBinder implements MarkerFactoryBinder { /** * The unique instance of this class. From 7feaeb2637181dd2802d8feb838b0f13682098c6 Mon Sep 17 00:00:00 2001 From: Anton Kurako Date: Tue, 15 Mar 2022 21:17:41 +0300 Subject: [PATCH 7/7] [0.13.0] SimpleLoggerLayouts#LevelLayout simplified and duplication removed --- .../SimpleLoggerConfiguration.java | 4 +- .../simplelogger/SimpleLoggerLayouts.java | 48 +++++++------------ 2 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java index 344fa31..8b578fa 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerConfiguration.java @@ -146,9 +146,9 @@ void init() { final boolean levelInBrackets = getBooleanProperty(LEVEL_IN_BRACKETS, LEVEL_IN_BRACKETS_DEFAULT); if (levelInBrackets) { - layouts.add(new SimpleLoggerLayouts.LevelInBracketLayout()); + layouts.add(new SimpleLoggerLayouts.LevelLayout("[TRACE] ", "[DEBUG] ", "[INFO] ", "[WARN] ", "[ERROR] ")); } else { - layouts.add(new SimpleLoggerLayouts.LevelLayout()); + layouts.add(new SimpleLoggerLayouts.LevelLayout("TRACE ", "DEBUG ", "INFO ", "WARN ", "ERROR ")); } this.showShortLogName = getBooleanProperty(SHOW_SHORT_LOG_NAME, SHOW_SHORT_LOG_NAME_DEFAULT); diff --git a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java index 2902bd4..42d4d93 100644 --- a/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java +++ b/src/main/java/io/goodforgod/slf4j/simplelogger/SimpleLoggerLayouts.java @@ -184,35 +184,19 @@ public int order() { static final class LevelLayout implements Layout { - @Override - public void print(String loggerName, int level, StringBuilder builder) { - builder.append(renderLevel(level)); - } + private final String trace; + private final String debug; + private final String info; + private final String warn; + private final String error; - private String renderLevel(int level) { - switch (level) { - case SimpleLogger.LOG_LEVEL_INFO: - return "INFO "; - case SimpleLogger.LOG_LEVEL_WARN: - return "WARN "; - case SimpleLogger.LOG_LEVEL_ERROR: - return "ERROR "; - case SimpleLogger.LOG_LEVEL_DEBUG: - return "DEBUG "; - case SimpleLogger.LOG_LEVEL_TRACE: - return "TRACE "; - default: - throw new IllegalStateException("Unrecognized level [" + level + "]"); - } - } - - @Override - public int order() { - return LayoutOrder.LEVEL.ordinal(); + LevelLayout(String trace, String debug, String info, String warn, String error) { + this.trace = trace; + this.debug = debug; + this.info = info; + this.warn = warn; + this.error = error; } - } - - static final class LevelInBracketLayout implements Layout { @Override public void print(String loggerName, int level, StringBuilder builder) { @@ -222,15 +206,15 @@ public void print(String loggerName, int level, StringBuilder builder) { private String renderLevel(int level) { switch (level) { case SimpleLogger.LOG_LEVEL_INFO: - return "[INFO] "; + return info; case SimpleLogger.LOG_LEVEL_WARN: - return "[WARN] "; + return warn; case SimpleLogger.LOG_LEVEL_ERROR: - return "[ERROR] "; + return error; case SimpleLogger.LOG_LEVEL_DEBUG: - return "[DEBUG] "; + return debug; case SimpleLogger.LOG_LEVEL_TRACE: - return "[TRACE] "; + return trace; default: throw new IllegalStateException("Unrecognized level [" + level + "]"); }