Search code examples
tomcatgrailslog4j

Why is Grails (in Tomcat) logging to both catalina.out and my custom file appender?


I have the following for my log4j DSL configuration in Grails 1.2:

log4j = {
    appenders {
        console name: 'stdout', layout: pattern(conversionPattern: conversionPattern)

        environments {
            production {
                // ... some code to determine file path ...

                rollingFile name: 'file', file: "${logDirectory}/${appName}.log", layout: pattern(conversionPattern: conversionPattern)
                rollingFile name: 'StackTrace', file: "${logDirectory}/${appName}-stacktrace.log"
        }
    }

    environments {
        development { root { warn 'stdout' } }
        test { root { warn 'stdout' } }
        production { root { error 'file' } }
    }

    // ... package-specific logging configurations ...
}

When I deploy as a war to Tomcat, my logs get written to both catalina.out and my 'file' logger defined for production.

I've tried:

  • adding additivity = false to the root {} definition for production {}, which doesn't work (and I wouldn't really expect it to, since it's apparently setting additivity for the root logger itself?).
  • defining the 'stdout' console appender inside of a development {} and test {} block within the appenders {} closure, but that doesn't work either.

Perhaps this is an issue with my Tomcat configuration and not my log4j DSL? The closest I've come to finding someone with a similar issue is this mailing-list thread, for which there was no (simple) solution.

How can I prevent logs from being written to catalina.out in production?


Solution

  • I was able to work around the issue by doing the following in Config.groovy:

    import org.apache.log4j.Logger
    
    log4j = {
        // ... configuration from question ...
    }
    
    environments {
        production {
            def logger = Logger.getRootLogger()
            logger.removeAppender('stdout')
        }
    }
    

    However, this feels like a dirty hack, and I'm hoping there's a better, Grails log4j DSL-specific way to do this.

    Also, anything the application might happen to write to stdout will probably not get written, which might be a bad thing if there are logs/exceptions/stacktraces being somehow written directly to stdout.