how to log runtime errors in grails - grails

I am trying to debug a simple problem with saving my domain object.
class AppRideOfferController {
def index() {}
def create() {
if(params.fromAddr && params.toAddr && params.preferences && params.startDate) {
RideOffer rideOffer = new RideOffer(startLocation: params.fromAddr, endLocation: params.toAddr, startDateTime: new Date(Integer.parseInt((String) params.startDate)));
rideOffer.save(flush: true);
//assert(rideOffer.id);
log.info("blah");
render(contentType:"text/json") {
result(blah: rideOffer)
};
}
}
}
In the above code, I am simply creating a domain object, saving it, and returning it as json with the generated id in it. However, if I uncomment the asset statement, it fails because id is not set.
I do not get any error on the console, so I wonder how do I get runtime error stacktraces onto the stdout? My Config.groovy's log4j configuration looks like this:
log4j = {
// Example of changing the log pattern for the default console appender:
//
appenders {
console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
}
info 'grails.app.controllers',
'grails.app.controller',
'grails.app';
error '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'
}

If your code generates a runtime error, you will see the error.gsp view. In the documentation you can see that the save() will not produce an exception, but populate errors that can happen in the validation of your domain class. If you generate your controller you will see how you can handle errors in the save method.
Something like:
def save() {
if(!instance.save(flush:true)) {
//instance fails in validation, you need to respond those errors
Locale locale = RequestContextUtils.getLocale(request) //Locale of the user
render([success: false, errors: errorsToMap(instance.errors, locale)]) as JSON
} else {
render([success: true, record: instance]) as JSON
}
}
//just a helper to format the errors output
private List<Map> errorsToMap(Errors errors, Locale locale) {
def error = []
for(def err : errors.allErrors) {
if(err instanceof FieldError) {
error << [id: err.field, msg: Holders.grailsApplication.mainContext.getMessage(err, locale)]
}
}
return error
}
Holders, JSON and RequestContextUtils are available by default.

Try replacing rideOffer.save(flush: true); with rideOffer.save(flush: true, failOnError:true); and you should see errors in console

Related

Configuring log4j grails

I'm new in grails and I need to configuring loggind for my application. I started to configure log4j in my grails application and I got this error described below and I don't know what makes this:
log4j:ERROR Property missing when configuring log4j: Environment
Someone know what causes it? Below is my code!
def myappLogLevel = "DEBUG"
def myappLogPattern = "%d{yyyy-MM-dd/HH:mm:ss.SSS} [%t] %x %-5p %c{2} -
%m%n"
def log4jFileName = System.properties.getProperty('catalina.base', '.') +
"/logs/myapp.log"
environments {
development {
log4jFileName = "logs/myapp.log"
}
test {
log4jFileName = "logs/myapp.log"
}
log4j = {
def logLayoutPattern = new PatternLayout(myappLogPattern)
appenders {
appender new DailyRollingFileAppender(name: "myappLog",
threshold: Level.toLevel(myappLogLevel),
file: log4jFileName,
datePattern: "'.'yyyy-MM-dd", //Rollover at midnight each day.
layout: logLayoutPattern
)
if (Environment.current == Environment.DEVELOPMENT ||
Environment.current == Environment.TEST) {
appender new ConsoleAppender(name: "console",
threshold: Level.toLevel(myappLogLevel),
layout: logLayoutPattern
)
}
}
error '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
'org.springframework',
'org.hibernate.cache',
'org.hibernate',
'net.sf.ehcache.hibernate'
'grails'
'groovyx.net.http'
warn 'org.springframework',
'org.hibernate',
'grails.plugins.springsecurity',
'groovyx.net.http'
debug 'grails.plugins.springsecurity',
'grails.plugin.springcache',
'com.myapp',
'org.codehaus.groovy.grails.plugins.springsecurity',
'org.apache.http.headers',
'grails.app.services',
'grails.app.domain',
'grails.app.controllers',
'grails.plugin.databasemigration',
'liquibase'
List<String> loggers = []
loggers.add('myappLog')
if (Environment.current.name == "development" ||
Environment.current.name == "test") {
loggers.add('console')
}
root {
error loggers as String[]
additivity = true
}
}
You may be able to use the log config DSL construction to branch on environment without explicitly accessing Environment.
environments {
development { loggers.add('console') }
test { loggers.add('console') }
}
That said, I am not sure what you are trying to accomplish with the rest of the configuration, so there may be a more elegant way to handle things.

Debug statements aren't showing src/groovy classes

I have the following in my config.groovy
// default for all environments
log4j = { root ->
appenders {
rollingFile name:'stacktrace', file:"${logDirectory}/app_stack.log".toString(), maxFileSize:'100KB'
}
error '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'
debug 'com.my.code'
root.level = org.apache.log4j.Level.INFO
}
I get debug statements printed to the logs for all classes except for my groovy files placed in package com.my.code I don't get the debug statements printed. Only the info statements are being printed to the log.
Here is an example for one of the groovy classes in src/groovy
#Log4j
class SomeTest {
def someMethod() {
log.info("This will print")
log.debug("This will not print")
println log.isDebugEnabled() //prints false
print log.isInfoEnabled() //prints true
}
}
Question
How can I turn on debugging for all class under package com.my.code ? I'm on grails 2.3.5. When I change root.level to org.apache.log4j.Level.DEBUG then the debug statements do show up but that turns on DEBUG for ALL other classes as well
Here's a configuration that will log all code in packages com.my.code at the DEBUG level, and all other packages at the ERROR level.
The logs will be sent to the console and a file named appLog.txt.
log4j = {
appenders {
def logPattern = '%d{dd-MM-yyyy HH:mm:ss,SSS} %5p %c{2} - %m%n'
console name: 'consoleAppender', layout: pattern(conversionPattern: logPattern)
file name: "fileAppender", file: "appLog.txt"
}
root {
// define the root logger's level and appenders, these will be inherited by all other loggers
error 'consoleAppender', 'fileAppender'
}
def appNamespaces = [
'com.my.code',
'grails.app.conf.com.my.code',
'grails.app.filters.com.my.code',
'grails.app.taglib.com.my.code',
'grails.app.services.com.my.code',
'grails.app.controllers.com.my.code',
'grails.app.domain.com.my.code'
]
appNamespaces.each { debug it }
}
In grails 2.x apps I used next format (with regards to your config):
debug rollingFile 'com.my.code'
Furthermore, if you need to set different log level for a bunch of packages:
debug rollingFile: ['com.example','com.otherpackage']

logger in Grails always report wrong method and line number

I use Grails 2.4.4 and Oracle JDK 1.7.45
The below is my logger configuration in Config.groovy:
log4j.main = {
appenders {
console name:'stdout', layout:pattern(conversionPattern: '%d{yy/MM/dd HH:mm:ss.SSS} %p %c{1}.%M(%L): %m%n')
}
error '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'
debug 'grails.app'
}
My controller is :
class HomeController {
def index() {
log.debug("HELLO, WORLD")
render "HELLO, WORLD"
}
}
The log result looks like below:
15/04/08 13:15:26.723 DEBUG HomeController.debug(128) : HELLO, WORLD
How do I config Config.groovy so that the log result can correctly display method and line number like below:
15/04/08 13:15:26.723 DEBUG HomeController.index(3) : HELLO, WORLD

Prevent specific exceptions loggin in Grails

In grails I want to stop logging some specific exceptions occouring in my controllers.
I have managed this exception with urlmapping to render a custome warning page
Es my url mapping
"500"(controller:'error', action:'excOne', exception: MyExceptionOne)
"500"(controller:'error', action:'excTwo', exception: MyExceptionTwo)
But this exceptions continued to be logged by log4j. How I can exclude them from logging?
This is my log4j config:
log4j = {
error '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.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',
'grails.app.services.org.grails.plugin.resource',
'grails.app.taglib.org.grails.plugin.resource',
'grails.app.resourceMappers.org.grails.plugin.resource',
'grails.app.services.NavigationService'
warn 'org.mortbay.log'
debug "com.myproject.*"
debug "grails.app"
debug "com.myproject.*"
appenders {
console name:'stdout', layout:pattern(conversionPattern: '[%r] %c{2} %m%n')
}
root {
error 'stdout'
warn 'stdout'
additivity = true
}
}
I have not managed to remove all mentions of the exception in the log, but what I have done is I prevented the stack trace from cluttering up the logs:
Create a StackTracePrinter implementation that behaves the way you want.
package com.myStuff
import org.codehaus.groovy.grails.exceptions.DefaultStackTracePrinter
class MyStackTracePrinter extends DefaultStackTracePrinter {
String prettyPrint(Throwable throwable) {
if (throwable instanceof MyException) return "<stack trace suppressed>"
return super.prettyPrint(throwable)
}
}
Then, in Config.groovy:
grails.logging.stackTracePrinterClass = 'com.myStuff.MyStackTracePrinter'
Try:
off "your.class.file"
After the line of code:
debug "com.myproject.*"
Just make sure you provide correct path of your class, let me know the class file path if this doesn't work?

Grails not printing messages to log file using custom appender

My Grails application is going to mirgate an existing database to a new database. I got some unformatted email addresses from the existing database which do not pass validation with my Grails application because of a constraint (email:true), so I get a field error.
I want write these field errors in a log file. How can I do that? I tried a Appender in log4J. It will somehow create a log file so-call "migration.log", but it does not write any field error into this log file.
log4j = {
// Example of changing the log pattern for the default console
// appender:
//
appenders {
// console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
appender new FileAppender(
name: "migrationAppender",file : "migration.log", layout: pattern(conversionPattern: "%c{2} %m%n")
)
}
This is configration. I define a FileAppender.
In my service. I just call the following:
def foundation = new Foundation(name: name, foundationName: foundationName).addToAddresses(address).addToCommunicationMedia(email)
foundation.validate()
if (!foundation.hasErrors()) {
foundation.save(flush: true)
}
else {
log.error "${foundation.errors}"
}
In the console, the errors occur and I saw a "migration.log" has been created, but somehow the file in empty.
Error 2011-09-26 09:00:29,543 [main] ERROR service.MasterDataMigrationService - org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'de.rvgmbh.nemesis.migration.domain.partner.participant.IndividualPerson' on field 'communicationMedia[0].address': rejected value [erbelrechtsanwalt-eberl.de];
log4j = {
appenders {
rollingFile name:"file", maxFileSize:(1024*1024), file:"migration.log", maxBackupIndex:10
environments {
development {
console name:'stdout'
}
}
}
error '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'
warn 'org.mortbay.log'
environments {
development {
root {
info 'file', 'stdout'
}
debug 'grails.app'
}//development
test {
root {
info 'file'
}
info 'grails.app'
}
production {
root {
info 'file'
}
info 'grails.app'
}
}
}
dev: logs to console and file from debug level
test: logs to file from info level
prod: logs to file from info level

Resources