Grails 2.3.8 中两个位置的 log4j 日志记录配置
Posted
技术标签:
【中文标题】Grails 2.3.8 中两个位置的 log4j 日志记录配置【英文标题】:log4j logging configuration for two locations in Grails 2.3.8 【发布时间】:2014-05-19 22:21:37 【问题描述】:我想将 BootStrap.groovy 文件中的一些信息记录到控制台和日志文件中。输出报告了一些配置信息,并标记了应用程序从配置到执行阶段的过渡。我遇到的问题是仅在控制台上看到所需的输出,而不是在日志文件中。我的环境包括
Grails 2.3.8 红帽企业 Linux 工作站 6.5 版我提供了两个代码 sn-ps 来显示我在做什么。它们也很容易插入一个空的 Grails 项目(不需要创建域类或控制器来查看我所看到的行为)。当我运行 'grails run-app' 时,我希望 environments
块的 development 部分将 BootStrap 输出配置到两个位置。除了让两个位置的日志记录正常工作之外,如果您对我的 log4j 配置有任何一般性建议,我们也将不胜感激。
我修改了我的 BootStrap.groovy:
import grails.util.Environment
class BootStrap
def grailsApplication
def init = servletContext ->
log.info """
tryLoggingInGrails2-3-8 configuration ---------------- $new Date()
environment : $Environment.current.name
dataSource.username : $grailsApplication.config?.dataSource?.username
dataSource.url : $grailsApplication.config?.dataSource?.url
------------------------------------------------------"""
def destroy =
在Config.groovy中,log4j配置部分为:
// ----------------------------- Start Config.groovy snippet
// log4j configuration
def catalinaBase = System.getProperty( 'catalina.base' )
if ( !catalinaBase ) catalinaBase = './target' // just in case
def logDirectory = "$catalinaBase/logs"
def consoleLevelThreshold = org.apache.log4j.Level.WARN
def fileLevelThreshold = org.apache.log4j.Level.INFO
environments
development
consoleLevelThreshold = org.apache.log4j.Level.DEBUG
fileLevelThreshold = org.apache.log4j.Level.DEBUG
// Inside the log4j closure, use '$myAppName' instead of '$appName'
def myAppName = appName
log4j =
appenders
// This 'null' prevents the empty stacktrace.log file from being created
// in the default location, where we may not have permission to write
// in a production tomcat.
'null' name: 'stacktrace'
console name: 'stdoutAppender',
threshold: consoleLevelThreshold,
layout: pattern( conversionPattern: '%-5p %c2 %m%n' )
file name: 'fileAppender',
file: "$logDirectory/$myAppName.log",
threshold: fileLevelThreshold,
layout: pattern( conversionPattern: '%-4r [%t] %-5p %c %d %x - %m%n' ),
append: false
file name: 'stacktraceAppender',
file: "$logDirectory/$myAppName_stacktrace.log",
threshold: org.apache.log4j.Level.ERROR,
append: false
// appenders
root
warn 'fileAppender', 'stdoutAppender'
error stacktraceAppender: "StackTrace"
error fileAppender: [
'grails.app',
'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'
]
environments
development
debug additivity: false,
stdoutAppender: [
"grails.app.conf.BootStrap"
]
debug additivity: false,
fileAppender: [
"grails.app.conf.BootStrap"
]
// development
production
info additivity: false,
fileAppender: [
"grails.app.conf.BootStrap"
]
// production
// environments
// ----------------------------- End Config.groovy snippet
【问题讨论】:
【参考方案1】:我采用了我们的日志记录配置并使用您的配置对其进行了测试。它确实完成了你想要的。我们的开发模式日志目录最终位于logs
下,而不是target
。此外,确保在Config.groovy
的顶部添加PatternLayout
、Level
和Environment
的导入。也许你可以从这个倒过来。
// If we are running under tomcat, this is the tomcat base
def logHome = "./logs"
environments
production
logHome = (System.getProperty("catalina.base") ?: ".") + "/logs"
// Ensure the log directory exists
new File(logHome).mkdirs()
def applicationName = appName
log4j =
def layout = new PatternLayout("%d %-5p %c %x - %m%n")
def logName = String baseName -> "$logHome/$applicationName-$baseName.log"
// Only configure file appenders if running under tomcat
appenders
console name: 'stdout', layout: pattern(conversionPattern: "%-5p %c2 - %m%n"), threshold: Level.INFO
console name: 'stderr', layout: pattern(conversionPattern: "%-5p %c2 - %m%n"), threshold: Level.ERROR
// Disable the stacktrace.log file, it's already going to error anyway
'null' name: 'stacktrace'
rollingFile name: "errorLog", threshold: Level.ERROR, fileName: logName('error'), layout: layout, immediateFlush: true, maxFileSize: "100MB", maxBackupIndex: 5
rollingFile name: "infoLog", threshold: Level.INFO, fileName: logName('info'), layout: layout, maxFileSize: "100MB", maxBackupIndex: 5
rollingFile name: "debugLog", threshold: Level.DEBUG, fileName: logName('debug'), layout: layout, maxFileSize: "100MB", maxBackupIndex: 5
def infoLogged = [
'grails.app.conf',
'grails.app.taglib.com.triu',
'grails.app.filters.com.triu',
'grails.app.services.com.triu',
'grails.app.controllers.com.triu',
'grails.app.domain',
'liquibase',
'grails.plugin.databasemigration'
]
// Mirror logs to stdout and info logging
environments
development
info stdout: infoLogged, infoLog: infoLogged
debug debugLog: infoLogged
test
info stdout: infoLogged, infoLog: infoLogged
production
info infoLog: infoLogged
error errorLog: infoLogged
debug debugLog: infoLogged
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.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
'grails.spring',
'org.springframework',
'org.hibernate'
// Per docs, can't put environment blocks inside of root block
root
error 'errorLog', 'stderr'
【讨论】:
感谢您的建议,但我的日志文件的输出没有变化。除了按照说明尝试您的建议外,我还将“可加性”部分放在首位(并不重要),无论哪种方式结果都相同。 奇怪,我们做同样的事情,我们的配置或多或少像你的。唯一的例外是我们只指定了“grails.app.conf”,而不是明确的 BootStrap。 我还确认使用“grails.app.conf”而不是“grails.app.conf.BootStrap”不会改善结果。 我已经用一个工作配置更新了我的答案,虽然稍微复杂一些。 感谢您对 @Aaron 的帮助。如果我想出任何重要的简化,我会发布一个摘要。【参考方案2】:这确实是为了补充 Aaron 的答案,但是 *** 中的 cmets 没有我想要使用的丰富格式。
我有时间重新审视这一点,发现我之前使用的 Grails 2.2.4 和 Grails 2.3.8 之间的行为存在差异。
设置logDirectory
后在Config.groovy文件中添加调试println
:
def logDirectory = "$catalinaBase/logs"
println "logDirectory = $logDirectory"
在 Grails 2.2.4 下显示(可能是 2.3.x 之前的任何版本)
logDirectory = ./target/logs
但在 Grails 2.3.8 下,会打印一个“grails run-app”
logDirectory = ./target/logs
...
logDirectory = ./target/work/tomcat/logs
啊哈!看到两个位置,我现在记得在“What's new in grails 2.3?”中读到,现在可以将许多命令分叉到单独的 JVM 中。以前,“grails run-app”执行时使用空的“catalinaBase
”值,我的输出进入了 target/logs 目录下的日志文件。但是对于 Grails 2.3.8,我没有意识到在 target/work/tomcat 下创建了第二组日志文件:
tryLoggingInGrails2-3-8$ find . -name *.log -print
./target/logs/tryLoggingInGrails2-3-8.log (expected file is created, but empty)
./target/logs/tryLoggingInGrails2-3-8_stacktrace.log (expected file, but empty)
./target/work/tomcat/logs/tryLoggingInGrails2-3-8.log (unexpected file)
./target/work/tomcat/logs/tryLoggingInGrails2-3-8_stacktrace.log (unexpected file)
并且我想要的输出进入另一组日志文件,显然一个 fork 获得了一个非空的 catalinaBase
值来使用。我以为我没有从 log4j 获得输出,但它正在工作;只是进入一个我不知道或正在寻找的文件。
Aaron 的代码之所以有效,是因为他的代码块不会被此愚弄,它专门针对生产环境,并且目标文件已按预期设置:
def logHome = "./logs"
environments
production
logHome = (System.getProperty("catalina.base") ?: ".") + "/logs"
【讨论】:
以上是关于Grails 2.3.8 中两个位置的 log4j 日志记录配置的主要内容,如果未能解决你的问题,请参考以下文章
我们如何将更高版本的 Log4j 设置为 grails 应用程序
Grails 应用程序中的 Log4J 问题,它依赖于 comons-logging