Skip to content

Commit

Permalink
Ensure Logback is refreshed before application starts (#8238)
Browse files Browse the repository at this point in the history
  • Loading branch information
driverpt committed Dec 16, 2022
1 parent 5cca96a commit 214051e
Show file tree
Hide file tree
Showing 8 changed files with 370 additions and 22 deletions.
Expand Up @@ -18,17 +18,24 @@
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.joran.spi.JoranException;
import io.micronaut.context.annotation.Property;
import io.micronaut.context.annotation.Replaces;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.logging.LogLevel;
import io.micronaut.logging.LoggingSystemException;
import io.micronaut.management.endpoint.loggers.LoggerConfiguration;
import io.micronaut.management.endpoint.loggers.LoggersEndpoint;
import io.micronaut.management.endpoint.loggers.ManagedLoggingSystem;
import jakarta.inject.Singleton;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
Expand All @@ -42,6 +49,10 @@
@Requires(classes = ch.qos.logback.classic.LoggerContext.class)
@Replaces(io.micronaut.logging.impl.LogbackLoggingSystem.class)
public class LogbackLoggingSystem implements ManagedLoggingSystem, io.micronaut.logging.LoggingSystem {
private static final String DEFAULT_LOGBACK_LOCATION = "logback.xml";

@Property(name = "logger.config")
private Optional<String> logbackXmlLocation;

@Override
@NonNull
Expand Down Expand Up @@ -106,4 +117,21 @@ private static Level toLevel(LogLevel logLevel) {
return Level.valueOf(logLevel.name());
}
}

@Override
public void refresh() {
LoggerContext context = getLoggerContext();
context.reset();
String logbackXml = logbackXmlLocation.orElse(DEFAULT_LOGBACK_LOCATION);
URL resource = getClass().getClassLoader().getResource(logbackXml);
if (Objects.isNull(resource)) {
throw new LoggingSystemException("Resource " + logbackXml + " not found");
}

try {
new ContextInitializer(context).configureByResource(resource);
} catch (JoranException e) {
throw new LoggingSystemException("Error while refreshing Logback", e);
}
}
}
7 changes: 7 additions & 0 deletions runtime/src/main/java/io/micronaut/logging/LoggingSystem.java
Expand Up @@ -38,4 +38,11 @@ public interface LoggingSystem {
*/
void setLogLevel(@NotBlank String name, @NotNull LogLevel level);

/**
* Refreshes Logging System with the goal of cleaning its internal caches.
*
*/
default void refresh() {

}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2017-2022 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.logging;

/**
* Thrown when something goes wrong on Logging System.
*
* @author Luis Duarte
* @since 3.8
*/
public class LoggingSystemException extends RuntimeException {

/**
* Create exception with detailed message and cause.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
*/
public LoggingSystemException(String message, Throwable cause) {
super(message, cause);
}

/**
* Create exception with detailed message and cause.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
*/
public LoggingSystemException(String message) {
super(message);
}
}
Expand Up @@ -64,6 +64,7 @@ final class PropertiesLoggingLevelsConfigurer implements ApplicationEventListene
public PropertiesLoggingLevelsConfigurer(Environment environment, List<LoggingSystem> loggingSystems) {
this.environment = environment;
this.loggingSystems = loggingSystems;
initLogging();
configureLogLevels();
}

Expand All @@ -74,9 +75,12 @@ public PropertiesLoggingLevelsConfigurer(Environment environment, List<LoggingSy
*/
@Override
public void onApplicationEvent(RefreshEvent event) {
if (event.getSource().keySet().stream().anyMatch(key -> key.startsWith(LOGGER_LEVELS_PROPERTY_PREFIX))) {
configureLogLevels();
}
initLogging();
configureLogLevels();
}

private void initLogging() {
this.loggingSystems.forEach(LoggingSystem::refresh);
}

private void configureLogLevels() {
Expand Down
Expand Up @@ -15,12 +15,20 @@
*/
package io.micronaut.logging.impl;

import java.net.URL;
import java.util.Objects;
import java.util.Optional;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.joran.spi.JoranException;
import io.micronaut.context.annotation.Property;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.annotation.Internal;
import io.micronaut.logging.LogLevel;
import io.micronaut.logging.LoggingSystem;
import io.micronaut.logging.LoggingSystemException;
import jakarta.inject.Singleton;
import org.slf4j.LoggerFactory;

Expand All @@ -35,11 +43,33 @@
@Internal
public final class LogbackLoggingSystem implements LoggingSystem {

private static final String DEFAULT_LOGBACK_LOCATION = "logback.xml";

@Property(name = "logger.config")
private Optional<String> logbackXmlLocation;

@Override
public void setLogLevel(String name, LogLevel level) {
getLoggerContext().getLogger(name).setLevel(toLevel(level));
}

@Override
public void refresh() {
LoggerContext context = getLoggerContext();
context.reset();
String logbackXml = logbackXmlLocation.orElse(DEFAULT_LOGBACK_LOCATION);
URL resource = getClass().getClassLoader().getResource(logbackXml);
if (Objects.isNull(resource)) {
throw new LoggingSystemException("Resource " + logbackXml + " not found");
}

try {
new ContextInitializer(context).configureByResource(resource);
} catch (JoranException e) {
throw new LoggingSystemException("Error while refreshing Logback", e);
}
}

/**
* @return The logback {@link LoggerContext}
*/
Expand Down
@@ -0,0 +1,180 @@
[
{
"name": "org.slf4j.impl.StaticLoggerBinder",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.DateConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.MessageConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.ThrowableProxyConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.NopThrowableInformationConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.ContextNameConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.BoldYellowCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.LoggerConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.ReplacingCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.BoldBlueCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.CyanCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.RedCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.WhiteCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.PropertyConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.RootCauseFirstThrowableProxyConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.MethodOfCallerConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.LevelConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.IdentityCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.BoldWhiteCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.MarkerConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.BoldCyanCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.BoldMagentaCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.RelativeTimeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.MagentaCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.ClassOfCallerConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.LineOfCallerConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.FileOfCallerConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.BoldGreenCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.LocalSequenceNumberConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.YellowCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.color.HighlightingCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.GrayCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.MDCConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.ClassOfCallerConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.BoldRedCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.GreenCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.pattern.color.BlackCompositeConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.ThreadConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.pattern.LineSeparatorConverter",
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.classic.encoder.PatternLayoutEncoder",
"allPublicMethods":true,
"allDeclaredConstructors": true
},
{
"name": "ch.qos.logback.core.ConsoleAppender",
"allPublicMethods":true,
"allDeclaredConstructors": true
},
{
"name": "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl",
"allDeclaredConstructors": true
}
]

0 comments on commit 214051e

Please sign in to comment.