Moving to Grails

Changing log level at run-time

Sometimes you need to change log-level for parts of your application at run-time. Most likely for debugging.

When researching this topic I found a useful trait that logs log-level.

package no.prpr

trait LogHelper {

    void log() {
        String simpleName = this.class.simpleName

        log.error ">>> ${simpleName} error message"
        log.warn ">>> ${simpleName} warn message" ">>> ${simpleName} info message"
        log.debug ">>> ${simpleName} debug message"
        log.trace ">>> ${simpleName} trace message"


With this I created a LogLevel controller to visualize and manipulate log-levels:

package no.prpr

import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import ch.qos.logback.classic.LoggerContext
import org.slf4j.LoggerFactory

class LogLevelController implements LogHelper {

    def index() {

        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        def loggerList = context.getLoggerList().findAll() { logger ->
        def loggerNames = loggerList*.name
        def logLevels = new LinkedHashMap<>()
        loggerList.each { logger ->
            logLevels.put(, [level: logger.level, effectiveLevel: logger.effectiveLevel])
        def logLevelList = []
        respond logLevelList, model: [loggers: loggerNames, logLevels: logLevels]
    def update() {
        log.debug("logLevel: ${params['level']}")
        log.debug("logger: ${params['logger']}")
        Logger logger = LoggerFactory.getLogger(params['logger'])

        redirect action: 'index'


The loggerList variable gets very long if not filtered.

Here’s the logLevel/index.gsp:

<!doctype html>
    <meta name="layout" content="main"/>
    <title>Welcome to Grails</title>

<div id="content" role="main">
    <section class="row colset-2-its">
        <h1>LogLevel controller</h1>
    <div  >
        loggerList: ${loggers}
        logLevels: ${logLevels}
    <g:form action="update">
        Logger: <g:select name="logger" from="${loggers}"></g:select>
        LogLevel: <g:select name="level" from="['DEBUG', 'INFO', 'TRACE']"></g:select>
        <input class="save" type="submit" value="Set loglevel"  />


It seems to update immediately.

Beware that depending on other settings logback can update from configuration-file at interval.