I like the first syntax with the map-like API. About Ralph’s concern, would it not be possible for the DSL to create actual Appender and Layout objects? What prevents us from doing this?
Remko > On May 4, 2019, at 3:25, Matt Sicker <[email protected]> wrote: > > Second example was a typo it looks like. > > On Fri, May 3, 2019 at 12:57, Ralph Goers <[email protected]> > wrote: > >> My only concern is that people might be expecting a DSL to create the >> actual Appenders, Layouts, etc. where this will just be creating >> configuration Nodes. That said, I don’t have a problem with it. I am not >> sure that your second example is valid since you are declaring an appender >> without an appenders node. The first syntax looks more concise to me. >> >> Ralph >> >>> On May 3, 2019, at 10:08 AM, Matt Sicker <[email protected]> wrote: >>> >>> 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]> >>> >> >> >> -- > Matt Sicker <[email protected]>
