I believe Ralph has brought up a feature request in the past, though I
don't remember where. Anyways, Logback has a Groovy DSL [1] as an
option to configure itself, and we could introduce a similar feature
built on top of the existing ConfigurationBuilder code from the Java
DSL in log4j-core. After seeing how easily Groovy integrates with Java
to form DSLs in Jenkins [2] (more so in the web framework than in
pipelines, but both are valid), I've been considering working on such
a feature.

Let's take a random configuration sample from the manual [3]:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
%logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="com.foo.Bar" level="trace">
      <AppenderRef ref="Console"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

If I were to translate this to the equivalent Groovy DSL, here is one
example of how that might look:

configuration(status: 'warn') {
  appenders {
    console(name: 'Console', target: 'SYSTEM_OUT') {
      patternLayout(pattern: '%d{HH:mm:ss.SSS} [%t] %-5level
%logger{36} - %msg%n')
    }
  }
  loggers {
    logger(name: 'com.foo.Bar', level: 'trace') {
      appenderRef(ref: 'Console')
    }
    root(level: 'error') {
      appenderRef(ref: 'Console')
    }
  }
}

An alternative syntax would be to switch from using method parameters
to properties of the closure. For example, that might look like:

configuration {
  status = 'warn'
  console {
    name = 'Console'
    target = 'SYSTEM_OUT'
    patternLayout {
      pattern = '%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n'
    }
  }
  // ...
}

Are there any preferences on syntax? I don't think we can get super
fancy with the DSL due to the underlying APIs (i.e., we can't provide
much in the way of code completion AFAIK), but supporting a dynamic
DSL like that is fairly easy with Groovy. This does open a question of
configuration being scripted versus declarative since we'd be offering
a full script engine technically in order to write your configuration.
I do not expect this feature to offer a programmatic way of
manipulating the underlying plugin objects (i.e., this would be for
building a Configuration, not manipulating a running one); that might
make more sense with a more standardized plugin API which is a
wishlist item I have for 3.0.

[1]: https://logback.qos.ch/manual/groovy.html
[2]: 
https://github.com/stapler/stapler/blob/master/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/JellyBuilder.java
[3]: https://logging.apache.org/log4j/2.x/manual/configuration.html

-- 
Matt Sicker <[email protected]>

Reply via email to