Logback-tyler translates logback-classic XML configuration files into Java.
The resulting java class named TylerConfigurator
implements the
Configurator
interface. It can thus be declared as a custom configuration provider
using Java's standard
service-provider
meachanism. Custom configurators are searched by looking up a provider-configuration file
resource located under the
META-INF/services/ch.qos.logback.classic.spi.Configurator file in
your project. This provider-configuration should contain a line with the fully
qualified class name of your desired configurator.
Running TylerConfigurator
does not require XML parsers and usually
executes noticeably faster than JoranConfigurator
, logback's XML
configurator. Moreover, TylerConfigurator
does not use
reflection. In addition, given that it ships with your project's
binaries, it is harder to modify and offers an even smaller attack
surface.
At runtime, TylerConfigurator
does not have any additional
dependencies other than logback-classic version 1.5.10.
A instance of logback-tyler translator is available online. Do not hesitate to experiment with it.
Logback-tyler is located at the following Maven coordinates:
<groupId>ch.qos.logback.tyler</groupId>
<artifactId>tyler-base</artifactId>
<version>0.9</version>
Here is a sample program to translate a logback.xml as string into Java.
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.model.Model;
import ch.qos.logback.core.util.StatusPrinter;
import java.io.IOException;
public class TylerExample {
String xmlInput =
"""
<configuration debug="true">
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<property name="APP_NAME" value="myApp"/>
<contextName>${APP_NAME}</contextName>
<appender class="ch.qos.logback.core.FileAppender" name="TOTO">
<file>toto.log</file>
<append>true</append>
<immediateFlush>true</immediateFlush>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="TOTO"/>
</root>
</configuration>
""";
public static void main(String[] args) throws JoranException, IOException {
ContextBase context = new ContextBase();
ModelToJava m2j = new ModelToJava(context);
Model model = m2j.extractModel(xmlInput);
String result = m2j.toJava(model);
System.out.println(result);
// print any error messages occuring during the translation
StatusPrinter.print(context);
}
}
running the above program will produce the following output
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.Configurator;
import ch.qos.logback.classic.tyler.TylerConfiguratorBase;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.joran.spi.NoAutoStartUtil;
import ch.qos.logback.core.spi.ContextAware;
import ch.qos.logback.core.spi.LifeCycle;
import java.lang.Override;
/**
*
* <p>This file was generated by logback-tyler version 0.9.</p>
*
* <p>Eventual errors and warnings are appended at the end.</p>
*
* <p>You may experiment with logback.xml to Java translation, i.e.
* TylerConfigurator generation, at the following URL:</p>
*
* <p> https://logback.qos.ch/translator/services/xml2Java.html </p>
*
* <p>This generated TylerConfigurator class is intended to be copied and integrated
* into the user's project as a custom configurator. It will configure logback
* without XML. You are free to rename TylerConfigurator as you wish.</p>
*
* <p>It requires logback-classic version 1.5.11 or later at runtime.</p>
*
* <p>Custom configurators are looked up via Java's service-provide facility. If a
* custom provider is found, it takes precedence over logback's own configurators,
* e.g. DefaultJoranConfigurator.</p>
*
* <p>To install your custom configurator to your project, add a
* provider-configuration file to the following path:</p>
*
* <pre> META-INF/services/ch.qos.logback.classic.spi.Configurator</pre>
*
* <p>This provider-configuration file should contain a line with the fully
* qualified class name of your tyler configurator.</p>
*
* <p>See also item 1 of 'Configuration at initialization' section at </p>
*
* <p> https://logback.qos.ch/manual/configuration.html#auto_configuration</p>
*
* <p>With recent versions of logback and logback-tyler you can still
* configure logger levels dynamically using properties files. Note that
* configuration files in properties format can be watched for
* changes. See the documentation on PropertiesConfigurator for more details.</p>
*
* <p>https://logback.qos.ch/manual/configuration.html#propertiesConfigurator</p>
*
* <p>Keep in mind that by integrating a .properties configuration file info
* your tyler configurator, you can still change logger levels dynamically, without
* redeploying your application.</p>
*
*/
class TylerConfigurator extends TylerConfiguratorBase implements Configurator {
/**
* <p>This method performs configuration per {@link Configurator} interface.</p>
*
* <p>If <code>TylerConfigurator</code> is installed as a configurator service, this
* method will be called by logback-classic during initialization.</p>
*/
@Override
public Configurator.ExecutionStatus configure(LoggerContext loggerCoontext) {
setContext(loggerCoontext);
addOnConsoleStatusListener();
propertyModelHandlerHelper.handlePropertyModel(this, "APP_NAME", "myApp", "", "", "");
setContextName(subst("${APP_NAME}"));
Appender appenderRFILE = setupAppenderRFILE();
logger_ROOT.addAppender(appenderRFILE);
Logger logger_ROOT = setupLogger("ROOT", "DEBUG", null);
return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
}
Appender setupAppenderRFILE() {
FileAppender appenderRFILE = new FileAppender();
appenderRFILE.setContext(context);
appenderRFILE.setName("RFILE");
appenderRFILE.setFile("toto.log");
appenderRFILE.setAppend(true);
appenderRFILE.setImmediateFlush(true);
// Configure component of type PatternLayoutEncoder
PatternLayoutEncoder patternLayoutEncoder = new PatternLayoutEncoder();
patternLayoutEncoder.setContext(context);
patternLayoutEncoder.setPattern("%-4relative [%thread] %-5level %logger{35} -%kvp- %msg%n");
patternLayoutEncoder.setParent(appenderRFILE);
patternLayoutEncoder.start();
// Inject component of type PatternLayoutEncoder into parent
appenderRFILE.setEncoder(patternLayoutEncoder);
appenderRFILE.start();
return appenderRFILE;
}
}
----------------
15:44:51,087 |-INFO in ch.qos.logback.tyler.base.handler.ImplicitModelHandler - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
15:44:51,092 |-INFO in ch.qos.logback.core.model.processor.DefaultProcessor@1f760b47 - End of configuration.