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 }
}
_______________________________________________
logback-dev mailing list
[email protected]
http://qos.ch/mailman/listinfo/logback-dev