`Log4jConfig.groovy`
`001 /* 002 * Copyright 2004-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.codehaus.griffon.runtime.logging 017 018 import griffon.util.Environment 019 import griffon.util.Metadata 020 import org.apache.log4j.helpers.LogLog 021 import org.apache.log4j.varia.NullAppender 022 import org.apache.log4j.xml.XMLLayout 023 import org.codehaus.groovy.runtime.InvokerHelper 024 import org.apache.log4j.* 025 026 /** 027 * Encapsulates the configuration of Log4j. 028 * 029 * @author Graeme Rocher (Grails 1.1) 030 * @since 0.9.2 031 */ 032 class Log4jConfig { 033 static final DEFAULT_PATTERN_LAYOUT = new PatternLayout( 034 conversionPattern: '%d [%t] %-5p %c{2} %x - %m%n') 035 036 static final LAYOUTS = [xml: XMLLayout, html: HTMLLayout, simple: SimpleLayout, pattern: PatternLayout] 037 static final APPENDERS = ["null": NullAppender, console: ConsoleAppender, 038 file: FileAppender, rollingFile: RollingFileAppender, 039 event: GriffonApplicationEventAppender] 040 041 private appenders = [:] 042 043 def methodMissing(String name, args) { 044 if (APPENDERS.containsKey(name) && args) { 045 def constructorArgs = args[0] instanceof Map ? args[0] : [:] 046 if (!constructorArgs.layout) { 047 constructorArgs.layout = DEFAULT_PATTERN_LAYOUT 048 } 049 def appender = APPENDERS[name].newInstance() 050 InvokerHelper.setProperties appender, constructorArgs 051 if (appender.name) { 052 appenders[appender.name] = appender 053 } else { 054 LogLog.error "Appender of type $name doesn't define a name attribute, and hence is ignored." 055 } 056 appender.activateOptions() 057 return appenders[name] 058 } 059 060 if (LAYOUTS.containsKey(name) && args) { 061 return LAYOUTS[name].newInstance(args[0]) 062 } 063 064 if (isCustomEnvironmentMethod(name, args)) { 065 return invokeCallable(args[0]) 066 } 067 068 LogLog.error "Method missing when configuring log4j: $name" 069 } 070 071 private boolean isCustomEnvironmentMethod(String name, args) { 072 Environment.current == Environment.CUSTOM && 073 Environment.current.name == name && 074 args && (args[0] instanceof Closure) 075 } 076 077 def environments(Closure callable) { 078 invokeCallable(callable) 079 } 080 081 private invokeCallable(Closure callable) { 082 callable.delegate = this 083 callable.resolveStrategy = Closure.DELEGATE_FIRST 084 callable.call() 085 } 086 087 def development(Closure callable) { 088 if (Environment.current == Environment.DEVELOPMENT) { 089 invokeCallable(callable) 090 } 091 } 092 093 def production(Closure callable) { 094 if (Environment.current == Environment.PRODUCTION) { 095 invokeCallable(callable) 096 } 097 } 098 099 def test(Closure callable) { 100 if (Environment.current == Environment.TEST) { 101 invokeCallable(callable) 102 } 103 } 104 105 def configure(Closure callable = {}) { 106 107 Logger root = Logger.getRootLogger() 108 109 callable.delegate = this 110 callable.resolveStrategy = Closure.DELEGATE_FIRST 111 112 try { 113 callable.call(root) 114 for (appender in appenders.values()) root.addAppender appender 115 116 if (!root.allAppenders.hasMoreElements()) { 117 def consoleAppender = createConsoleAppender() 118 root.setLevel Level.ERROR 119 appenders['stdout'] = consoleAppender 120 121 error 'org.codehaus.griffon' 122 123 root.addAppender appenders['stdout'] 124 } 125 /* 126 Logger logger = Logger.getLogger("StackTrace") 127 logger.additivity = false 128 def fileAppender = createFullstackTraceAppender() 129 if (!logger.allAppenders.hasMoreElements()) { 130 logger.addAppender fileAppender 131 } 132 */ 133 } 134 catch (Exception e) { 135 LogLog.error "WARNING: Exception occured configuring log4j logging: $e.message" 136 } 137 } 138 139 private createConsoleAppender() { 140 def consoleAppender = new ConsoleAppender(layout: DEFAULT_PATTERN_LAYOUT, name: "stdout") 141 consoleAppender.activateOptions() 142 appenders.console = consoleAppender 143 return consoleAppender 144 } 145 146 private createFullstackTraceAppender() { 147 if (appenders.stacktrace) { 148 return appenders.stacktrace 149 } 150 151 def fileAppender = new FileAppender(layout: DEFAULT_PATTERN_LAYOUT, name: "stacktraceLog") 152 if (Environment.current == Environment.DEVELOPMENT) { 153 def targetDir = Metadata.current.getGriffonWorkingDir() 154 if (targetDir) targetDir.mkdirs() 155 fileAppender.file = targetDir ? "${targetDir.absolutePath}/stacktrace.log" : "stacktrace.log" 156 } 157 else { 158 fileAppender.file = "stacktrace.log" 159 } 160 fileAppender.activateOptions() 161 appenders.stacktrace = fileAppender 162 return fileAppender 163 } 164 165 Logger root(Closure c) { 166 def root = Logger.getRootLogger() 167 168 if (c) { 169 c.delegate = new RootLog4jConfig(root, this) 170 c.resolveStrategy = Closure.DELEGATE_FIRST 171 c.call() 172 } 173 174 return root 175 } 176 177 def appenders(Closure callable) { 178 callable.delegate = this 179 callable.resolveStrategy = Closure.DELEGATE_FIRST 180 callable.call() 181 } 182 183 def appender(Map name, Appender instance) { 184 if (name && instance) { 185 String appenderName = name.values().iterator().next() 186 instance.name = appenderName 187 appenders[appenderName] = instance 188 instance.activateOptions() 189 } 190 } 191 192 def appender(Appender instance) { 193 if (instance && instance.name) { 194 appenders[instance.name] = instance 195 instance.activateOptions() 196 } 197 else { 198 LogLog.error "Appender [$instance] is null or does not define a name." 199 } 200 } 201 202 def off(Map appenderAndPackages) { 203 setLogLevelForAppenderToPackageMap(appenderAndPackages, Level.OFF) 204 } 205 206 def fatal(Map appenderAndPackages) { 207 setLogLevelForAppenderToPackageMap(appenderAndPackages, Level.FATAL) 208 } 209 210 def error(Map appenderAndPackages) { 211 setLogLevelForAppenderToPackageMap(appenderAndPackages, Level.ERROR) 212 } 213 214 def warn(Map appenderAndPackages) { 215 setLogLevelForAppenderToPackageMap(appenderAndPackages, Level.WARN) 216 } 217 218 def info(Map appenderAndPackages) { 219 setLogLevelForAppenderToPackageMap(appenderAndPackages, Level.INFO) 220 } 221 222 def debug(Map appenderAndPackages) { 223 setLogLevelForAppenderToPackageMap(appenderAndPackages, Level.DEBUG) 224 } 225 226 def trace(Map appenderAndPackages) { 227 setLogLevelForAppenderToPackageMap(appenderAndPackages, Level.TRACE) 228 } 229 230 def all(Map appenderAndPackages) { 231 setLogLevelForAppenderToPackageMap(appenderAndPackages, Level.ALL) 232 } 233 234 private setLogLevelForAppenderToPackageMap(appenderAndPackages, Level level) { 235 236 def additivity = appenderAndPackages.additivity != null ? appenderAndPackages.remove('additivity') : true 237 238 appenderAndPackages?.each { appender, packages -> 239 eachLogger(packages) { Logger logger -> 240 logger.level = level 241 if (appenders[appender]) { 242 logger.addAppender appenders[appender] 243 logger.additivity = additivity 244 } 245 else { 246 LogLog.error "Appender $appender not found configuring logger ${logger.getName()}" 247 } 248 } 249 } 250 } 251 252 def eachLogger(packages, Closure callable) { 253 if (packages instanceof String || packages instanceof GString) { 254 Logger logger = Logger.getLogger(packages) 255 callable(logger) 256 } 257 else { 258 for (p in packages) { 259 p = p?.toString() 260 if (p) { 261 Logger logger = Logger.getLogger(p) 262 callable(logger) 263 } 264 } 265 } 266 } 267 268 def off(Object[] packages) { 269 eachLogger(packages) { logger -> logger.level = Level.OFF } 270 } 271 272 def fatal(Object[] packages) { 273 eachLogger(packages) { logger -> logger.level = Level.FATAL } 274 } 275 276 def error(Object[] packages) { 277 eachLogger(packages) { logger -> logger.level = Level.ERROR } 278 } 279 280 def warn(Object[] packages) { 281 eachLogger(packages) { logger -> logger.level = Level.WARN } 282 } 283 284 def info(Object[] packages) { 285 eachLogger(packages) { logger -> logger.level = Level.INFO } 286 } 287 288 def debug(Object[] packages) { 289 eachLogger(packages) { Logger logger -> logger.level = Level.DEBUG } 290 } 291 292 def trace(Object[] packages) { 293 eachLogger(packages) { logger -> logger.level = Level.TRACE } 294 } 295 296 def all(Object[] packages) { 297 eachLogger(packages) { logger -> logger.level = Level.ALL } 298 } 299 300 def removeAppender(String name) { 301 Logger.getRootLogger().removeAppender name 302 } 303 } 304 305 class RootLog4jConfig { 306 Logger root 307 Log4jConfig config 308 309 def RootLog4jConfig(root, config) { 310 this.root = root 311 this.config = config 312 } 313 314 def debug(Object[] appenders = null) { 315 setLevelAndAppender(Level.DEBUG, appenders) 316 } 317 318 private setLevelAndAppender(Level level, Object[] appenders) { 319 root.level = level 320 for (appName in appenders) { 321 Appender app 322 if (appName instanceof Appender) { 323 app = appName 324 } else { 325 app = config.appenders[appName?.toString()] 326 } 327 if (app) { 328 root.addAppender app 329 } 330 } 331 } 332 333 def info(Object[] appenders = null) { 334 setLevelAndAppender(Level.INFO, appenders) 335 } 336 337 def warn(Object[] appenders = null) { 338 setLevelAndAppender(Level.WARN, appenders) 339 } 340 341 def trace(Object[] appenders = null) { 342 setLevelAndAppender(Level.TRACE, appenders) 343 } 344 345 def all(Object[] appenders = null) { 346 setLevelAndAppender(Level.ALL, appenders) 347 } 348 349 def error(Object[] appenders = null) { 350 setLevelAndAppender(Level.ERROR, appenders) 351 } 352 353 def fatal(Object[] appenders = null) { 354 setLevelAndAppender(Level.FATAL, appenders) 355 } 356 357 def off(Object[] appenders = null) { 358 setLevelAndAppender(Level.OFF, appenders) 359 } 360 361 void setProperty(String s, Object o) { 362 root."$s" = o 363 } 364 }`