grails log4j diffrerent appenders according files - grails

I would like to log to different appenders depending on the module...
I have 3 appenders: the console, a rolling file to log the controller and services, and another rolling file to log some stuff in jobs. I want to log the code of the job only for its rolling file and to log the controllers and services only with the other rolling file.
So this is my grails log4j configuration:
development {
def catalinaBase = System.properties.getProperty('catalina.base')
if (!catalinaBase) catalinaBase = '.'
def logDirectory = "${catalinaBase}/logs/AmbienticWebsite"
log4j = {
appenders {
console name:'stdout', layout:pattern(conversionPattern: '%c{2} [%p] - %m%n')
appender new DailyRollingFileAppender(
name: "rollingFileGrailsApp",
file: "${logDirectory}/GrailsApp.log",
datePattern: "'.'yyyy-MM-dd",
layout: pattern(conversionPattern: commonPattern)
)
appender new DailyRollingFileAppender(
name: "rollingFileImport",
file: "${logDirectory}/Imports.log",
datePattern: "'.'yyyy-MM-dd",
layout: pattern(conversionPattern: commonPattern)
)
}
root {
error 'stdout', 'rollingFileImport', 'rollingFileGrailsApp' // both stdout and AmbienticWebsite_dev.log are filled by logging information
additivity = false
}
debug rollingFileImport: 'ambienticwebsite.EventImportJob',
'time2marketing.time2marketingImportService',
'eventImportData.DiscomImportDataService',
'eventImportData.EventImportService'
info rollingFileGrailsApp: 'ambienticwebsite',
'ambienticwebsite.jobManagement.AmbienticJobListener',
'BootStrap',
'grails.app.controllers',
'grails.app.services'
}
}
With this configuration, the logs are written to the two rolling files and stdout. If I delete the rolling appenders from the root, the rolling file stays empty, even if the appenders are specified for the group of files.
Does anyone have advice to separate the log into the appenders?

I think you need to add additivity: false to the custom appenders.
debug rollingFileImport: [foo, bar, baz]
additivity: false
info rollingFileGrailsApp: [foo1, bar1, baz1]
additivity: false
Refer Logger Inheritance in grails.

Related

grails logfile does not created in production server

In my Grails project I've created and implemented log4j logging system.
In local environment file is correctly created, but in production server it is not.
here is the log4j configuration inside config.groovy file:
log4j = {
appenders {
file name: 'file', file:"/home/file.log"
}
root{
info 'stdout', 'file'
}
}
I've tried with other paths but it does not work.
How can I solve this issue?

dailyrollingfileappender in grails

I want to use send log messages to hourly rolling files in my grails application. Here is how I have configured log4j in Config.groovy
appenders {
rollingFile name:"stacktrace",
file: "/tmp/logs/app.log",
conversionPattern: '%-5p %d{MM-dd HH:mm:ss} %m (%F:%L)'
appender new DailyRollingFileAppender(
name: "events",
datePattern: "'.'yyyy-MM-dd-HH:mm",
file: "/tmp/logs/app_events.log",
layout: pattern(conversionPattern: "%c{2} %m%n")
)
}
root {
error 'stacktrace'
}
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.springframework'
info events: "com.app.events", additivity: false
This is how I'm getting logger for events within com.app.events package:
LOG = Logger.getLogger('events')
LOG.info("logging info")
I'm not sure what I'm missing here. I don't see any logs printed. If I add info 'events' inside root, it works but logs from all packages also go inside app_events.log which is not what I want. I only want logs from com.app.events package to go in app_events.log.
The parts of the logging instructions line in Config.groovy are:
// "Logging Level" "Appender Name": "Logger Name", "Other Options"
info events: "com.app.events", additivity: false
And in where you retrieve your logger:
// LOG = Logger.getLogger("Logger Name")
LOG = Logger.getLogger('events')
So to have the events appender receive package com.app.events logging, change how you retrieve your logger to:
LOG = Logger.getLogger('com.app.events')
Maybe using error 'stacktrace' in the root block is affecting log4j. The stacktrace appender is a special appender just for full stacktraces. Try adding another appender as your root appender and use that in place of 'stacktrace' in your root block.
appenders {
appender new DailyRollingFileAppender(
name: "base",
datePattern: "'.'yyyy-MM-dd-HH:mm",
file: "/tmp/logs/app_events.log",
layout: pattern(conversionPattern: "%c{2} %m%n")
)
}
root {
error "base"
}

grails log4j is not working on custom appenders

I am trying to log the "info and above level" logging from grails.app.controllers and grails.app.services into this appender "appLog". From the documentation and a lot of google search and ofcourse stack overflow. I understood that all i need is my appender and then logger info.
But that never works for me, so i added the root block as below and made it route every log to my appender and I also set my additivity to false so that it won't pull any of the inherited logs.
My requirement was very simple, but i could not get it working. I am using grails 2.4.1.
Can someone please shed some light on what is going wrong here?
Below is my configuration:
Log4j:main{
appender name: "appLog",
new org.apache.log4j.DailyRollingFileAppender(
threshold: org.apache.log4j.Level.INFO,
datePattern: "'.'yyyy-MM-dd",
file: log4jFileName,
layout: pattern(conversionPattern: '[%d{yyyy-MM-dd hh:mm:ss.SSS}] %p %c{5} %m%n')
)
info additivity: false, appLog: "grails.app.services.xxxService"
root {
debug 'appLog'
additivity = false
}
}
A couple things I'm seeing wrong here:
Your name: "appLog" portion should be inside of the DailyRollingFileAppender constructor.
You are missing an appenders block.
Try changing the configuration to this:
log4j = {
appenders {
appender new org.apache.log4j.DailyRollingFileAppender(
name: "appLog",
threshold: org.apache.log4j.Level.INFO,
datePattern: "'.'yyyy-MM-dd",
file: log4jFileName,
layout: pattern(conversionPattern: '[%d{yyyy-MM-dd hh:mm:ss.SSS}] %p %c{5} %m%n')
)
}
info additivity: false,
appLog: "grails.app.services.xxxService"
root {
debug 'appLog'
}
}

log4j in grails: error printed when use variable in appender config

I am using slf4j "DailyRollingFileAppender" in grails 2.3.4.
When i tried to use a variable as part of the "file" parameter, the grails always print some error logs when the app starting.
But my app's log messages can printed into the specified "user-event.log" as expected although grails gives me those error messages.
Below is my log4j configuration:
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 DailyRollingFileAppender(
name: "userEventLog",
file: "${event.log.dir}/user-event.log",
layout: pattern(conversionPattern: '%m%n'),
datePattern: "'.'yyyy_MM_dd",
threshold: org.apache.log4j.Level.INFO
)
}
info userEventLog: "app.bean.log.UserEventLog"
}
The "event.log.dir" variable is defined as below :
environments {
development {
// event log dir
event.log.dir = "${userHome}/workspace/app/logs/event"
}
production {
// event log dir
event.log.dir = "/opt/www/app/logs/event"
}
}
The error messages printed in grails console when app starting are:
| Error log4j:ERROR Property missing when configuring log4j: event
| Error log4j:ERROR Property missing when configuring log4j: event
when i replace the "${event.log.dir}" variable with a string path, for example "/home/app/" and restart grails, the error messages disappear.
Use Holders to read config properties. I assume it will not be able to read the config property itself while setting up log4j as it is part of the config itself.
import grails.util.Holders
...
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 DailyRollingFileAppender(
name: "userEventLog",
file: "${Holders.config.event.log.dir}/user-event.log",
layout: pattern(conversionPattern: '%m%n'),
datePattern: "'.'yyyy_MM_dd",
threshold: org.apache.log4j.Level.INFO
)
}
info userEventLog: "app.bean.log.UserEventLog"
}

grails configure log4j without rebuilding war?

This seems pretty strange, but when grails builds a war file it doesn't generate a log4j.properties or log4j.xml file.
Instead it has the following in WEB-INF/web.xml
web.xml:
<listener>
<listener-class>org.codehaus.groovy.grails.web.util.Log4jConfigListener</listener-class>
</listener>
and apparently "grails Log4j DSL configures logging in-memory". The problem here is - log4j isn't automatically exposed to JMX for us to dynamically change and there's no log4j file generated by grails. But Config.groovy is a compiled file.
There's got to be an easy way to manage this without rebuilding the war?
One option suggested is go through to spring and configure logging there:
resources.groovy:
beans = {
log4jConfigurer(org.springframework.beans.factory.config.MethodInvokingFactoryBean)
{
targetClass = "org.springframework.util.Log4jConfigurer"
targetMethod = "initLogging"
arguments = ["classpath:myapp/log4j.properties"]
}
}
then shift the configuration in the DSL to the configured file.
Can anyone advise the 'groovy' way to dynamically change logging configuration without rebuilding the WAR file each time. Using grails-1.3.7. Cutting the DSL out doesn't seem the right way.
Thanks
You may have an external config file that is searched for by your application at startup time.
You would have a MyExternalConfig.groovy file somewhere in your production environment. For example:
log4j = {
def catalinaBase = System.properties.getProperty('catalina.base')
if (!catalinaBase) catalinaBase = '.'
def logDirectory = "${catalinaBase}/logs"
appenders {
rollingFile name:"infoLog", maxFileSize:'900KB', file:"${logDirectory}/${appName}Info.log", maxBackupIndex:10, layout:pattern(conversionPattern: '%d{DATE} %p %c - %m%n'), threshold: org.apache.log4j.Level.INFO
rollingFile name:"erroLog", maxFileSize:'900KB', file:"${logDirectory}/${appName}Erro.log", maxBackupIndex:10, layout:pattern(conversionPattern: '%d{DATE} %p %c - %m%n'), threshold: org.apache.log4j.Level.ERROR
}
root {
info 'infoLog', 'erroLog'
additivity = false
}
error erroLog:"StackTrace"
error erroLog: 'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages', // GSP
'net.sf.ehcache.hibernate'
warn infoLog: 'org.mortbay.log'
info infoLog: "grails.app"
}
Then in your Config.groovy file, that belongs to your grails project in conf folder, you put this as the last thing of the file:
def ENV_NAME = "MY_EXTERNAL_CONFIG"
if(!grails.config.locations || !(grails.config.locations instanceof List)) {
grails.config.locations = []
}
if(System.getenv(ENV_NAME)) {
grails.config.locations << "file:" + System.getenv(ENV_NAME)
} else if(System.getProperty(ENV_NAME)) {
grails.config.locations << "file:" + System.getProperty(ENV_NAME)
} else {
println "No external configuration file defined."
}
This will look for external configurations files to add to your grails.config.locations attribute of your Config.groovy. First it looks for it as a System Environment variable (I use it this way), if it does not find, then it looks for a command line parameter (so you could add it when you start your tomcat app, as a parameter to startup.sh).
To configure your system environment variabble, just do this before starting tomcat:
MY_EXTERNAL_CONFIG="/home/tomcat/configs/MyExternalConfig.groovy"
export MY_EXTERNAL_CONFIG
--- start tomcat here ---
That's it.

Resources