LoggingFacility - controlling the logger that will be used - castle-windsor

I'm using Log4Net with Castle.Windsor, the LoggingFacility, and Log4netIntegration. The project I'm using this in involves NHibernate, which also talks to log4net.
What I'm trying to do is split the logs such that NHibernate ends up in one log (data-log.txt), while all the system logging ends up in a separate log (system-log.txt).
The problem I'm having is that it seems like the Logger injected by windsor will only write to the root logger in my log4net configuration. NHibernate looks for loggers named NHibernate or Nhibernate., so I'm able to divert those logs into the data-log.txt appender, but it also writes to the root logger.
So what I've got right now is logs from Windsor and NHibernate all end up with the root logger, and logs from NHibernate additionally end up at the nhibernate specific loggers.
Here is my log4net config section in my app.config:
<log4net xsi:noNamespaceSchemaLocation="http://csharptest.net/downloads/schema/log4net.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<appender name="Console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%5level [%thread] (%file:%line) - %message%newline"/>
</layout>
</appender>
<appender name="AspNetTraceAppender" type="log4net.Appender.AspNetTraceAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
</layout>
</appender>
<appender name="NHibernateLogAppender" type="log4net.Appender.RollingFileAppender">
<file value="data-log.txt" />
<!-- various stuff -->
</appender>
<appender name="SystemLogAppender" type="log4net.Appender.RollingFileAppender">
<file value="system-log.txt" />
<!-- various stuff -->
</appender>
<root>
<level value="ALL" />
<appender-ref ref="AspNetTraceAppender" />
<appender-ref ref="Console" />
</root>
<logger name="SystemLogger">
<level value="ALL" />
<appender-ref ref="SystemLogAppender" />
</logger>
<logger name="NHibernate">
<level value="WARN" />
<appender-ref ref="NHibernateLogAppender" />
</logger>
<logger name="NHibernate.SQL">
<level value="DEBUG" />
<appender-ref ref="NHibernateLogAppender"/>
</logger>
and windsor is getting configured by code like so
container.AddFacility<LoggingFacility>(f => f.UseLog4Net().WithAppConfig());
How do I tell Windsor to aim for the SystemLogger instead of the root?
I know one way to do this is by creating a specific logger for each type that wants to use logging, but that seems like a great way to shoot yourself in the foot when you forget about that later.

Have just the root logger with all appenders. Then use appender whitelist and blacklist filtering on logger name:
<appender name="NHibernateLogAppender" type="log4net.Appender.RollingFileAppender">
<file value="data-log.txt" />
<!-- various stuff -->
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="NHibernate" />
</filter>
</appender>
<appender name="SystemLogAppender" type="log4net.Appender.RollingFileAppender">
<file value="system-log.txt" />
<!-- various stuff -->
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="NHibernate" />
<acceptOnMatch value="false" />
</filter>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="NHibernateLogAppender" />
<appender-ref ref="SystemLogAppender" />
</root>

Another route: I've submitted a patch to the Castle.Windsor team that allows users to specify a log name to use.
If you pull and build Windsor from github, LoggingFacility now has a configuration method ToLog(string LogName) that allows you to control which log will be used.

Related

How do i define some variables in logback.xml and be able to use that variable in my java code?

So, I am making a custom appender and i want elasticsearch url and index pattern to be saved in logback.xml and somehow get that value in my java code and i also want to be able to override it if i want in my append() function. I am using maven for my project if that helps.
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n</pattern>
</encoder>
</appender>
<appender name="myappender" class="esappender.EsAppender">
<m_elasticSearchUrl>http://xxx.xxx.xxx.x:xxxx</m_elasticSearchUrl>
<m_elasticSearchIndex>output-%d{yyyy-MM-dd}</m_elasticSearchIndex>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n</pattern>
</encoder>
</appender>
<logger name="esappender" level="debug" />
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="myappender" />
</root>
</configuration>
I thought directly metioning it in the tags will work and i could use it in my java code but it doesn't seem to work. When i search the internet i only find variables referenced in the logback itself but i want to be able to refrence it from append() function.

Gatling not logging request/response

Gatling is not logging anything (errors, request body, response body etc) even though I am using default logback.xml. Does anyone know what is missing?
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
<immediateFlush>false</immediateFlush>
</encoder>
</appender>
<!-- Uncomment for logging ALL HTTP request and responses -->
<logger name="io.gatling.http.ahc" level="TRACE" />
<logger name="io.gatling.http.response" level="TRACE" />
<!-- Uncomment for logging ONLY FAILED HTTP request and responses -->
<!-- <logger name="io.gatling.http.ahc" level="DEBUG" /> -->
<!-- <logger name="io.gatling.http.response" level="DEBUG" /> -->
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
Question was answered on the Gatling mailing list.
This issue is that CyberNinja has 2 slf4j implementation in his classpath (the logback Gatling provides plus one he added himself) so it fails to start.
And as he also configured a NopStatusListener (which is not here in Gatling's standard logback.xml file), slf4j fails silently.
Please try to add
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>

Logback - possible to get AsyncAppender's current queue's size?

Is it possible to get Logback's AsyncAppender's current queue size?
Here's the relevant section of our config:
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>1000</queueSize>
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="FILE" />
</appender>

conditions in logback configuration

I'm trying to remove redundant logback config files by using janino's conditional processing.
Below is the conditional logic which I had added
<root level="INFO">
<appender-ref ref="ROLLING" />
<!-- use console appender on windows, email appender on linux -->
<if condition='property("os.name").contains("win")'>
<then>
<appender-ref ref="CONSOLE" />
</then>
<else>
<appender-ref ref="EMAIL" />
</else>
</if>
</root>
but this throws the below errors
12:30:34,877 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter#90:55 - no applicable action for [if], current pattern is [[configuration][root][if]]
12:30:34,877 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter#91:10 - no applicable action for [then], current pattern is [[configuration][root][if][then]]
12:30:34,877 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter#92:35 - no applicable action for [appender-ref], current pattern is [[configuration][root][if][then][appender-ref]]
12:30:34,877 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter#94:10 - no applicable action for [else], current pattern is [[configuration][root][if][else]]
12:30:34,877 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter#95:35 - no applicable action for [appender-ref], current pattern is [[configuration][root][if][else][appender-ref]]
The configuration works fine if I remove the conditional logic and use something like
<root level="INFO">
<appender-ref ref="ROLLING" />
<appender-ref ref="CONSOLE" />
<appender-ref ref="EMAIL" />
</root>
How can I configure this correctly in such a way that the CONSOLE appender is used only on Windows and the EMAIL appender everywhere else?
Can you try the latest version? I used the latest version and the above conditional statements work perfectly fine

How can I configure logback conditionally based on context name?

I have three separate projects, each with their own embedded logback.xml files. Each of these files includes a common logging config file in the user's home durectory:
<include file="${user_home}/loggingConfig.xml"/>
After the include, I have this specification:
<root level="error">
<appender-ref ref="${appender:-console}" />
</root>
This allows the user to configure their log levels and appenders, and have them applied by the core logging config file.
For example, in ~/loggingConfig.xml I have this line:
<property name="appender" value="file" />
But co-workers who prefer console logging leave that line out.
The problem is I would like to use different appenders for each log file. In otherwords, I would like to conditionally set a different appender based on which project is reading the customized config file.
I realize I could configure each project to read differently named config files, but I would like to eliminate the clutter and allow for shared configuration as well.
The documentation is a bit spare for advanced configuration, but I found that you can use the logback context name as a variable with conditional logging. So for each project I define a custom context name in the projects logback.xml file:
<contextName>project1</contextName>
etc...
Then in my ~/loggingConfig.xml file I can do this:
<property name="appender" value="file" />
<!--if condition='property("CONTEXT_NAME").equalsIgnoreCase("project1")'>
<then>
<property name="appender" value="file" />
</then>
</if-->
<if condition='property("CONTEXT_NAME").equalsIgnoreCase("project2")'>
<then>
<property name="appender" value="console" />
</then>
</if>
<if condition='property("CONTEXT_NAME").equalsIgnoreCase("project3")'>
<then>
<property name="appender" value="file" />
</then>
</if>
This can get a bit clunky, but in reality I am using this solution to configure properties used by a single appender for different projects, while still having a graceful fallback to a default value for projects that don't have their own conditional block.
In case this helps anyone else, this is how I set up conditional logback configuration with a property that can contain multiple appenders:
<root level="${logback.loglevel}">
<if condition='isDefined("logback.appenders")'>
<then>
<if condition='property("logback.appenders").contains("CONSOLE")'>
<then>
<appender-ref ref="CONSOLE"/>
</then>
</if>
<if condition='property("logback.appenders").contains("FILE")'>
<then>
<appender-ref ref="FILE"/>
</then>
</if>
<if condition='property("logback.appenders").contains("GELF")'>
<then>
<appender-ref ref="GELF"/>
</then>
</if>
</then>
<else>
<appender-ref ref="CONSOLE"/>
</else>
</if>
</root>