7
votes

I would like to log messages from one controller in my grails application at info level to a specific file. Everything else at info or any other level should go to another default logging file.

However, I cannot get log4J to populate the usage.log file at all, although it happily logs to the 'default' appender defined below.

Can anyone give any clues as to why my setup is not working?

My log4j setup is as follows:

log4j = {

appenders {

    console name: 'stdout', 
    layout: pattern(conversionPattern: '%d %-5p %c{1} - %m%n')

    appender new DailyRollingFileAppender(
            name: 'default', 
            datePattern: "'.'yyyy-MM-dd",
            layout: pattern(conversionPattern: '%d %-5p %c{1} - %m%n'),
            file: 'C:/logs/default.log'
         )

    //daily usage log
    appender new DailyRollingFileAppender(
            name: 'usage', datePattern: "'.'yyyy-MM-dd",
            layout: pattern(conversionPattern: '%d %-5p %c{1} - %m%n'),
            file: 'C:/logs/usage.log'
         )
}


info usage: "grails.app.controllers.com.example.MyController", 
additivity: false

root {
    info 'stdout', 'default'
    additivity = true
}

     info 'grails.app'
}

UPDATE

I have been able to solve this by replacing the specific controller class mapping with

info usage: 'usage', additivity: true

and then using

private static final log = LogFactory.getLog("usage")

No other documented or described way seems to work, and ideally I'd be able to configure it on a package or class basis, but this works.

1
I'm not sure whether it makes a difference but I always put the less specific logger definitions first and the more specific ones later (i.e. move the grails.app.controllers.... one after the grails.app one). What version of Grails are you using? - Ian Roberts
I'm using 2.1.0. Sadly, moving the logger definitions makes no difference. I still get all my log messages in the default appender file, and nothing in the usage appender file. - user1740752
That's definitely the right syntax so it should work unless you've overridden the log4j closure in an environments block or an external config file. - Ian Roberts
Thanks for your suggestions guys. Unfortunately, I still see no log messages in the usage appender file at all, everything goes into default. I tried changing root to include the usage appender, but then everything from info level or above goes into the usage log, which isn't what I want at all. - user1740752
Weird. Try putting System.out.println(log.name) into an action of your controller, to confirm that it's using the logger you think it's using. - Ian Roberts

1 Answers

2
votes

You need to be careful with the named parameter types that info et. al. expects. The following configurations works in a Grails 2.1.1 test project:

// log4j configuration
log4j = {
    appenders {
        def logPattern = '%d{dd-MM-yyyy HH:mm:ss,SSS} %5p %c{2} - %m%n'
        console name: 'stdout', layout: pattern(conversionPattern: logPattern)

        appender new DailyRollingFileAppender(
            name: 'usage', datePattern: "'.'yyyy-MM-dd",
            layout: pattern(conversionPattern: logPattern),
            file: 'usage.log'
        )
    }

    root {
        error 'stdout'
    }

    info additivity: false, usage: ["grails.app.controllers.com.example.MyController"]
}