I have a Grails (2.3.6) app (myapp) and a custom plugin (grails-myapplogging). I want to:
Configure log4j in the plugin and nowhere else
In keeping with the above, this implies that I am omitting any log4j closures inside the app's Config.groovy file
Per this answer, I added a Config.groovy file to my plugin and gave it this:
println("Well hello!")
log4j {
appenders {
appender new org.apache.log4j.DailyRollingFileAppender(
name: "appLog",
datePattern: "'.'yyyy-MM-dd",
fileName: "/var/log/myapp.log"
)
}
root {
error 'stdout', 'appLog'
}
}
Then in my app's BuildConfig.groovy, I add the plugin to my project. Then I run the app (grails run-app) and expect to see some logging. The app starts up just fine, doesn't throw or print any errors, however /var/log/myapp.log never gets created. Additionally, when building, I never see the "Well hello!" message get printed out. Ideas?
When I take this log4j closure and put it into my app's Config.groovy, everything works perfectly fine. So this is definitely a situation where the plugin's Config.groovy is not being read.
Update: do I need to manually "include" the plugin's Config.groovy somehow, or explicitly tell the app to load it, etc.?
Related
Everything works fine when I have a rolling file configured as so:
RollingFile name="RollingFileAppender"
fileName="/applicationLogs/CTMSApplicationService-${hostName}.log"
filePattern="/applicationLogs/CTMSApplicationService-${hostName}-%d{MM-dd-yyyy}-%i.log"
BUT as soon as I use the ${sys:jboss.server.log.dir} for the "root" of my log location the primary log gets created but nothing ever rolls. The log file just gets appended to:
RollingFile name="RollingFileAppender"
fileName="${sys:jboss.server.log.dir}/CTMSApplicationService-${hostName}.log"
filePattern="${sys:jboss.server.log.dir}/CTMSApplicationService-${hostName}-%d{MM-dd-yyyy}-%i.log">
The value of ${sys:jboss.server.log.dir}="E:\Wildfly-8.1.0.Final\standalone\log"
Is it because the fileName can handle the Winblows "E:\" and the filePattern can not?
This may be caused by this issue: https://issues.apache.org/jira/browse/LOG4J2-829
This is fixed in the master branch and will be included in the upcoming 2.1 release.
I use Grails
In my file Config.groovy I create an appender as:
log4j = {
appenders {
file name:'myAppli', file:'/tmp/myAppli.log'
}
...
}
Is it possible to parameter file path of my appender through data of file.properties ?
something like that :
file.properties:
myAppli.log.path=C:\\tmp\\
Config.groovy:
appenders {
file name:'myLogs', file:myAppli.log.path + 'myLogs.log'
}
myAppli.log.path should work!!!
There's a section in the docs for this: externalized configuration. You can set a absolute location or let Grails look into the classpath. Here's the example of the docs:
grails.config.locations = [
"classpath:${appName}-config.properties",
"classpath:${appName}-config.groovy",
"file:${userHome}/.grails/${appName}-config.properties",
"file:${userHome}/.grails/${appName}-config.groovy" ]
EDIT: I tested here. It appears that the value is only available throught the config object during runtime and not available inside Config.groovy. According to this thread it's not possible to do what you want.
You're almost right. The log4j closure is executed after the whole configuration has been parsed and assembled, and within the closure you have access to the complete configuration via the variable config. You can say
grails.config.locations = ['file:file.properties']
log4j = {
appenders {
file name:'myAppli', file:"${config.myAppli.log.path}myLogs.log"
}
// ...
}
I've tested this with Grails 2.2: run grails create-app log4jtest to create a new application, then edit log4jtest/grails-app/conf/Config.groovy to add at the top
grails.config.locations = ["file:file.properties"]
logfile.name = "from-config.log"
and for the log4j closure
// log4j configuration
log4j = {
println "filename: ${config.logfile.name}"
// rest of closure as before
Run this app using grails run-app and you'll see it print filename: from-config.log (twice, in fact). Now create a file named file.properties in the top-level log4jtest folder containing the line
logfile.name=from-external.log
Run the app again and this time it will print filename: from-external.log instead.
As there is sensitive code in the config.groovy file, I am afraid that my friends will commit with bugs in this file. When getting svn update, we too will get the buggy config code.
Can i split the code at config.groovy in such a way that the sensitive code remains untouched and the other can be changed frequently?
Inside your main config file you are able to access this variable:
grails.config.locations
It is a list of configuration file locations to which you can add your own files:
grails.config.locations << 'file:MyConfigFile.groovy'
These files will then be added to your configuration.
For a more elaborate setup see this blog post:
http://www.pasopas.nl/2012/loading-grails-configuration-files-update/
Similar to Marijn's answer. This is how I usually set up my Config.groovy. I still use it for some settings, but anything environmentally (deployment location or individual machine) changing can override any settings in the Config.groovy.
Config.groovy >>>>
grails.config.locations = [
"file:../app-config/myapp-dataSource.groovy",
"file:../app-config/myapp-config.groovy"
]
environments {
development {
grails.config.locations = [
"file:../myapp-config/myapp-dataSource.groovy",
"file:../myapp-config/myapp-config.groovy",
"file:${userHome}/myapp-config/myapp-dataSource.groovy",
"file:${userHome}/myapp-config/myapp-config.groovy"
]
some.config.setting=true
}
}
file:${userHome}/myapp-config/myapp-config.groovy >>>>
some.config.setting=false
I am traying to get log4j to log to file in XMLLayout using the groovy log4j dsl. However, it seems that the "layout:"-part is being ignored. This is my setup:
appenders {
file name: 'fileAppender', layout: xml, file: '/tmp/logs/applog.xml', threshold: org.apache.log4j.Level.INFO
console name: "stdout", threshold: org.apache.log4j.Level.INFO
}
root {
debug 'stdout', 'fileAppender'
}
So to stdout I corectly get my info-level pattern layout, but in the file I also get pattern-layout...
What's the trick here?
This is a bug. I've fixed it for 2.0.1: http://jira.grails.org/browse/GRAILS-8635
The workaround as you found is to use the constructor explicitly instead of the DSL shortcut.
Well I found out that you can just use
layout: new XMLLayout()
or
layout: new HTMLLayout()
But still, in the documentation it says
By default the Log4j DSL assumes that you want to use a PatternLayout.
However, there are other layouts available including:
xml - Create an XML log file
html - Creates an HTML log file
simple - A simple textual log
pattern - A Pattern layout
It seems to me that the shortcuts for xml and html don't work.
Grails 1.3.7
I have some configuration located in an external config file. One of the entires looks like this:
site.maintenance.mode = false
I have a filter which checks for certain config settings for specific URLs. When I do a run-app or deploy a WAR into Tomcat and do:
boolean maintenanceMode = grailsApplication.config.site.maintenance.mode
maintenanceMode is coming back true. If I look at the config object in debug mode, this is what I get:
site={maintenance={mode=false, message="<p>Our trail guides are working hard to get the system back on track.</p><p>We're sorry, the account system is down for maintenance at the moment. We'll get it back online as quickly as we can. Thanks for your patience.</p>"}}
I have a controller that I use to reload this config file dynamically and hitting this controller will fix the issue. But I'm curious as to why it is incorrect on first runs and why the discrepency in what is getting put in the maintenanceMode variable vs what is actually in the config object.
Are you using a Java properties file or a Groovy file? If you're using a properties file then I believe Grails will interpret site.maintenance.mode=false the same way as site.maintenance.mode='false' and since Groovy will interpret:
"false".asBoolean() == true
then that would explain why you would see that initial true value.
I just ran a simple test locally to verify this behavior. When I externalize my properties in a file called test.properties then site.maintenance.mode=false initially gets a boolean value of true, when I use a file called test.groovy then it interprets the boolean value of site.maintenance.mode=false as false. I believe this is because when you use a Groovy file Grails uses ConfigurationSlurper to process it but when you use a properties file Grails interprets everything as String name/value pairs.
What I do is to have an external Config.groovy file, for instance: MyConfig.groovy
At the end of the standard grails Config.groovy file, I have the following:
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 Configs found."
}
So now you can have a MyConfig.groovy file anywhere in production environment (for example) and then set an Environment system variable to point to this file (or pass it as parameter to startup.sh), before you start tomcat:
MY_EXTERNAL_CONFIG="/home/tomcat/configs/MyConfig.groovy"
export MY_EXTERNAL_CONFIG
That's it. Now you have an external MyConfig.groovy file. The properties in it are accessible from your grails app as they were part of the standard Config.groovy
import org.codehaus.groovy.grails.commons.*
//...
ConfigurationHolder.config.foo.bar.hello