Using multiple loggers on a single appender

2019-07-25 21:44发布

问题:

Below is my logging configuration. It is logging exactly what I want, but it is only logging it to a file. I would like to see the same information on the console. I have tried several variations, but with every variation I can only get the information logged to either the console or a file, not both.

    def appName = grails.util.Metadata.current.'app.name'
    def catalinaBase = System.properties.getProperty('catalina.base')
    catalinaBase = catalinaBase ?: "."
    def logDirectory = "${catalinaBase}${File.separator}logs${File.separator}${appName}"

    // log4j configuration
    log4j = {
        appenders {
            rollingFile name: 'stdout',     file: "${logDirectory}${File.separator}${appName}.log".toString(), maxFileSize: '100MB' // Use the same file for stdout and stacktrace
            rollingFile name: 'stacktrace', file: "${logDirectory}${File.separator}${appName}.log".toString(), maxFileSize: '100MB' // Use the same file for stdout and stacktrace
        }

        warn   'org.codehaus.groovy.grails.web.servlet',        // controllers
               'org.codehaus.groovy.grails.web.pages',          // GSP
               'org.codehaus.groovy.grails.web.sitemesh',       // layouts
               'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
               'org.codehaus.groovy.grails.web.mapping',        // URL mapping
               'org.codehaus.groovy.grails.commons',            // core / classloading
               'org.codehaus.groovy.grails.plugins',            // plugins
               'org.codehaus.groovy.grails.orm.hibernate',      // hibernate integration
               'org.springframework',
               'org.hibernate',
               'net.sf.ehcache.hibernate'

        all    'grails.app.controllers.test',
               'grails.app.domain.test',
               'grails.app.services.test',
               'grails.app.taglib.test',
               'grails.app.conf.test',
               'grails.app.filters.test'
    }

回答1:

Firstly, having two different appenders that log to the same file is a bad idea, if you want the full stacktraces to go to the same place as the normal logs then you should re-point things at the logger level rather than the appender level.

For your actual problem, I would create a console appender and a single file appender, and attach them both to the root logger.

log4j = {
  appenders {
    console name:'stdout'
    rollingFile name: 'applog',     file: "${logDirectory}${File.separator}${appName}.log".toString(), maxFileSize: '100MB'
    'null' name:'stacktrace' // prevent Grails trying to create stacktrace.log
  }

  root {
    warn 'stdout', 'applog'
  }

  // Send full stack traces to the main appName.log file
  warn applog:'StackTrace'

  // individual warn/all logger configurations as before
}

This will send the same logs to stdout and to the log file, but will only send full stack traces to the file (not to the console). If you really do want the full stack traces on the console too then change it to

  warn applog:'StackTrace', stdout:'StackTrace'

Alternatively, you might consider disabling the StackTrace logger altogether (remove the whole warn applog:'StackTrace' line) and then also disabling stack trace filtering by setting the system property grails.full.stacktrace to true so you get full unfiltered stack traces recorded by the normal loggers.



回答2:

With your configuration above, for exmaple, to have all INFO-level 'grails.app' events log to console and your 'stdout' appender, you'd want something like the following:

log4j = {
   appenders { 
     ... appender configuration here ...
   }
   // configure a root logger
   root {
     warn 'stdout'
     additivity = false
   }

   info stdout:'grails.app'
   info console:'grails.app'

}


标签: grails log4j