log4net: deny other components except than a specific one from logging - nhibernate

Assume you are using some libraries like NHibernate or Castle ActiveRecord that use log4net internally. Your application uses log4net too. It's possible to configure all applications to save logs into file or any other output. But the problem is by enabling log4net for my own application, other programs save their log into the log file and causes it grow very fast with information that I don't need at the moment.
How can I route logs of each application to different outputs or at least how can I deny other applications from logging?

NHibernate/Castle Active Record generate lot of log information but that is all DEBUG level logging. So you can turn down your log level from "ALL" to "INFO" or "ERROR" in config file and you should be OK.
log4Net also support named logger and logger hierarchy. I am sure both NHibernate/Castle would be using named logger. So you can choose to ignore that particular named logger using configuration. See log4Net help where they have used have different logging level for Com.Foo library.
Using named logger is a typical way of separating log traces from different components/modules/libraries etc. Each application (as in different process) would have different configuration file and you can always have different log files to separate the log traces.

Just direct different loggers to different appenders.
Pseudo example:
<log4net>
<appender name="MyAppender" type="log4net.Appender.FileAppender">
<!--appender properties (file name, layout, etc)-->
</appender>
<appender name="NHAppender" type="log4net.Appender.FileAppender">
<!--ditto-->
</appender>
<logger name="MyAppMainNamespace">
<level value="INFO"/>
<appender-ref ref="MyAppender" />
</logger>
<logger name="NHibernate">
<level value="ERROR"/>
<appender-ref ref="NHAppender" />
</logger>
</log4net>

Related

EclipseLink internal logging statements go through Log4j2

I want the internal logging statements from EclipseLink (version 2.7.x) to be logged through my Log4j2 setup.
I know there's a bug report on this (https://issues.apache.org/jira/browse/LOG4J2-444) which never got solved. I also know, there is a wiki how to implement an own logger (https://wiki.eclipse.org/EclipseLink/Examples/Foundation/Logging).
Since I think someone must have already addressed this problem (since there should be thousands of EclipseLink + log4j2 setups out there) and come out with a reliable solution, my question would be:
Where can i find it?
I am not sure this solution is the best, but
The library contain EclipseLink logger impelementation for slf4j:
https://search.maven.org/artifact/org.eclipse.persistence/org.eclipse.persistence.extension
You can set it to use in persistence.xml:
<property name="eclipselink.logging.logger" value="org.eclipse.persistence.logging.slf4j.SLF4JLogger" />
Now you need bridge slf4j -> log4j2:
https://search.maven.org/artifact/org.apache.logging.log4j/log4j-slf4j-impl
And finally log4j2.xml: <Logger name="eclipselink.logging" level="ALL"> ... </Logger>
level="ALL" because what exatly will be logged is configured in persistence.xml e.g. eclipselink.logging.level property an so on:
https://wiki.eclipse.org/EclipseLink/Examples/JPA/Logging

Log4Net setting contexts for multiple requests with multiple file logging?

We're trying to use log4net log processes requested to a WCF service. For that, our goal was to log in different files depending of some arguments of the request. For that, we have used Context properties of log4net, setting the context of it in every call to the service, but, because of possible concurrency issues, we can't use "GlobalContext".
Thinking(it seems that thinking wrong) that wcf uses one thread per call, we set ThreadContext properties when the request was received, such as this:
GlobalContext.Properties("fulldate") = Now.ToString("yyyyMMdd")
GlobalContext.Properties("date") = Now.ToString("yyyyMM")
ThreadContext.Properties("center") = center //it comes with the request header
XmlConfigurator.Configure()
And the appender is defined in the config file like this:
<appender name="IntAppender" type="log4net.Appender.FileAppender">
<file type="log4net.Util.PatternString" value="c:\\Logs\\%property{center}\\%property{date}\\%property{fulldate}\\theLog.log" />
<datePattern value=".yyyyMMdd.'log'" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level - [%ndc] %message%newline" />
</layout>
But sometimes, logs that should be in one center's log is in an another center's log, and it seems that the problem is how WCF manages threads. I don't want to set the service to be instanced per request. Can you point me a link or doc of how WCF manages threads? I haven't been able to find one. And is it possible to accomplish what I'm trying to do? That is, to log all request of one center in that center's log file.
Thanks.
That won't work, and it's nothing to do with WCF's thread model.
Log4net shares your single defined appender between loggers, and thus between threads. When one thread changes the file value on the file appender, this applies to all threads so it's a race condition to see what log the error actually ends up in!
To accomplish this you need to have one file appender per log file, per "center". If the centers are known beforehand you could set them up in config, or otherwise it's easy enough to set them up programatically

logback additivity is false still hibernate sql logs generated on Tomcat console

How to generate 2 log files; One will log Hibernate sql messages generated by show-sql = true property. And another will log rest of the Hibernate logs.
I have configured logback.xml as shown below:
<logger name="org.hibernate" level="debug" additivity="false">
<appender-ref ref="hibernate" />
</logger>
<logger name="org.hibernate.SQL" additivity="false">
<appender-ref ref="hibernate-sql" />
</logger>
It is generating 2 log files as expected. However, It is duplicating hibernate-sql log messages in Tomcat console, hibernate appender, and hibernate-sql appender.
How could I restrict logback to generate Hibernate sql logs in hibernate-sql appender only?
Hibernate writes the generated SQL in two distinct and completely separate ways. When you set the property hibernate.show_sql to true, it tells Hibernate to write generated SQL to stdout. No logging framework is involved in this in any way. That's why you should pretty much never use it. Just remove that property from your config, and the SQL in the Tomcat console will go away.
The second way Hibernate writes the SQL, and the way you should use, is that it sends it to the logging framework under the org.hibernate.SQL logging category. It has no connection at all with hibernate.show_sql.
As an additional tidbit, in case you don't know, Hibernate also logs all values bound to parameters of the prepared statements using the org.hibernate.type category. This is something you can't get with hibernate.show_sql, so using Hibernate's logging instead of show_sql is both more flexible and more informative.

NHibernate messages going to the console no matter what

I have a console app using Fluent NHibernate. I have configured it to log to various places using log4net. And it works great. I can see the SQL that I want to see and can sent log output to various appenders. The problem is that I cannot suppress the log4net sql output going to the console.
The extra console output is not being controlled by my log4net config settings. It always appears, no matter if I turn off all appenders.
Any suggestions?
Do you have this property set to true in your nhibernate section in your app.config?
<property name="show_sql">true</property>
If so set it to false.
Edit
Here is a sample piece of code from the nhibernate source:
log.Debug(logMessage);
if (LogToStdout)
{
Console.Out.WriteLine("NHibernate: " + statement);
}
In the above code LogToStdout is directly linked to the show_sql configuration property. If you have this set to true nothing will stop it from writing to the console. In regards to your comment you cannot control this via log4net. You can only control what you are doing with the log.Debug(logMessage) via log4net.
To disable any logs put the following code:
< add key="nhibernate-logger" value="" />
into your appSettings section.
The NHibernate logs don't help me much, I'll turn them on when I need them... I add these settings to the log4net section of my app.config:
<logger name="NHibernate">
<level value="OFF" />
</logger>
<logger name="NHibernate.SQL">
<level value="OFF" />
</logger>

WAS hosted WCF service and log4net

I'm facing a problem when trying to log my application using log4net.
My application consists of a WCF service, and clients connecting to it.
Logging at client-side is not a problem, everything works perfectly.
Here is how my server-side is made:
A WCF dll, which contains my service's contract and base implementation (including error handling). Actual operations are made in a separate business layer, which throws the needed exceptions which are caught by the implementation (and sent back using FaultContracts).
A data layer (not a problem here).
A "Utils" library, which contains my wrapper log methods.
My log4net.config file is the following:
<?xml version="1.0" encoding="utf-8" ?>
<log4net debug="false">
<appender name="TechnicalFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="c:\\log\\technical.log"/>
<param name="AppendToFile" value="true"/>
<param name="RollingStyle" value="Date"/>
<param name="DatePattern" value="'_'yyyyMMdd-HH"/>
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%-5t] %-5p - %m%n"/>
</layout>
</appender>
<root>
<level value="ALL"/>
</root>
<logger name="TechnicalLog">
<level value="ALL"/>
<appender-ref ref="TechnicalFileAppender"/>
</logger>
</log4net>
So when an error occurs in the business layer, it is captured, logged and transformed into a FaultException. There is the problem. No log file is created.
I googled and found some clues (access rights generally, but I used ProcMon and found no call to the desired file or directory).
I'm a bit lost now, I don't know what to try.
I publish my service using the "publish" command in visual studio, so on the server I have my application directory, inside there is a svc file, a web.config file, and then a bin directory with all my dll's including the log4net.dll, and log4net.config.
I tried to copy that config file in the root of my application without success.
I also tried to place the
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
statement in my WCF's AssemblyInfo.cs (it was originally in the Utils's AssemblyInfo.cs), but without any success.
Thanks for you help, any idea is welcome !
I am pretty sure that log4net does not find the configuration file.
I had the same issue and I think I solved it by having an application setting in the web.config file that contains the full path to the log4net config file. In my wrapper I made sure that log4net is configured by calling the ConfigureAndWatch method if log4net is not configured yet.
Alternatively you could simply copy the log4net configuration to the web.config file (but I would not do that because you loose the ability to change the log settings for the running system). In that case you need to add this to you AssemblyInfo.cs (or some other file if you prefer):
[assembly: log4net.Config.XmlConfigurator()]
If that still does not help then I recommend to turn on internal debugging.