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.
Related
I am using Grail 2.2.4,
in conf/spring/resources.xml, I try to import a file as ${realm}-config.properties, where realm is a vm arguement, I tried to set vm arguements in BuildConfig.groovy as below
grails.tomcat.jvmArgs = ["-Dstage=dev","-Drealm=app"]
But it doesn't seem to pick up. I get below error,
class path resource [${realm}-config.properties] cannot be opened because it does not exist
What is the right way to set vm arguements in grails 2.2.4 ?
Maybe try to load your config via environment variable handled in conf/Config.groovy
def ENV_NAME = "MY_CONFIG"
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)
}
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?
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.
I have setup an environment variable like this:
APP_HOME = "c:\app\app-datasource.properties
in config.groovy I do
def ENV_NAME = "APP_HOME"
if(!grails.config.location || !(grails.config.location instanceof List)) {
grails.config.location = []
}
if(System.getenv(ENV_NAME)) {
println "Including configuration file specified in environment: " + System.getenv(ENV_NAME);
grails.config.location << "file:" + System.getenv(ENV_NAME)
} else if(System.getProperty(ENV_NAME)) {
println "Including configuration file specified on command line: " + System.getProperty(ENV_NAME);
grails.config.location << "file:" + System.getProperty(ENV_NAME)
} else {
println "No external configuration file defined."
}
I got this from a post online, I want to know if we need to use grails.config.location or grails.config.locations ?
Also instead of APP_HOME being set to the properties file directly, can I set it to a directory path (e.g.: c:\apps) and then can I have multiple properties files placed in that directory, then if I do the following multiple times will it work?:
grails.config.locations << "file:" + System.getProperty(ENV_NAME)+ "\app-datasource.properties"
grails.config.locations << "file:" + System.getProperty(ENV_NAME)+ "\app-reporting.properties"
and so on...
Thanks in advance
You need to modify grails.config.locations (plural). My (very limited) experience says that the external files are probably not loaded until after Config.groovy is completed.
You might want to consider looking for he additional configuration file on your classpath; then you can put your extra outside of the Grails project (e.g., in your web server's library) or within the grails-app/conf directory. I have written the instructions on how to do that here.
Here's a post on how to do it from a plugin: https://stackoverflow.com/a/9789506/1269312
I have a few log.debugs() that I don't want to process (since they are heavy) unless the app is currently in debug mode (not production).
Is there a way to check if the grails app is currently in debug mode/development mode?
You can test if the current environment is dev (for example) using the following:
import grails.util.Environment
if (Environment.current == Environment.DEVELOPMENT ) {
// Do your dev logging here
}
IMO, a better solution than hard-coding the env where this logging happens, is to configure it. For example, to enable debug logging for this class only in the dev environment. add the following to Config.groovy
log4j = {
appenders {
// config for stdout and logfile appenders omitted
}
// log everything at error level to stdout and logfile appenders
root {
error 'stdout', 'logfile'
}
environments {
development {
// log this class at debug level in dev env only
debug 'com.example.MyClass'
}
}
}
in the config.groovy the environments are defined.
you can specify what you want the log configuration to be based on the environment the application in running in
environments {
development {
log4j = {
// determine what appenders are logging in development...
}
}
production {
log4j = {
// determine what appenders are logging in production...
}
}
}