From 6662a19afc0fb4cf4e0ec59f554e56641780023f Mon Sep 17 00:00:00 2001 From: Jean Helou Date: Thu, 9 Mar 2023 14:40:02 +0100 Subject: [PATCH] adds the logger_name and thread_name labels for logback --- .../tkowalcz/tjahzi/logback/LabelFactory.java | 56 ++++++-- .../tkowalcz/tjahzi/logback/LokiAppender.java | 21 ++- .../logback/LokiAppenderConfigurator.java | 18 +++ .../tjahzi/logback/LokiAppenderFactory.java | 14 ++ .../tjahzi/logback/LabelFactoryTest.java | 121 +++++++++++++++++- .../LogLevelLabelConfigurationTest.java | 5 + .../appender-test-with-log-label-set.xml | 7 +- .../test/resources/logback-configuration.xml | 6 + 8 files changed, 231 insertions(+), 17 deletions(-) diff --git a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LabelFactory.java b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LabelFactory.java index 087c944..f6fedb9 100644 --- a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LabelFactory.java +++ b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LabelFactory.java @@ -17,15 +17,21 @@ public class LabelFactory { private final ContextAware internalLogger; private final String logLevelLabel; + private final String loggerNameLabel; + private final String threadNameLabel; private final Label[] labels; public LabelFactory( ContextAware internalLogger, String logLevelLabel, + String loggerNameLabel, + String threadNameLabel, Label... labels ) { this.internalLogger = internalLogger; this.logLevelLabel = logLevelLabel; + this.loggerNameLabel = loggerNameLabel; + this.threadNameLabel = threadNameLabel; this.labels = labels; } @@ -36,9 +42,34 @@ public HashMap convertLabelsDroppingInvalid() { public String validateLogLevelLabel(HashMap existingLabels) { if (logLevelLabel != null) { - return validateLogLevelLabelAgainst( + return validatePredefinedLabelAgainst( existingLabels, - logLevelLabel + logLevelLabel, + "log level label" + ); + } + + return null; + } + + public String validateLoggerNameLabel(HashMap existingLabels) { + if (loggerNameLabel != null) { + return validatePredefinedLabelAgainst( + existingLabels, + loggerNameLabel, + "logger name label" + ); + } + + return null; + } + + public String validateThreadNameLabel(HashMap existingLabels) { + if (threadNameLabel != null) { + return validatePredefinedLabelAgainst( + existingLabels, + threadNameLabel, + "thread name label" ); } @@ -89,15 +120,17 @@ private HashMap convertAndLogViolations() { return lokiLabels; } - private String validateLogLevelLabelAgainst( + private String validatePredefinedLabelAgainst( Map existingLabels, - String logLevelLabel + String predefinedLabel, + String predefinedLabelDescription ) { - if (!Label.hasValidName(logLevelLabel)) { + if (!Label.hasValidName(predefinedLabel)) { internalLogger.addWarn( String.format( - "Ignoring log level label '%s' - contains invalid characters. %s\n", - logLevelLabel, + "Ignoring %s '%s' - contains invalid characters. %s\n", + predefinedLabelDescription, + predefinedLabel, GitHubDocs.LABEL_NAMING.getLogMessage() ) ); @@ -105,15 +138,16 @@ private String validateLogLevelLabelAgainst( return null; } - if (existingLabels.remove(logLevelLabel) != null) { + if (existingLabels.remove(predefinedLabel) != null) { internalLogger.addWarn( String.format( - "Ignoring log level label '%s' - conflicts with label defined in configuration.\n", - logLevelLabel + "Ignoring %s '%s' - conflicts with label defined in configuration.\n", + predefinedLabelDescription, + predefinedLabel ) ); } - return logLevelLabel; + return predefinedLabel; } } diff --git a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppender.java b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppender.java index f1a6bfe..21e7364 100644 --- a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppender.java +++ b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppender.java @@ -26,6 +26,8 @@ public class LokiAppender extends LokiAppenderConfigurator { private TjahziLogger logger; private String logLevelLabel; + private String loggerNameLabel; + private String threadNameLabel; private List mdcLogLabels; private MutableMonitoringModuleWrapper monitoringModuleWrapper; @@ -62,11 +64,15 @@ public LoggingSystem getLoggingSystem() { @Override protected void append(ILoggingEvent event) { String logLevel = event.getLevel().toString(); + String loggerName = event.getLoggerName(); + String threadName = event.getThreadName(); ByteBuffer logLine = actualEncoder.apply(event); Map mdcPropertyMap = event.getMDCPropertyMap(); - + LabelSerializer labelSerializer = LabelSerializers.threadLocal(); appendLogLabel(labelSerializer, logLevel); + appendLoggerLabel(labelSerializer, loggerName); + appendThreadLabel(labelSerializer, threadName); appendMdcLogLabels(labelSerializer, mdcPropertyMap); logger.log( @@ -83,6 +89,17 @@ private void appendLogLabel(LabelSerializer labelSerializer, String logLevel) { } } + private void appendLoggerLabel(LabelSerializer labelSerializer, String loggerName) { + if (loggerNameLabel != null) { + labelSerializer.appendLabel(loggerNameLabel, loggerName); + } + } + + private void appendThreadLabel(LabelSerializer labelSerializer, String threadName) { + if (threadNameLabel != null) { + labelSerializer.appendLabel(threadNameLabel, threadName); + } + } @SuppressWarnings("ForLoopReplaceableByForEach") // Allocator goes brrrr private void appendMdcLogLabels(LabelSerializer serializer, Map mdcPropertyMap) { @@ -112,6 +129,8 @@ public void start() { LokiAppenderFactory lokiAppenderFactory = new LokiAppenderFactory(this); loggingSystem = lokiAppenderFactory.createAppender(); logLevelLabel = lokiAppenderFactory.getLogLevelLabel(); + loggerNameLabel = lokiAppenderFactory.getLoggerNameLabel(); + threadNameLabel = lokiAppenderFactory.getThreadNameLabel(); mdcLogLabels = lokiAppenderFactory.getMdcLogLabels(); monitoringModuleWrapper = lokiAppenderFactory.getMonitoringModuleWrapper(); diff --git a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderConfigurator.java b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderConfigurator.java index 90d4c30..f997e7c 100644 --- a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderConfigurator.java +++ b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderConfigurator.java @@ -32,6 +32,8 @@ public abstract class LokiAppenderConfigurator extends UnsynchronizedAppenderBas private boolean useOffHeapBuffer = true; private String logLevelLabel; + private String loggerNameLabel; + private String threadNameLabel; private final List mdcLogLabels = new ArrayList<>(); private long batchSize = 10_2400; @@ -156,6 +158,22 @@ public void setLogLevelLabel(String logLevelLabel) { this.logLevelLabel = logLevelLabel; } + public String getLoggerNameLabel() { + return loggerNameLabel; + } + + public void setLoggerNameLabel(String loggerNameLabel) { + this.loggerNameLabel = loggerNameLabel; + } + + public String getThreadNameLabel() { + return threadNameLabel; + } + + public void setThreadNameLabel(String threadNameLabel) { + this.threadNameLabel = threadNameLabel; + } + public void setBatchSize(long batchSize) { this.batchSize = batchSize; } diff --git a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderFactory.java b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderFactory.java index 5f59305..59da390 100644 --- a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderFactory.java +++ b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderFactory.java @@ -20,6 +20,8 @@ public class LokiAppenderFactory { private final HashMap lokiLabels; private final String logLevelLabel; + private final String loggerNameLabel; + private final String threadNameLabel; private final List mdcLogLabels; private final MutableMonitoringModuleWrapper monitoringModuleWrapper; @@ -29,11 +31,15 @@ public LokiAppenderFactory(LokiAppenderConfigurator configurator) { LabelFactory labelFactory = new LabelFactory( configurator, configurator.getLogLevelLabel(), + configurator.getLoggerNameLabel(), + configurator.getThreadNameLabel(), configurator.getLabels().toArray(new Label[0]) ); lokiLabels = labelFactory.convertLabelsDroppingInvalid(); logLevelLabel = labelFactory.validateLogLevelLabel(lokiLabels); + loggerNameLabel = labelFactory.validateLoggerNameLabel(lokiLabels); + threadNameLabel = labelFactory.validateThreadNameLabel(lokiLabels); mdcLogLabels = configurator.getMdcLogLabels(); monitoringModuleWrapper = new MutableMonitoringModuleWrapper(); } @@ -96,6 +102,14 @@ public String getLogLevelLabel() { return logLevelLabel; } + public String getLoggerNameLabel() { + return loggerNameLabel; + } + + public String getThreadNameLabel() { + return threadNameLabel; + } + public MutableMonitoringModuleWrapper getMonitoringModuleWrapper() { return monitoringModuleWrapper; } diff --git a/logback-appender/src/test/java/pl/tkowalcz/tjahzi/logback/LabelFactoryTest.java b/logback-appender/src/test/java/pl/tkowalcz/tjahzi/logback/LabelFactoryTest.java index f6ea05d..6f5cfca 100644 --- a/logback-appender/src/test/java/pl/tkowalcz/tjahzi/logback/LabelFactoryTest.java +++ b/logback-appender/src/test/java/pl/tkowalcz/tjahzi/logback/LabelFactoryTest.java @@ -20,6 +20,8 @@ void shouldRemoveDuplicatedLabels() { LabelFactory labelFactory = new LabelFactory( new ConsoleAppender<>(), "log_level", + "logger_name", + "thread_name", thisIsADuplicateAndShouldBeDropped, thisShouldStay, thisTooShouldStay @@ -45,6 +47,8 @@ void shouldSkipLabelsWithInvalidName() { LabelFactory labelFactory = new LabelFactory( new ConsoleAppender<>(), "log_level", + "logger_name", + "thread_name", thisShouldStayToo, thisShouldStay, invalidNameShouldBeDropped @@ -61,7 +65,7 @@ void shouldSkipLabelsWithInvalidName() { } @Test - void shouldAcceptNullLogLevel() { + void shouldAcceptNullPredefinedLabels() { // Given Label label1 = Label.createLabel("ip", "10.0.2.34"); Label label2 = Label.createLabel("region", "coruscant-west-2"); @@ -69,6 +73,8 @@ void shouldAcceptNullLogLevel() { LabelFactory labelFactory = new LabelFactory( new ConsoleAppender<>(), null, + null, + null, label2, label1 ); @@ -94,6 +100,8 @@ void logLevelLabelShouldOverrideConflictingLabel() { LabelFactory labelFactory = new LabelFactory( new ConsoleAppender<>(), logLevelLabel, + null, + null, thisShouldBeRemovedDueToConflict, thisShouldStay ); @@ -121,7 +129,7 @@ void shouldDisableLogLevelLabelIfItHasInvalidName() { // Given String logLevelLabel = "log-level"; - LabelFactory labelFactory = new LabelFactory(new ConsoleAppender<>(), logLevelLabel); + LabelFactory labelFactory = new LabelFactory(new ConsoleAppender<>(), logLevelLabel, null, null); // When String actual = labelFactory.validateLogLevelLabel(new HashMap<>()); @@ -131,10 +139,115 @@ void shouldDisableLogLevelLabelIfItHasInvalidName() { } @Test - void shouldHandleDisabledLogLevelLabel() { + void loggerNameLabelShouldOverrideConflictingLabel() { + // Given + String loggerNameLabel = "logger_name"; + + Label thisShouldStay = Label.createLabel("ip", "10.0.2.34"); + Label thisShouldBeRemovedDueToConflict = Label.createLabel(loggerNameLabel, "coruscant-west-2"); + + LabelFactory labelFactory = new LabelFactory( + new ConsoleAppender<>(), + null, + loggerNameLabel, + null, + thisShouldBeRemovedDueToConflict, + thisShouldStay + ); + + HashMap labels = new HashMap<>( + Map.ofEntries( + asEntry(thisShouldStay), + asEntry(thisShouldBeRemovedDueToConflict) + ) + ); + + // When + String actual = labelFactory.validateLoggerNameLabel(labels); + + // Then + assertThat(labels).containsOnly( + asEntry(thisShouldStay) + ); + + assertThat(actual).isEqualTo(loggerNameLabel); + } + + @Test + void shouldDisableLoggerNameLabelIfItHasInvalidName() { + // Given + String loggerNameLabel = "logger-name"; + + LabelFactory labelFactory = new LabelFactory(new ConsoleAppender<>(), null, loggerNameLabel, null); + + // When + String actual = labelFactory.validateLogLevelLabel(new HashMap<>()); + + // Then + assertThat(actual).isNull(); + } + + @Test + void threadNameLabelShouldOverrideConflictingLabel() { + // Given + String threadNameLabel = "thread_name"; + + Label thisShouldStay = Label.createLabel("ip", "10.0.2.34"); + Label thisShouldBeRemovedDueToConflict = Label.createLabel(threadNameLabel, "coruscant-west-2"); + + LabelFactory labelFactory = new LabelFactory( + new ConsoleAppender<>(), + threadNameLabel, + null, + null, + thisShouldBeRemovedDueToConflict, + thisShouldStay + ); + + HashMap labels = new HashMap<>( + Map.ofEntries( + asEntry(thisShouldStay), + asEntry(thisShouldBeRemovedDueToConflict) + ) + ); + + // When + String actual = labelFactory.validateLogLevelLabel(labels); + + // Then + assertThat(labels).containsOnly( + asEntry(thisShouldStay) + ); + + assertThat(actual).isEqualTo(threadNameLabel); + } + + @Test + void shouldDisableThreadNameLabelIfItHasInvalidName() { + // Given + String threadNameLabel = "thread-name"; + + LabelFactory labelFactory = new LabelFactory(new ConsoleAppender<>(), threadNameLabel, null, null); + + // When + String actual = labelFactory.validateLogLevelLabel(new HashMap<>()); + + // Then + assertThat(actual).isNull(); + } + + @Test + void shouldHandleDisabledPredefinedLabels() { // Given String logLevelLabel = null; - LabelFactory labelFactory = new LabelFactory(new ConsoleAppender<>(), logLevelLabel); + String loggerNameLabel = null; + String threadNameLabel = null; + LabelFactory labelFactory = new LabelFactory( + new ConsoleAppender<>(), + logLevelLabel, + loggerNameLabel, + threadNameLabel + ); // When String actual = labelFactory.validateLogLevelLabel(new HashMap<>()); diff --git a/logback-appender/src/test/java/pl/tkowalcz/tjahzi/logback/LogLevelLabelConfigurationTest.java b/logback-appender/src/test/java/pl/tkowalcz/tjahzi/logback/LogLevelLabelConfigurationTest.java index ea731b5..c28b3e2 100644 --- a/logback-appender/src/test/java/pl/tkowalcz/tjahzi/logback/LogLevelLabelConfigurationTest.java +++ b/logback-appender/src/test/java/pl/tkowalcz/tjahzi/logback/LogLevelLabelConfigurationTest.java @@ -36,8 +36,11 @@ void shouldSendLogLevelAsConfigured() { LoggerContext context = loadConfig("appender-test-with-log-label-set.xml"); // When + String originalThreadName=Thread.currentThread().getName(); + Thread.currentThread().setName("appender-test-with-log-label-set.xml"); Logger logger = context.getLogger(LogLevelLabelConfigurationTest.class); logger.info("Test"); + Thread.currentThread().setName(originalThreadName); // Then assertThat(loki) @@ -46,6 +49,8 @@ void shouldSendLogLevelAsConfigured() { .body("status", equalTo("success")) .body("data.result.size()", equalTo(1)) .body("data.result[0].stream.log_level", equalTo("INFO")) + .body("data.result[0].stream.logger_name", equalTo("pl.tkowalcz.tjahzi.logback.LogLevelLabelConfigurationTest")) + .body("data.result[0].stream.thread_name", equalTo("appender-test-with-log-label-set.xml")) ); } } diff --git a/logback-appender/src/test/resources/appender-test-with-log-label-set.xml b/logback-appender/src/test/resources/appender-test-with-log-label-set.xml index dc83009..bba1488 100644 --- a/logback-appender/src/test/resources/appender-test-with-log-label-set.xml +++ b/logback-appender/src/test/resources/appender-test-with-log-label-set.xml @@ -15,7 +15,12 @@ log_level - + + logger_name + + + thread_name +