Reputation: 218
We are currently deploying several Grails (2.4.4) applications to a Tomcat 7 server and have configured logging exactly as described here tomcat-slf4j-logback.
The desire is to configure all grails applications via one logback.xml file as well as log all applications to a single file, but discriminate log messages by their application name as defined in grails' application.properties:
#Grails Metadata file
app.name=my-application
Our logback.xml appender currently looks like this:
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${catalina.base}/logs/all.log</file>
<append>true</append>
<encoder>
<charset>utf-8</charset>
<pattern>%d [%X{appname:-null}] %-5level %logger : %msg%n</pattern>
</encoder>
...
</appender>
As you can see we are currently pulling the 'appname' from the MDC (Mapped Diagnostic Context). It is placed there by a Grails Filter in a Grails Plugin shared by all the applications which looks it up from the application.properties file. This produces output in the log file similar to:
13:34:18.796 [application-1] DEBUG a.b.c.MyClass : hello
13:34:18.797 [application-2] DEBUG a.b.c.MyClass : hello
13:34:18.798 [null] DEBUG b.c.d.OtherClass : No App Name
13:34:18.798 [application-3] DEBUG a.b.c.MyClass : hello
13:34:18.799 [null] DEBUG b.c.d.OtherClass : No App Name
This solution is lacking due to the threadLocal nature of the MDC. Those classes executing outside of the request/response threads don't have access to the same MDC to get the 'appname' and instead print '[null]'.
I have tried the following in logback.xml
<property resource="application.properties" />
Which is supposed to load the application.properties from the classpath but gives:
13:34:18.796 [app.name_IS_UNDEFINED] DEBUG a.b.c.MyClass : hello
Which I think means logback can't find the application.properties files (they are packaged in WEB-INF\classes\ in each of the wars)...
I've also tried locally using logback.groovy ala:
// logback.groovy
// Read in the Grails application.properties
def props = new Properties()
new File("application.properties").withInputStream {
stream -> props.load(stream)
}
def slurper = new ConfigSlurper().parse(props)
// Get the application name.
String grailsAppName = slurper.app.name
appender("CONSOLE", ConsoleAppender) {
encoder(PatternLayoutEncoder) {
pattern = "%d [${grailsAppName ?: 'Application Name Not Set'}] %-5level %logger - %msg%n"]
}
}
And this works, as long as I set 'logback.configurationFile' to point to it but I don't think replacing the single logback.xml the Tomcat 7 server with logback.groovy will work (but it is next on my list to try)
Other things I've tried
Any help would be appreciated
Upvotes: 2
Views: 1388
Reputation: 26
Steps to configure:
Add the below line in the grails-app/conf/application.yml or external application configuration file:
logging:
config: "C:/Application/config/logback.groovy"
file: "app.log"
path: "C:/Application/logs"
Put the configuration file in the above provided config path(in above e.g C:/Application/config/logback.groovy):
Ex.:
import grails.util.BuildSettings
import grails.util.Environment
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.core.ConsoleAppender
import ch.qos.logback.core.FileAppender
import static ch.qos.logback.classic.Level.DEBUG
def targetDir = System.getProperty("LOG_PATH")
def targetFile = System.getProperty("LOG_FILE")
appender("FILE", FileAppender) {
file = "${targetDir}/${targetFile}"
encoder(PatternLayoutEncoder) {
pattern = "%date %level %logger - %msg%n"
}
}
appender("STDOUT", ConsoleAppender) {
encoder(PatternLayoutEncoder) {
pattern = "%msg%n"
}
}
root(INFO, ["FILE", "STDOUT"])
All the applications can point to same configuration file by following the first step. So, all the logs will be generated according to the path and file specified in step 1.
System properties which the Logging System takes care of creating for you:
• ${PID} the current process ID.
• ${LOG_FILE} if logging.file was set in Boot’s external configuration.
• ${LOG_PATH} if logging.path was set (representing a directory for log files to live in).
• ${LOG_EXCEPTION_CONVERSION_WORD} if logging.exception-conversion-word was set in Boot’s external configuration.
So you can use them in logback.groovy file as shown above System.getProperty("LOG_PATH").
References:
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html
Upvotes: 1