Skip to content

Commit

Permalink
Merge branch 'branch_1.3.x' of github.com:qos-ch/logback into branch_…
Browse files Browse the repository at this point in the history
…1.3.x
  • Loading branch information
ceki committed Aug 4, 2023
2 parents 42e0355 + fbe45c6 commit 54c23fe
Show file tree
Hide file tree
Showing 16 changed files with 111 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*
* @author Ceki Gülcü
*/
@ConfiguratorRank(value = ConfiguratorRank.Value.FALLBACK)
@ConfiguratorRank(value = ConfiguratorRank.FALLBACK)
public class BasicConfigurator extends ContextAwareBase implements Configurator {

public BasicConfigurator() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ public class ClassicConstants {
public static final String CONFIG_FILE_PROPERTY = "logback.configurationFile";

/**
* property name for the model file used for configuration
* property name designating the path for the serialized configuration model file
* @since 1.3.9/1.4.9
*/
public static final String MODEL_CONFIG_FILE_PROPERTY = "logback.modelFile";
public static final String MODEL_CONFIG_FILE_PROPERTY = "logback.scmoFile";

public static final String JNDI_CONFIGURATION_RESOURCE = JNDI_JAVA_NAMESPACE
+ "comp/env/logback/configuration-resource";
Expand Down Expand Up @@ -60,4 +60,6 @@ public class ClassicConstants {

public static final String FINALIZE_SESSION = "FINALIZE_SESSION";
public static final Marker FINALIZE_SESSION_MARKER = MarkerFactory.getMarker(FINALIZE_SESSION);
final public static String AUTOCONFIG_FILE = "logback.xml";
final public static String TEST_AUTOCONFIG_FILE = "logback-test.xml";
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import ch.qos.logback.classic.ClassicConstants;
import ch.qos.logback.classic.joran.serializedModel.HardenedModelInputStream;
import ch.qos.logback.classic.model.processor.LogbackClassicDefaultNestedComponentRules;
import ch.qos.logback.classic.spi.ConfiguratorRank;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.LogbackException;
import ch.qos.logback.core.model.Model;
Expand All @@ -43,6 +44,7 @@
*/

// BEWARE: the fqcn is used in SerializedModelModelHandler
@ConfiguratorRank(value = ConfiguratorRank.SERIALIZED_MODEL)
public class SerializedModelConfigurator extends ContextAwareBase implements Configurator {

final public static String AUTOCONFIG_MODEL_FILE = "logback"+ MODEL_CONFIG_FILE_EXTENSION;
Expand Down Expand Up @@ -96,10 +98,13 @@ private void buildModelInterpretationContext(Model topModel) {
}

private Model retrieveModel(URL url) {
long start = System.currentTimeMillis();
try (InputStream is = url.openStream()) {
HardenedModelInputStream hmis = new HardenedModelInputStream(is);

Model model = (Model) hmis.readObject();
long diff = System.currentTimeMillis() - start;
addInfo("Model at ["+url+"] read in "+diff + " milliseconds");
return model;
} catch(IOException e) {
addError("Failed to open "+url, e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ public void handle(ModelInterpretationContext mic, Model model) {
}

protected void processScanAttrib(ModelInterpretationContext mic, ConfigurationModel configurationModel) {
System.out.println("This is overriden processScanAttrib");
String scanStr = mic.subst(configurationModel.getScanStr());
if (!OptionHelper.isNullOrEmpty(scanStr) && !"false".equalsIgnoreCase(scanStr)) {
addInfo("Skipping ReconfigureOnChangeTask registration");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,19 @@
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ConfiguratorRank {
enum Value {
FIRST,
REGULAR,
FALLBACK;
}

Value value() default Value.REGULAR;
static public int FALLBACK = -10;
static public int NOMINAL = 0;
static public int SERIALIZED_MODEL = 10;

static public int DEFAULT = 20;

static public int CUSTOM_LOW_PRIORITY = DEFAULT;

static public int CUSTOM_NORMAL_PRIORITY = 30;

static public int CUSTOM_HIGH_PRIORITY = 40;

static public int CUSTOM_TOP_PRIORITY = 50;
public int value() default DEFAULT;
}
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ public long getSequenceNumber() {
return sequenceNumber;
}

public void setSquenceNumber(long sn) {
public void setSequenceNumber(long sn) {
sequenceNumber = sn;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,21 @@
*/
public class ContextInitializer {

final public static String AUTOCONFIG_FILE = DefaultJoranConfigurator.AUTOCONFIG_FILE;
final public static String TEST_AUTOCONFIG_FILE = DefaultJoranConfigurator.TEST_AUTOCONFIG_FILE;
/**
* @deprecated Please use ClassicConstants.AUTOCONFIG_FILE instead
*/
final public static String AUTOCONFIG_FILE = ClassicConstants.AUTOCONFIG_FILE;
/**
* @deprecated Please use ClassicConstants.TEST_AUTOCONFIG_FILE instead
*/
final public static String TEST_AUTOCONFIG_FILE = ClassicConstants.TEST_AUTOCONFIG_FILE;
/**
* @deprecated Please use ClassicConstants.CONFIG_FILE_PROPERTY instead
*/
final public static String CONFIG_FILE_PROPERTY = ClassicConstants.CONFIG_FILE_PROPERTY;
private static final String JORAN_CONFIGURATION_DURATION_MSG = "JoranConfiguration duration ";
private static final String CONFIGURATION_AS_A_SERVICE_DURATION_MSG = "Configuration as a service duration ";

String[] INTERNAL_CONFIGURATOR_CLASSNAME_LIST = {"ch.qos.logback.classic.joran.SerializedModelConfigurator",
"ch.qos.logback.classic.util.DefaultJoranConfigurator", "ch.qos.logback.classic.BasicConfigurator"};

final LoggerContext loggerContext;

Expand All @@ -67,45 +74,74 @@ public void autoConfig(ClassLoader classLoader) throws JoranException {
loggerContext.getStatusManager().add(new InfoStatus(CoreConstants.LOGBACK_CLASSIC_VERSION_MESSAGE + versionStr, loggerContext));
StatusListenerConfigHelper.installIfAsked(loggerContext);

long startConfigurationAsAService = System.currentTimeMillis();
List<Configurator> configuratorList = ClassicEnvUtil.loadFromServiceLoader(Configurator.class, classLoader);

// invoke custom configurators
List<Configurator> configuratorList = ClassicEnvUtil.loadFromServiceLoader(Configurator.class, classLoader);
configuratorList.sort(rankComparator);
if (configuratorList.isEmpty()) {
contextAware.addInfo("No custom configurators were discovered as a service.");
} else {
printConfiguratorOrder(configuratorList);
}

for (Configurator c : configuratorList) {
try {
contextAware.addInfo("Constructed configurator of type " + c.getClass());
c.setContext(loggerContext);
Configurator.ExecutionStatus status = c.configure(loggerContext);
if (status == Configurator.ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY) {
printDuration(startConfigurationAsAService, CONFIGURATION_AS_A_SERVICE_DURATION_MSG, true);
return;
}
} catch (Exception e) {
throw new LogbackException(String.format("Failed to initialize Configurator: %s using ServiceLoader",
c != null ? c.getClass().getCanonicalName() : "null"), e);
}
if (invokeConfigure(c) == Configurator.ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY)
return;
}

printDuration(startConfigurationAsAService, CONFIGURATION_AS_A_SERVICE_DURATION_MSG, false);
// invoke internal configurators
for (String configuratorClassName : INTERNAL_CONFIGURATOR_CLASSNAME_LIST) {
contextAware.addInfo("Trying to configure with "+configuratorClassName);
Configurator c = instantiateConfiguratorByClassName(configuratorClassName, classLoader);
if(c == null)
continue;
if (invokeConfigure(c) == Configurator.ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY)
return;
}
}

long startJoranConfiguration = System.currentTimeMillis();
Configurator.ExecutionStatus es = attemptConfigurationUsingJoranUsingReflexion(classLoader);
private Configurator instantiateConfiguratorByClassName(String configuratorClassName, ClassLoader classLoader) {
try {
Class<?> classObj = classLoader.loadClass(configuratorClassName);
return (Configurator) classObj.getConstructor().newInstance();
} catch (ReflectiveOperationException e) {
contextAware.addInfo("Instantiation failure: " + e.toString());
return null;
}
}

if (es == Configurator.ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY) {
printDuration(startJoranConfiguration, JORAN_CONFIGURATION_DURATION_MSG, true);
return;
/**
*
* @param configurator
* @return true if enclosing loop should break, false otherwise
*/
private Configurator.ExecutionStatus invokeConfigure(Configurator configurator) {
try {
long start = System.currentTimeMillis();
contextAware.addInfo("Constructed configurator of type " + configurator.getClass());
configurator.setContext(loggerContext);
Configurator.ExecutionStatus status = configurator.configure(loggerContext);
printDuration(start, configurator, status);
return status;

} catch (Exception e) {
throw new LogbackException(String.format("Failed to initialize or to run Configurator: %s",
configurator != null ? configurator.getClass().getCanonicalName() : "null"), e);
}
printDuration(startJoranConfiguration, JORAN_CONFIGURATION_DURATION_MSG, false);
}

// at this stage invoke basicConfigurator
fallbackOnToBasicConfigurator();
private void printConfiguratorOrder(List<Configurator> configuratorList) {
contextAware.addInfo("Here is a list of configurators discovered as a service, by rank: ");
for(Configurator c: configuratorList) {
contextAware.addInfo(" "+c.getClass().getName());
}
contextAware.addInfo("They will be invoked in order until ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY is returned.");
}

private void printDuration(long start, String message, boolean success) {
private void printDuration(long start, Configurator configurator, Configurator.ExecutionStatus executionStatus) {
long end = System.currentTimeMillis();
long configurationAsAServiceDuration = end - start;
contextAware.addInfo(message+configurationAsAServiceDuration + " milliseconds. Success status="+success);
long diff = end - start;
contextAware.addInfo( configurator.getClass().getName()+".configure() call lasted "+diff + " milliseconds. ExecutionStatus="+executionStatus);
}

private Configurator.ExecutionStatus attemptConfigurationUsingJoranUsingReflexion(ClassLoader classLoader) {
Expand All @@ -122,68 +158,28 @@ private Configurator.ExecutionStatus attemptConfigurationUsingJoranUsingReflexio

}

private void fallbackOnToBasicConfigurator() {
BasicConfigurator basicConfigurator = new BasicConfigurator();
basicConfigurator.setContext(loggerContext);
basicConfigurator.configure(loggerContext);
}

// private void sortByPriority(List<Configurator> configuratorList) {
// configuratorList.sort(new Comparator<Configurator>() {
// @Override
// public int compare(Configurator o1, Configurator o2) {
// if (o1.getClass() == o2.getClass())
// return 0;
// if (o1 instanceof DefaultJoranConfigurator) {
// return 1;
// }
//
// // otherwise do not intervene
// return 0;
// }
// });
// }

Comparator<Configurator> rankComparator = new Comparator<Configurator>() {
@Override
public int compare(Configurator c1, Configurator c2) {

ConfiguratorRank r1 = c1.getClass().getAnnotation(ConfiguratorRank.class);
ConfiguratorRank r2 = c2.getClass().getAnnotation(ConfiguratorRank.class);

ConfiguratorRank.Value value1 = r1 == null ? ConfiguratorRank.Value.REGULAR : r1.value();
ConfiguratorRank.Value value2 = r2 == null ? ConfiguratorRank.Value.REGULAR : r2.value();
int value1 = r1 == null ? ConfiguratorRank.DEFAULT : r1.value();
int value2 = r2 == null ? ConfiguratorRank.DEFAULT : r2.value();

int result = compareRankValue(value1, value2);
// reverse the result for high to low sort
return (-result);
}
};

private int compareRankValue(ConfiguratorRank.Value value1, ConfiguratorRank.Value value2) {

switch (value1) {
case FIRST:
if (value2 == ConfiguratorRank.Value.FIRST)
return 0;
else
return 1;
case REGULAR:
if (value2 == ConfiguratorRank.Value.FALLBACK)
return 1;
else if (value2 == ConfiguratorRank.Value.REGULAR)
return 0;
else
return -1;
case FALLBACK:
if (value2 == ConfiguratorRank.Value.FALLBACK)
return 0;
else
return -1;

default:
private int compareRankValue(int value1, int value2) {
if(value1 > value2)
return 1;
else if (value1 == value2)
return 0;
}
else return -1;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@
/**
* @since 1.3.0-beta1
*/
@ConfiguratorRank(value = ConfiguratorRank.Value.REGULAR)
// Note that DefaultJoranConfigurator is invoked via reflection
@ConfiguratorRank(value = ConfiguratorRank.NOMINAL)
public class DefaultJoranConfigurator extends ContextAwareBase implements Configurator {

final public static String AUTOCONFIG_FILE = "logback.xml";
final public static String TEST_AUTOCONFIG_FILE = "logback-test.xml";

@Override
public ExecutionStatus configure(Context context) {
URL url = performMultiStepConfigurationFileSearch(true);
Expand All @@ -37,7 +35,7 @@ public ExecutionStatus configure(Context context) {
} catch (JoranException e) {
e.printStackTrace();
}
// we tried and that counts Mary.
// You tried and that counts Mary.
return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
} else {
return ExecutionStatus.INVOKE_NEXT_IF_ANY;
Expand All @@ -51,12 +49,12 @@ private URL performMultiStepConfigurationFileSearch(boolean updateStatus) {
return url;
}

url = getResource(TEST_AUTOCONFIG_FILE, myClassLoader, updateStatus);
url = getResource(ClassicConstants.TEST_AUTOCONFIG_FILE, myClassLoader, updateStatus);
if (url != null) {
return url;
}

return getResource(AUTOCONFIG_FILE, myClassLoader, updateStatus);
return getResource(ClassicConstants.AUTOCONFIG_FILE, myClassLoader, updateStatus);
}
public void configureByResource(URL url) throws JoranException {
if (url == null) {
Expand Down
1 change: 0 additions & 1 deletion logback-classic/src/main/java9/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
requires ch.qos.logback.core;
uses ch.qos.logback.core.spi.Configurator;
provides org.slf4j.spi.SLF4JServiceProvider with ch.qos.logback.classic.spi.LogbackServiceProvider;
provides ch.qos.logback.core.spi.Configurator with ch.qos.logback.classic.joran.SerializedModelConfigurator;

exports ch.qos.logback.classic;
exports ch.qos.logback.classic.boolex;
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion logback-classic/src/test/input/joran/model/minimal.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<configuration debug="false">

<serializeModel file="${target.smo}"/>
<serializeModel file="${targetModelFile}"/>

<logger name="ModelSerializationTest" level="DEBUG"/>
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package ch.qos.logback.classic.joran;

import ch.qos.logback.classic.AsyncAppender;
import ch.qos.logback.classic.ClassicConstants;
import ch.qos.logback.classic.ClassicTestConstants;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
Expand Down Expand Up @@ -728,7 +729,7 @@ public void dateConverterWithLocale() throws JoranException {
public void modelSerialization() throws JoranException, IOException, ClassNotFoundException {
String outputPath = OUTPUT_DIR_PREFIX+"minimal_"+diff+ MODEL_CONFIG_FILE_EXTENSION;

loggerContext.putProperty("target.smo", outputPath);
loggerContext.putProperty("targetModelFile", outputPath);
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "model/minimal.xml");
StatusPrinter.print(loggerContext);

Expand All @@ -747,13 +748,13 @@ public void modelSerialization() throws JoranException, IOException, ClassNotFou
assertEquals(2, configurationModel.getSubModels().size());

SerializeModelModel smm = (SerializeModelModel) configurationModel.getSubModels().get(0);
assertEquals("${target.smo}", smm.getFile());
assertEquals("${targetModelFile}", smm.getFile());


LoggerModel loggerModel = (LoggerModel) configurationModel.getSubModels().get(1);
assertEquals("ModelSerializationTest", loggerModel.getName());

// <serializeModel file="${target.smo}"/>
// <serializeModel file="${targetModelFile}"/>
// <logger name="ModelSerializationTest" level="DEBUG"/>


Expand Down

0 comments on commit 54c23fe

Please sign in to comment.