Grails: log stacktrace to stdout

2019-04-01 11:21发布

问题:

When I launch my grails application, I get the following error:

java.io.FileNotFoundException: stacktrace.log (Permission denied)

I know this can be solved by chowning some files/directories or by changing the file the logs go to, but I don't want this: I just want stracktraces to be logged to the stdout.

The documentation states:

For example if you prefer full stack traces to go to the console, add this entry:

error stdout: "StackTrace"

However: it also states:

This won't stop Grails from attempting to create the stacktrace.log file - it just redirects where stack traces are written to.

And later:

or, if you don't want to the 'stacktrace' appender at all, configure it as a 'null' appender:

log4j = {
    appenders {
        'null' name: "stacktrace"
    }
}

I combine the 2 and get the following configuration:

// log4j configuration
environments {
    production {
        log4j = {
            appenders {
                console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
                // Don't use stacktrace.log
                'null' name: "stacktrace"
            }
        }

    }
}

log4j = {
    // print the stacktrace to stdout
    error stdout:"StackTrace"
}

Unfortunately, this doesn't work:

INFO: Deploying web application archive MyBackend.war

Sep 12, 2012 4:46:11 PM org.apache.catalina.core.StandardContext start

SEVERE: Error listenerStart

Sep 12, 2012 4:46:11 PM org.apache.catalina.core.StandardContext start

SEVERE: Context [/MyBackend2] startup failed due to previous errors

Admittedly, it doesn't attempt to write stacktrace.log anymore, so the Permission denied error isn't thrown anymore, but I have no clue why the app won't start becaue the only thing it logs is "Error listenerStart"

Can anyone please help me with configuring my app to just log the stacktraces to stdout?

回答1:

Grails Bug report: http://jira.grails.org/browse/GRAILS-2730 (contains some workarounds)

If you want stacktraces to stdout:

log4j = {
  appenders {
    console name:'stacktrace'
    ...
  }
...
}

Disable stacktrace.log:

log4j = {
  appenders {
    'null' name:'stacktrace'
    ...
  }
...
}

stacktraces to application specific log file in Tomcat logs directory

log4j = {
  appenders {
    rollingFile name:'stacktrace', maxFileSize:"5MB", maxBackupIndex: 10, file:"${System.getProperty('catalina.home')}/logs/${appName}_stacktrace.log", 'append':true, threshold:org.apache.log4j.Level.ALL
    ...
  }
...
}

kudos to this blog post: http://haxx.sinequanon.net/2008/09/grails-stacktracelog/



回答2:

Here is what I have to deal with this:

log4j = {
    appenders {
        // Be smart if we are running in tomcat or not 
        String logDir = Environment.warDeployed ? 
                System.getProperty('catalina.home') + '/logs' : 
                'target'

        // Handle the stacktrace log correctly
        rollingFile name:'stacktrace',
                maxFileSize: "5MB",
                maxBackupIndex: 10,
                file: "${logDir}/${appName}_stacktrace.log",
                layout: pattern(conversionPattern: "'%d [%t] %-5p %c{2} %x - %m%n'"),
                'append': true,
                threshold: org.apache.log4j.Level.ALL
    }
}

This lets us gracefully handle being deployed as a WAR in Tomcat, as well as in development. It also has the advantage of allowing multiple grails applications to run within the same container without mushing all of their stacktrace logs together.

Inspiration for this comes from @FlareCoder's answer above, as well as from @BurtBeckwith's mailing list post.