Playspec not picking logger configuration - logback

In my play application, I have provided a logback.xml. The configuration for controller AnswerController is <logger name="controllers.AnswerController" level="TRACE" additivity="false">
<appender-ref ref="STDOUT"/> </logger>
But when I run my test case, I don't see any logs. Do I need to configure logback explicitly? I am using custom application loader.
Why are the logs now showing?

I added the LoggerConfigurator to my code and it seem to work (still early day to confirm if this will create some side effect. Though I don't the flow of why this makes things work (BTW, I do the same for my customer application loader as well)
class AnswerControllerUnitSpec extends PlaySpec with BeforeAndAfterAll with BeforeAndAfterEach with OneAppPerSuiteWithComponents{
override def beforeEach() = {
println("------------new test -----------------")
}
LoggerConfigurator(context.environment.classLoader).foreach {
_.configure(context.environment, context.initialConfiguration, Map.empty)
}
...
}

Related

What is the way to identify and enable logging for a library (for a class and at root level)

I am using scalardb library. I want to enable logging in it.
I believe the way to enable logging is to add a line similar to <logger name="classnameinclduingpackage" level="DEBUG" additivity="false"> <appender-ref ref="FILE"/> </logger> in logback.xml.
I can see that Scalardb support Sl4J and some of its classes use the logger. - https://github.com/scalar-labs/scalardb/tree/master/src/main/java/com/scalar/db/transaction/consensuscommit
Question 1
If I want to enable logging for each class, would I have to add, for example, the following entry in logback.xml?
<logger name="com.scalar.db.transaction.consensuscommit.CommitHandler" level="ALL" additivity="false"> <appender-ref ref="STDOUT"/> </logger>
Adding each class like this would take a lot of time and I might miss some classes. Is there a way to provide a selector that would enable logging in all classes?
Would this work?
Is this the right way?

Can micronaut log access logs with logback?

I'm trying to setup access-logs in micronaut, but, as logback-access library uses a servlet filter, I don't see a straight-forward way to do it.
Is there a different solution? Some hidden Micronaut config or a trustable adapter of the filter (A Micronaut Filter wrapper for Servlet filters would be great)
The Micronaut http server supports automatically adding a LoggingHandler, you have to supply micronaut.server.netty.logLevel: <<level>> in your configuration where level is one of TRACE, DEBUG, INFO, WARN, ERROR. I don't know if that will provide the same detail that logback-access does, but you can give it a try.
EDIT: Be sure to also configure a logger. For example in logback:
<logger name="io.netty.handler.logging" level="TRACE"/>
I used the mn CLI to create my application (using groovy as the language for my development), and mn code generated a trivial logback.xml. from the 1st time I ran my application, logging was working.
Here's what was generated OOTB:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>true</withJansi>
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Then I went to the logback home page and used its code generator to convert the mn seed xml file to logback.groovy.
here's the result, after I added my logger for the hello.world package.
// ----------------------------------------------------------
//
// Built on Sun Jul 07 02:41:38 CEST 2019 by logback-translator
// For more information on configuration files in Groovy
// please see http://logback.qos.ch/manual/groovy.html
// For assistance related to this tool or configuration files
// in general, please contact the logback user mailing list at
// http://qos.ch/mailman/listinfo/logback-user
// For professional support please see
// http://www.qos.ch/shop/products/professionalSupport
// ----------------------------------------------------------
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.core.ConsoleAppender
import static ch.qos.logback.classic.Level.DEBUG
appender("STDOUT", ConsoleAppender) {
withJansi = true
encoder(PatternLayoutEncoder) {
pattern = "%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n"
}
}
root(INFO, ["STDOUT"])
logger("hello.world", DEBUG)

remove logger from configuration

When I use logback as logging framework, I add logger configuration on runtime for debugging. For example set "org.springframework" to debug level.
after I find the data I need I want to remove this configuration without restarting the application.
How can I do that?
You have two options depending upon how you want to modify the log level.
First option - using logback.xml
Logback xml provides an option to periodically scan the configuration. By setting that, you ask the logger framework to periodically update its in-memory setting to sync with the XML configuration. When you want to enable debug mode, XML configuration will look as below:
<configuration scan="true" scanPeriod="30 seconds">
<!-- Appender configurations here -->
<logger name="org.springframework" level="debug" additivity="false">
<appender-ref ref="YOUR_APPENDER_NAME"/>
</logger>
<!-- Other logger configurations (including root) go here -->
</configuration>
After you complete your task, you can either delete that logger entry or set the level to ERROR to stop logging for that package.
Second option - In-memory
If you don't want to touch your logback.xml, but somehow handle it in runtime (say, using some REST APIs of you application), you may get the specific logger instance and set the level to DEBUG. Once you complete your activity, you may set the level to 'null' so that the level is inherited from the parent. Sample code will be as below:
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import org.slf4j.LoggerFactory;
.....
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = context.getLogger("org.springframework");
logger.setLevel((Level.toLevel("DEBUG"));
// Do your task
logger.setLevel(null); // When we do this, level will be inherited from parent.
logback has an option that allows periodic rescanning of the configuration file to look for changes.
<configuration scan="true">
...
</configuration>

log4net logger configuration

Is it possible to set the logger from configuration. I have a web app
using a framework. The framework is extensible and has the logger.
When I log, currently, the logger is set to the framework class.
Is it possible that I can configure my web app and set the logger for the web app to
loggerForWebApp and the logger for a console app (which is using the
same framework) to loggerForConsoleApp?
In addition to the root logger (which must always be there) you can have named loggers with their own appender-refs and levels.
For instance, you could have something like this:
<root>
....
</root>
<logger name="loggerForWebApp">
<level value="WARN" />
<appender-ref ... />
</logger>
<logger name="loggerForConsoleApp">
<level value="WARN" />
<appender-ref ... />
</logger>
In code, you would summon these loggers by their name:
var log = LogManager.GetLogger("loggerForWebApp");
Most definitely, and this is one of the great things about log4net: it can log out to a wide range of loggers.
For examples of the appenders, see here. Probably the most common one in use is the RollingFileAppender, but the ConsoleAppender can be very handy for console applications. Alternatively the TraceAppender can write out to the standard .NET trace listeners for further redirection (or display in the debug Output window in Visual Studio).
To create your own, implement IAppender.
details to follow

Log4net - log parts of code, used in a couple of methods

I have some trouble.
My application could be divided to 3 logical parts (import, processing and export). There are some parts of code which are used in several parts of my application. How can I determine which part of code called my log4net object?
What is best practice to log info in parts of code which are called from several places in the application?
I want to turn on and off the ability to log parts of my application from a config file.
If I turn off logging for the processing part of my app, how could I log info in the export part of my app when both of them use one method, in which I initialize my logger object?
You could add a separate logger for each section of your app that you want to log and then turn them off and on as needed. They would all be independent from one another and this can all be setup via the config.
By setting the additivity property to false, the loggers will all be independent of one another. Here's an example of the config portion:
<logger name="Logger1" additivity="false">
<level value="INFO" />
<appender-ref ref="Logger1File" />
</logger>
To use it in your code, reference it like this:
private static ILog _Logger1= LogManager.GetLogger("Logger1");
Anything you log to Logger1 will be separate from any other logger, including the root one.
log4net provides contexts for this purpose. I would suggest using a context stack like this:
using(log4net.ThreadContext.Stacks["Part"].Push("Import"))
log.Info("Message during importing");
using(log4net.ThreadContext.Stacks["Part"].Push("Processing"))
log.Info("Message during processing");
using(log4net.ThreadContext.Stacks["Part"].Push("Export"))
log.Info("Message during exporting");
The value on the stack can be shown in the logs by including %property{Part} in a PatternLayout.