Do you think IIT Guwahati certified course can help you in your career?
No
Introduction🎯
Play is based on a stateless, lightweight, web-friendly architecture. Play is built on Akka, and it has minimal resource consumption. It is a developer-friendly framework and very versatile. We will study in detail configuring logging.
Most of the Java libraries are also supported in Play.
For logging, Play uses SLF4J, which is backed by logback and is used as the default logging engine. Logback is seen as a successor to log4j. Logback's design is highly versatile, allowing it to be used in a variety of situations. Logback is categorised into three modules: logback-core, logback-classic, and logback-access.Configuring Logging can be done in manyways.
Now, we will dive deeper into the topic of configuring logging.
Default Configuration⭕
The play uses the following default configuration when working in dev mode.
<!-- The default logback configuration that Play uses in dev mode if no other configuration is provided -->
<configuration>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>
<logger name="play" level="INFO" />
<logger name="com.gargoylesoftware.htmlunit.javascript" level="OFF" />
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>
The following code is used in Play when in the default configuration:
<!-- The default logback configuration that Play uses if no other configuration is provided -->
<configuration>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<!-- increases the default queue size -->
<queueSize>512</queueSize>
<!-- don't discard messages -->
<discardingThreshold>0</discardingThreshold>
<!-- block when queue is full -->
<neverBlock>false</neverBlock>
<appender-ref ref="STDOUT" />
</appender>
<logger name="play" level="INFO" />
<logger name="com.gargoylesoftware.htmlunit.javascript" level="OFF" />
<root level="WARN">
<appender-ref ref="ASYNCSTDOUT" />
</root>
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
</configuration>
Some Noteworthy Points about These Configurations:✍✍
1️⃣These default configurations simply provide a console logger that displays ten lines of an error stack trace.
2️⃣In level messages, Play employs ANSI colour codes by default.
3️⃣In production, the console logger is placed behind the logback AsyncAppender by default.
4️⃣ When your application ends, you must cleanly shut off logback to verify that logged messages have been handled by asynchronous appenders (including the TCP appender) and that background threads have been halted.You must also explicitly define DelayingShutdownHook: <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/
📍For adding a file in the logger, the following appender is needed to be added in conf/logback.xml file:
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${application.home:-.}/logs/application.log</file>
<encoder>
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
Also, we can use the async appender to wrap the FileAppender:
This was all in the default configuration, now we will see security logging.
Security Logging✅✅
For security-related activities in Play, a security marker has been introduced and failed security checks are now recorded at the WARN level with the security marker set. This guarantees that developers are constantly aware of why a certain request is failing, which is critical now that security filters are set by default in Play.
The security marker also allows security failures to be triggered or filtered apart from conventional logging. For example, to deactivate all logging with the SECURITY marker set, add the following lines to the logback.xml file.
Now, if any custom application loader is used, then the configuring logging configuration needs to be manually invoked, which we are going to see in the next section.
Using a Custom Application Loader💻
It should be noted that if you are using a custom application in configuring logging loader that does not extend the usual GuiceApplicationLoader (for example, when utilising compile-time dependency injection), you must manually run the LoggerConfigurator to pick up your specific settings. This is possible with the following code like this:
class MyApplicationLoaderWithInitialization extends ApplicationLoader {
def load(context: Context) = {
LoggerConfigurator(context.environment.classLoader).foreach {
_.configure(context.environment, context.initialConfiguration, Map.empty)
}
new MyComponents(context).application
}
}
Now, it’s time to check on the custom configuration types of configuring logging.
Custom Configuration❓
If we want to do the custom configuration, then we need to specify our own logback file.
Using a Configuration File from the Project Source📃📃
By providing the file conf/logback.xml, we may give a default logging setup.
Using an External Configuration File⭕
A configuration file can also be specified using a System property. This is especially handy in production scenarios because the configuration file may be managed independently of your application source.
Using -Dlogger.resource
A configuration file can be specified to load from the classpath:
$ start -Dlogger.resource=prod-logger.xml
Using -Dlogger.file
A configuration file can be specified to load from the file system
$ start -Dlogger.file=/opt/prod/logger.xml
Now, let’s see the examples.
Examples🎯
Here's an example of a setup that uses both a rolling file appender and a separate appender for generating an access log.
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${application.home:-.}/logs/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- Daily rollover with compression -->
<fileNamePattern>${application.home:-.}/logs/application-log-%d{yyyy-MM-dd}.gz</fileNamePattern>
<!-- keep 30 days worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss ZZZZ} [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="SECURITY_FILE" class="ch.qos.logback.core.FileAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
<marker>SECURITY</marker>
</evaluator>
<OnMismatch>DENY</OnMismatch>
<OnMatch>ACCEPT</OnMatch>
</filter>
<file>${application.home:-.}/logs/security.log</file>
<encoder>
<pattern>%date [%level] [%marker] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="ACCESS_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${application.home:-.}/logs/access.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover with compression -->
<fileNamePattern>${application.home:-.}/logs/access-log-%d{yyyy-MM-dd}.gz</fileNamePattern>
<!-- keep 1 week worth of history -->
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss ZZZZ} %message%n</pattern>
<!-- this quadruples logging throughput -->
<immediateFlush>false</immediateFlush>
</encoder>
</appender>
<!-- additivity=false ensures access log data only goes to the access log -->
<logger name="access" level="INFO" additivity="false">
<appender-ref ref="ACCESS_FILE" />
</logger>
<root level="INFO">
<appender-ref ref="FILE"/>
<appender-ref ref="SECURITY_FILE"/>
</root>
</configuration>
This highlights the following helpful features:
1️⃣It employs RollingFileAppender, which can aid in the management of expanding log files.
2️⃣It saves log files to a directory outside of the program so that they are not impacted by upgrades, etc.
3️⃣The FILE appender employs an enhanced message format that third-party log analytics providers such as Sumo Logic can interpret.
Using the ACCESS FILE appender, the access logger is sent to a different log file.
Using the EvaluatorFilter and the OnMarkerEvaluator, all log messages with the "SECURITY" marker attached are recorded to the security.log file.
All loggers are set to an INFO threshold, which is a common setting for production logging.
Including Properties✅
Only the property application.home is exposed by default to the logging framework, which means that files can be accessed relative to the Play application.
<file>${application.home:-}/example.log</file>
We can include Play.logger.includeConfigProperties=true if we wish to refer to attributes that are defined in the application.conf file. All configuration-defined attributes will be accessible to the logger during application startup:
Log in can be done in the Akka system by changing akka logger to INFO by the following code.
<!-- Set logging for all Akka library classes to INFO -->
<logger name="akka" level="INFO" />
<!-- Set a specific actor to DEBUG -->
<logger name="actors.MyActor" level="DEBUG" />
We can configure an appender for the Akka loggers to include useful properties such as actor address and threads.
Using A Custom Logging Framework💻
Play by default uses Logback, but if another logging framework is supported via an SLF4J adapter, it may be configured to use that one instead. To do this, disablePlugins must be used to disable the PlayLogback sbt plugin.
lazy val root = (project in file("."))
.enablePlugins(PlayScala)
.disablePlugins(PlayLogback)
Now, we can use a custom logging framework. For example, here we use Log4J.
Play is based on a stateless, lightweight, web-friendly architecture. Play is built on Akka, it has minimal resource consumption. It is a developer-friendly framework and very versatile. Most of the Java libraries are also supported in Play.
Which logging engine is used by Play?
The Play uses SLF4J, which is backed by logback.
Define Logback in context of configuring logging.
Logback is seen as a successor to log4j. Logback's design is highly versatile, allowing it to be used in a variety of situations. Logback is categorised into three modules: logback-core, logback-classic, and logback-access.
Play uses which code in level messages?
In level messages, Play employs ANSI colour codes by default.
Which property is exposed by logging framework by default?
The property application.home is exposed by default to the logging framework.
Conclusion
In this article, we extensively discussed the configuring logging in Play. We started with the introduction of the Play. Then we saw the default configuration and learnt about security logging, custom logging and custom configuration. Furthermore,we saw properties utilisation and custom logging framework.