[logback-dev] Concerning Logback's Groovy Configuration API

Добрынин Дмитрий dobrynya at inbox.ru
Tue Jun 29 17:15:45 CEST 2010


Hi all

I've read the documentation on Logback's Groovy Configuration API and found that API is not concise and convenient as it can be. I would like to explain my thoughts.

1) There is no need to use string literals to identify appenders. Configuring an appender in a closure mainly takes several lines of code, a better idea is to use groovy map literal to specify appender's parameters.

For example:

appender myAppender, [class: FileAppender, file: "myComponent.log", append: true, encoder: encoder(class: PatternEncoder, pattern: "%m%n" ]

appender myConsole // configuring an appender with default settings such as ConsoleAppender etc

// or excluding square brackets, but name of the appender is specified right in the parameter's map
appender name: myAppender, class: FileAppender, file: "myComponent.log", append: true, encoder: patternEncoder("%m%n") 
// here convenient method patternEncoder is used to avoid specifying the encoder's class

2) Loggers can refer appenders by name, no need to use strings. There is no need to use list literal to specify a collection of appenders, just using varargs.

   logger com.myorg.myapp.mypackage, INFO, myAppender
   logger com.myorg.myapp.mypackage.subpackage, DEBUG, false, myAppender, myConsole

   In the last statement also additivity flag is specified.

   logger root, INFO, myApp // configuring the root logger is achieved with the same API
                                                                                                          In my opinion this DSL is looking more naturally and clearer. All statements take one line. If convenient functions for creating encoders and other components is provided it would be easy-to-use configuration API. In the rest of this letter I've added sample code to show how it can be implemented. Hope this is useful.

Best regards,
Dmitry


Here is logging configuration in method config.

package org.logger
import org.junit.Test
import org.apache.log4j.*
import static org.apache.log4j.Level.*

/**
 * Configuration API
 * @author Dmitry Dobrynin
 * Created 28.06.2010 16:35:45
 */
class GrTest {
  Map<String, Logger> loggers = [:]
  Map<String, Appender> appenders = [:]

  @Before
  void config() {
    appender myApp, [class: FileAppender, file: "myLog.log", encoder: encoder()]
    appender oneMoreAppender
    logger root, INFO, myApp
    logger org.nomin, DEBUG, false, myApp, oneMoreAppender
  }

  @Test
  void test() {
    getLogger(org.logger).info "Loggers work! "
    getLogger(GrTest).info "Found logger by class!"
    getLogger(List).info "Found logger by class!"
  }

  def propertyMissing(String name) {
    appenders[name] ?: loggers[name] ?: new Name(name: name, config: this)
  }

  def encoder(params = null) {}

  Logger getLogger(loggerName) {
    switch (loggerName) {
      case String: return loggers[loggerName]
      case Name: return loggers[loggerName.toString()]
      default: throw new Exception("Undefined logger ${loggerName}!"
    }
  }

  Logger getLogger(Class clazz) { loggers.find { clazz.name.startsWith(it.key) }?.value ?: loggers["root"] }

  Logger logger(Name name, Level level, boolean additivity = true, Appender... appenders) {
    loggers[name.toString()] = new Logger(additivity: additivity, appenders: appenders.collect { it })
  }

  Appender appender(Name name, Map params = [:]) {
    appenders[name.toString()] = new Appender(name: name.toString(), appenderClass: params.class ?: ConsoleAppender)
  }

  static class Logger {
    def name
    def additivity = true
    def appenders = []
    void info(message) { appenders.each { it.append("${name}: ${message}" }}
  }

  static class Appender {
    String name
    Class appenderClass
    void append(message) { println("${name}:${appenderClass?.name}: ${message}" }
  }
}

class Name {
    String name
    Name prev
    def config
    def propertyMissing(String name) { new Name(name: name, prev: this) }
    String toString() { prev ? "${prev.toString()}.${name}" : name }
}


More information about the logback-dev mailing list