Log4j2 Grails RollingFileAppender - grails

I'm trying to implement log4j2 with grails 2.5.3 and I'm having problems with the configuration properties.
I my older projects with log4j 1.x I used to have in the config.groovy file something like this:
import org.apache.log4j.*
...
log4j={
environments{
production{
appenders{
def rollingAppender = new RollingFileAppender(
name: "rollingAppender",
layout: pattern(conversionPattern:"[%p] %d{yyyy-MM-dd HH:mm:ss.SSS} (%t) %c{2} %X - %ms : %m%n"),
file: "/tmp/logs/catalina.out",
bufferedIO: false,
maxFileSize: "300MB"
)
appender rollingAppender
}
}
development{
appenders {
def rollingAppender = new RollingFileAppender(
name: "rollingAppender",
layout: pattern(conversionPattern:"[%p] %d{yyyy-MM-dd HH:mm:ss.SSS} (%t) %c{2} %X - %ms : %m%n"),
file: "/tmp/logs/catalina.out",
bufferedIO: false,
maxFileSize: "15MB"
)
appender rollingAppender
}
}
}
info aditivity:false, rollingAppender:"grails.app.services"
info aditivity:false, rollingAppender:"grails.app.controllers"
}
Now, I have seen XML configuration files everywhere but I can't find the way to do it like I used to. I mean, I want to load different configs depending on the enviroment the application is running. Is it a possibility with log4j2?
I have something like this now:
import org.apache.logging.log4j.core.appender.RollingFileAppender
import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy
import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy
import org.apache.logging.log4j.core.layout.PatternLayout
...
enviroments{
development{
appenders {
def rollingAppender = new RollingFileAppender(
name: "rollingAppender",
filePattern: "/tmp/logs_bkp/catalina.%d{yyyy-MM-dd HH:mm:ss.SSS}.log.gz",
layout: new PatternLayout("[%p] %d{yyyy-MM-dd HH:mm:ss.SSS} (%t) %c{2} %X - %ms : %m%n")
fileName: "/tmp/logs/catalina.out",
bufferedIO: false,
policy: new SizeBasedTriggeringPolicy(1024),
strategy: new DefaultRolloverStrategy(2,1,"min",false,5)
)
appender rollingAppender
}
}
}
I know it has some errors, but I can't figure it out how to make it work without using the XML config file. Any ideas?

Related

Grails logging from controller

I'm having a hard time to get Grails 2.4.5 to log my custom messages from my controllers into a specific file. This is what I have in the config part:
log4j = {
/*
* Log levels
off
fatal
error
warn
info
debug
trace
all
*/
appenders {
console name:'stdout', threshold: org.apache.log4j.Level.INFO
rollingFile name: 'applog', maxFileSize: 1024, file: (System.getProperty('catalina.base') ?: 'target') + '/logs/' + appName + '.log',
layout: pattern(conversionPattern: "[%d{HH:mm:ss:SSS}] %-5p %c{2}: %m%n")
environments {
development {
rollingFile name: 'grailsfile', maxFileSize: 4096, file: 'target/logs/grails.log'
file name: 'rootlog', file: 'target/logs/root.log'
}
}
}
root { error 'stdout'}
environments {
development {
debug additivity: false, 'grails.app'
root { error 'stdout', 'rootlog'} //override the root
warn additivity: false, grailsfile:
['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 additivity: false, applog:
['grails.app.controllers', 'grails.app.domain', 'grails.app.services']
}
// production {
// root { error() }
// warn "grails.app.controllers"
// warn "grails.app.domain"
// warn "grails.app.services"
// warn additivity: false, applog: 'grails.app'
// }
}
}
in the controller:
println "Debug log enabled?: " + log.debugEnabled
log.debug "First piggy wrote to Debug"
log.info "Second piggy wrote to Info"
log.error "And the third piggy wrote to Error"
That shows me "Debug log enabled?: true" on console. But the message are not logged anywhere.
The Grails internals log to "grailsfile" and also errors go to "rootlog". But appName.log stays empty.
Any hint what I am having wrong?
UPDATE
To simplify my request I have only configured the most important now. I want the lines
log.debug "First piggy wrote to Debug"
log.info "Second piggy wrote to Info"
log.error "And the third piggy wrote to Error"
End up in the appender applog (file)
So the log4j now only has:
log4j = {
appenders {
console name:'stdout'//, threshold: org.apache.log4j.Level.INFO
rollingFile name: 'applog', maxFileSize: 1024, file: (System.getProperty('catalina.base') ?: 'target') + '/logs/' + appName + '.log',
layout: pattern(conversionPattern: "[%d{HH:mm:ss:SSS}] %-5p %c{2}: %m%n")
}
environments {
development {
debug 'grails.app'
debug additivity: false
applog: ['grails.app.controllers', 'grails.app.domain', 'grails.app.services']
}
}
}
But Still I get my log lines (and also errors from other sources) into console while my custom log file stays empty.
So I simply want to get (ONLY) my log lines into the applog appender as a first step. Any hint how to achieve this?
If you are running the app in development mode, then all your logs with error level and higher are going to target/logs/root.log
It is configured here:
file name: 'rootlog', file: 'target/logs/root.log' ...
root { error 'stdout', 'rootlog'} //override the root
That's because development closure overrides your global configuration.
If you want to see all the logs in appName.log, you should set lower logging level and change appender like this:
root { info 'stdout', 'applog'} //override the root
meanwhile I could figure out that this property made the trouble for my custom log messages:
def appName = grails.util.Metadata.current.'app.name'
...
file: (System.getProperty('catalina.base') ?: 'target') + '/logs/' + appName + '.log',
changing to this works:
log4jFileName = (System.properties.'catalina.base') + "/logs/${appName}.log"
...
file: "${config.log4jFileName}",

How to append grails logging using profiler into custom appender(log file)?

Using grails profiler plugin, I want to append logging into separate file only for profiler.
You should be able to create an appender and then set the appropriate logger (looks to be com.linkedin.grails) to append to it with additivity set to false.
grails 3.x:
appender("PROFILER", FileAppender) {
file = "profiler.log"
encoder(PatternLayoutEncoder) {
pattern = "%level %logger - %msg%n"
}
}
logger("com.linkedin.grails", DEBUG, ["PROFILER"], false) // false here is for additivity
grails before 3:
file name: 'profiler', file: 'profiler.log', layout: pattern(conversionPattern: '%d{[yyyy-MM-dd HH:mm:ss.SSS]} [%t] %-5p: %c %x - %m%n')
debug profiler: [
"com.linkedin.grails"
], additivity: false

How do I set up a log4j appender with 'appender-ref' in grails 2?

Using the Grails config DSL, how can I configure the appender-ref property on an appender?
I am trying to translate a log4j.xml from perf4j into the Grails config DSL (Grails 2.x).
In the log4j.xml file that I am trying to imitate, there is a segment like this:
log4j.xml
<appender name="CoalescingStatistics"
class="org.perf4j.log4j.AsyncCoalescingStatisticsAppender">
<param name="TimeSlice" value="10000"/>
<appender-ref ref="fileAppender"/>
</appender>
I want to imitate this appender's config in Grails, but I can't figure out the <appender-ref> tag.
Here is my latest attempt:
log4j = {
appenders {
//main appender for the app
rollingFile ...
//perf4j coalescing stats appender
appender new AsyncCoalescingStatisticsAppender(name: "coalescingStatsAppender", timeSlice: 10000)
//perf4j stats file appender
rollingFile name: "perfLogFileAppender", file: "perfStats.log", layout: new PatternLayout("%m%n")
}
root {
error 'stdout', 'rollingFileAppender'
}
info additivity: false, coalescingStatsAppender: [StopWatch.DEFAULT_LOGGER_NAME]
}
Additional details
Here is the source log4j.xml I am imitating:
https://web.archive.org/web/20150508124059/http://perf4j.codehaus.org/devguide.html#Using_the_log4j_Appenders_to_Generate_Real-Time_Performance_Information
I was able to make it work with some Groovy magic:
log4j = {
appenders {
//...regular appenders
//perf4j appenders
Appender perfLogFileAppender = delegate.rollingFile name: "perfLogFileAppender", file: "perfStats.log", layout: new PatternLayout("%m%n")
def statsAppender = new AsyncCoalescingStatisticsAppender(name: "coalescingStatsAppender", timeSlice:
10000)
statsAppender.addAppender(perfLogFileAppender)
appender statsAppender
}
root {
error 'stdout', 'rollingFileAppender'
}
info additivity: false, coalescingStatsAppender: [StopWatch.DEFAULT_LOGGER_NAME]
}
A more elegant solution is always welcome.

Relative path not working for log file in Grails

I am trying to give relative path of my custom log file. But it not working, and if I give from complete path it working fine.
My code is like this:
log4j = {
appenders {
// append new appenders of your own and add log level and packages/files like to add.
rollingFile name: "myAppender",
maxFileSize: 1024,
file: "C:/GrailsWS/BaseGrails/target/basegrails.log" // WORKING
//"basegrails.log" // NOT WORKING
//"/target/basegrails.log" // NOT WORKING
/*console name: "myAppender",
layout: pattern(conversionPattern: "%c{2} %m%n")*/
}
debug myAppender: 'com.nagarro.base.grails.EmployeeController'
}
I tried above ways, but it not working.
to write logs in logs dir of tomcat/jetty or in project-root if launched with run-app I use this (if it helps):
String logName = “myapp.log"
String logDirectory
// getting tomcat dir
logDirectory = System.getProperty('catalina.base') ? "${System.getProperty('catalina.base')}/logs/" : ''
// getting jetty dir
if (System.getProperty('jetty.home') != null) {
logDirectory = System.getProperty('jetty.home') ? "${System.getProperty('jetty.home')}/logs/" : ''
}
println("CONFIG:Writing log ${logName} in dir:" + logDirectory)
// log4j configuration
log4j = {
appenders {
appender new DailyRollingFileAppender(
name: 'file', datePattern: "'.'yyyy-MM-dd",
file: logDirectory + logName
)}
...

Import external config value into main config in grails

I have an external config file ${userHome}/.grails/${appName}/config.groovy:
package configs
grails.conf.logDirectory = '/home/serek/tmp/mamlog'
which I would like to import into main grails Config.groovy
grails.config.locations = ["file:${userHome}/.grails/${appName}/config.groovy"]
print grails.conf.logDirectory
log4j = {
appenders {
rollingFile name: 'infoLog', file: "${grails.conf.logDirectory}/info.log", threshold: org.apache.log4j.Level.INFO, maxFileSize: "1024MB", append: true
rollingFile name: 'warnLog', file: 'warn.log', threshold: org.apache.log4j.Level.WARN, maxFileSize: "1024MB", append: true
console name: 'stdout', layout: pattern(conversionPattern: '%d{yyyyMMdd.HHmmss.SSS} %r [%t] %-5p %c %x - %m%n')
}
Unfortunately, print grails.conf.logDirectory is not visible in main config.
How can I handle that? Print outputs only [:]
Groovy: 2.1.9
Grails: 2.3.2
========================================
I found solution, ex Config.groovy:
import org.yaml.snakeyaml.Yaml
Yaml yaml = new Yaml()
def extConfFilePath = "${userHome}/.grails/${appName}/mam.yaml" //my external conf in yaml
def extConfFileContent = new File(extConfFilePath).text
def extConf = yaml.load(extConfFileContent)
grails.ext = extConf
rollingFile name: 'infoLog', file: extConf.logDirectory + "info.log", threshold: org.apache.log4j.Level.INFO, maxFileSize: "1024MB", append: true
I believe its because the external config files are pulled in after Config.groovy is executed. Therefore, println at that location doesn't work. Try printing it from any gsp page with,
println "logDir = ${grailsApplication.config.grails.conf.logDirectory}"

Resources