Configuring commons logging in Glassfish - glassfish-3

I am using commons logging for my application running on Glassfish V3.1(I am new to glassfish). I have different applications running on Glassfish under ../domain1 folder(Developers machine). I am using an XML to configure Logging.Following is the my xml config
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration>
<appender name="file"
class="org.apache.log4j.RollingFileAppender">
<param name="maxFileSize" value="100KB" />
<param name="maxBackupIndex" value="5" />
<param name="File" value="/home/phanikumar/Desktop/debug.log" />
<param name="threshold" value="debug"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{DATE} %5p %c{1}:%L - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="warn" />
<param name="LevelMax" value="fatal" />
</filter>
</appender>
<logger name="com">
<level value="DEBUG" />
<appender-ref ref="file"/>
</logger>
<root>
<appender-ref ref="file" />
</root>
</log4j:configuration>
In this config file I have explicitly mentioned the file to be in a specific location but it never did.Is there any problem with the logger file?Am I missing some thing?
or
Is there any way that I can configure my logs to be in a specific location? I have seen the server.log file and it is unsuitable for my requirement as the logs of all applications are logged in a same file.
Please kindly help me.

SOLUTION
Add a Properties file named commons-logging.properties in the class path.
And add the following property
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
This initializes Logging to Log4j Logger
Then it works perfectly.
EDIT:
Usually, by default commons logging searches for loggers like log4j. If the above solution doesnt work, one needs to check if the commons-logging jar file is corrupted i.e, check if the class files like org.apache.commons.logging.impl.Log4jLogger is present.

Related

Using log4net RemoteSyslogAppender with .Net Core

I am trying to use both a RollingFileAppender and RemoteSyslogAppender in a .Net Core app with log4net 2.0.8. Here's what my log4net.config file looks like:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<root>
<priority value="Debug" />
<appender-ref ref="FileAppender" />
<appender-ref ref="SyslogAppender" />
</root>
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\ProgressiveLogs\ProgLoggerNetCoreDemo.log" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="14" />
<maximumFileSize value="15000KB" />
<datePattern value="yyyyMMdd" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="SyslogAppender" type="log4net.Appender.RemoteSyslogAppender">
<remoteAddress name="Address" value="syslogServer" />
<remotePort name="Port" value="514" />
<layout type="ProgressiveLogging.Core.ProgLayout.ProgPatternLayout, ProgressiveLogging.Core">
<conversionPattern value="%json%newline" />
</layout>
</appender>
</log4net>
As you can see, I'm using a custom pattern for the syslog appender. When I run my .Net Core version of the app (which uses a .Net Standard 1.3 build of ProgressiveLogging.Core), I do get output to the RollingFileAppender file, but not the RemoteSyslogAppender. When I run my my test app using .Net 4.6.2 (using a .Net 4.0 build of ProgressiveLogging.Core) it outputs fine to both appenders.
I have found documentation online stating that the log4net RemoteSysLogAppender is supported for .Net Standard 1.3 (https://logging.apache.org/log4net/release/framework-support.html).
Has anyone else been able to get something similar to work (using RemoteSysLogAppender with .Net Core or .Net Standard)?
Added 2017-09-01: I have done further investigation and find that this boils down to a major difference in how UDP packets are built and sent between .Net 4.* and .Net Standard. .Net 40, which works, sends the UDP message all in one datagram (packet), whereas .Net Standard splits the message up into a bunch of packets, which packets appear to be delimited by the commas in our JSON message. Apparently, our syslog daemon can't understand such nonsense. I'm going to do some direct testing to see if I can make a difference in what gets sent via UDP to syslog.
After much more thorough investigation I have found that there is not a problem with log4net RemoteSyslogAppender. My problem was that I was formatting the JSON message that ultimately was sent by the System.Net.Sockets.UdpClient. The formatting added CRLFs to the string, which then the UdpClient delimited the message and fragmented on those CRLF boundaries. That was making no sense to Syslog. It was a very simple fix - remove the formatting options from the call to NewtonSoft.Json.JsonConvert.SerializeObject. I had copied a snippet from somewhere that included formatting of the Json string. Works perfect now!

Can't enable spring orm/transaction logging even when log4j.xml is configured

I have a configuration problem regarding enabling spring related logging in my application as I'm using EclipseLink,JPA 2.0 & Spring 4.0, I need to verify when the entity manager is closed or cleaned up while doing transactions.
My application is JTA enabled so everything is controlled by my container (Websphere).Here is my log4j.xml
<?xml version="1.0"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true" xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- CONSOLE normally used in desktop environment -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<param name="Threshold" value="DEBUG"/>
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%-8X{context}] %-5p %-40.40c{2} - %m%n"/>
</layout>
</appender>
<appender name="FILE_APPENDER" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="C:\\proj\\was\\logs\\spring.log"/>
<param name="DatePattern" value="'-'yyyy-MM-dd'.txt'"/>
<param name="Threshold" value="DEBUG"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-4p [%t] %C{2} - %m%n"/>
</layout>
</appender>
<!-- Spring -->
<logger name="org.springframework.transaction" additivity="false">
<level value="DEBUG" />
<appender-ref ref="FILE_APPENDER"/>
</logger>
<logger name="org.springframework.orm.jpa.EntityManagerFactoryUtils" additivity="false">
<level value="DEBUG" />
<appender-ref ref="FILE_APPENDER"/>
</logger>
<logger name="org.springframework.orm.jpa" additivity="false">
<level value="DEBUG" />
<appender-ref ref="FILE_APPENDER"/>
</logger>
<root>
<level value="DEBUG" />
<appender-ref ref="console" />
<appender-ref ref="FILE_APPENDER" />
</root>
</log4j:configuration>
I have also tried many solutions like this, but it didn't help.Please help me where I'm going wrong?
From your comment, it seems that you not have the adapter slf4j to log4j. Or have another adapter.
To check the adapter in use, use the code:
StaticLoggerBinder binder = StaticLoggerBinder.getSingleton();
System.out.println(binder.getLoggerFactoryClassStr());
If it is not the log4j12 adapter showing:
Check on the war, you should have a slf4j-api-xxxx.jar in WEB-INF/lib.
put the slf4j-log4j12-xxxx.jar (same version) into WEB-INF/lib
if there is logback-xxxxx.jar remove it, else slf4j will take it to log
if there is log4j-over-slf4j-xxxx.jar remove it, else it is possible that log4j log will be redirected to slf4j that will redirect to log4j and so on..
there is perhaps another adapter (slf4j-jcl-xxxx.jar for instance) that need to be removed.
Logger Hierarchy
In most logging systems, logger has the parent and child relationship, in which children inherit
Level
Appender
ResourceBoudle
from father logger. And the root logger exists at the top of inheritance. The children will send log event to father logger depending on additivity. False means it will not send log to father logger.
So, from your original config, you didn't allow Spring related logger to send log to your root logger.
Suggestions
So, now we understand that we should set additivity to true and change the log4j config into like following:
<logger name="org.springframework.transaction" additivity="true"/>
<logger name="org.springframework.orm.jpa.EntityManagerFactoryUtils" additivity="true"/>
<logger name="org.springframework.orm.jpa" additivity="true"/>
<root>
<level value="DEBUG" />
<appender-ref ref="console" />
<appender-ref ref="FILE_APPENDER" />
</root>
More
Here and here are the blog posts I write about slf4j & log4j & logback, which Spring uses, and you can read to enhance the understanding of logging;
If you change the additivity and still can't see the log in console/file, I suggest you set a breakpoint at any logging line in EntityManagerFactoryUtils, then step in code to see what's wrong;
Update
The logger of EntityManagerFactoryUtils, as we can from source code, is not slf4j or log4j. It is commons logging. So your log4j config about this class will not work.
import org.apache.commons.logging.Log;
private static final Log logger = LogFactory.getLog(EntityManagerFactoryUtils.class);
In order to make your config work, you should make some bridge work:
exclude commons-logging.jar from spring-orm
add jcl-over-slf4j.jar
make sure you have slf4j-api & slf4j-log4j
By looking at the Jars on your classpath some cleaning is probably required, but in order to do so we need to understand what each of the Jars do.
log4j-1.2.9.jar
Is the implementation of Log4j. This one is required in order to log anything using Log4j and of course reading your log4j configuration file.
slf4j.api-1.6.1.jar
Is the Slf4j API library, Only required if you or some of your third-party dependencies use Slf4j for logging, which seem quite likely as you already have it on your classpath. This allows you to write to the logs through Slf4J API, e.g:
private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(MyLoggingClass.class);
slf4j.jdk14-1.6.1.jar
Is a JDK 1.4, also known as java.util.logging binding for Slf4j used to use java.util.logging as the logging engine when Slf4j is used. Obviously we're going to use log4j as the logging implementation and not java.util.logging meaning this should be removed.
slf4j-log4j12-1.7.12.jar
Is a log4j 1.2 binding for Slf4j, required to route logs from Slf4j to your Log4j implementation. This one is only required if slf4j.api-1.6.1.jar was required. However, versions should be harmonized in order to avoid conflicts.
commons-logging-1.1.1.jar and
commons-logging.jar
As far as I can tell those are both the commons logging framework. This is the logging framework used by Spring. However, you should only have one of those on your classpath, where I recommend using the one which reveals it's version.
Having the correct Jars on your classpath, commons logging should be able to pick up the correct logging implementation for you (which in your case is Log4j). If that's not the case, explicitly put a file named commons-logging.properties on the root of your classpath and add the following line to it:
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4jLogger
forcing it to use Log4j as the logging implementation.

Logs from java.util.logging in ICM

In my cartridge I use an external library that logs with java.util.logging. I want to redirect the log to SLF4J/logback, but somehow this does not work as I would expect it (logs are empty). Here is the relevant logback configuration:
<appender name="PayPal_LogFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>TRACE</level>
</filter>
<File>${intershop.logfile.Directory}/paypal-${intershop.logfile.NamePostfix}.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${intershop.logfile.Directory}/paypal-${intershop.logfile.NamePostfix}.%d{yyyy-MM-dd}.log</FileNamePattern>
</rollingPolicy>
<encoder>
<pattern>
[%date{yyyy-MM-dd HH:mm:ss.SSS Z}] %-5level ${intershop.HostName} ${intershop.InstallationID} ${intershop.ServerName} [%mdc{requestsite}] [%mdc{requestapplication}] %logger [%marker] [%mdc{request.type}] [%mdc{session.id}] [%mdc{request.uuid}] "%thread" %msg %ex%n
</pattern>
</encoder>
</appender>
<logger name="com.paypal" additivity="false">
<level value="TRACE" />
<appender-ref ref="Error" />
<appender-ref ref="PayPal_LogFile" />
</logger>
JUL logs in DEBUG level, DEBUG level is allowed for com.paypal and I believe that this should be translated to INFO in SLF4J. What's wrong?
I'll answer my own question.
The reason for the trouble is the additivity="false" property of the logger.
Background: Routing from other logging frameworks to SLF4J is generally easy via the so called bridges unless we speak about JUL. See the details here. ICM implements its own bridge between JUL and SLF4J and there is a subtle bug inside. The logging handler of the ICM is attached to the root level and any appender with additivity="false" won't work because it will never reach the root level.
The bug seems to be here com.intershop.beehive.core.internal.log.JavaLoggingAdapter:
handler = new JavaLoggingHandler();
handler.setLevel(Level.ALL);
Logger root = LogManager.getLogManager().getLogger("");
root.addHandler(handler);
I've changed the additivity to true although I'm not very happy about this and now I can explore the third party logs.

.NET Web Deployment Tool with log4Net: Not overwriting logs

I'm using the Web Deployment Tool to build and release an MVC site from VS 2010 to a server running IIS. I also have log4net logging to a subdirectory off of the root of the web application I'm deploying to. I already figured out how to keep write permissions intact when deploying with this tool on that directory, but now I'm running into the problem that I'd rather not lose the logs when deploying, and also, the deploy is failing because the log file that log4net is using is "used by another process" (presumably w3wp) and won't let the deploy continue.
So, I'd like to preserve the log files and not delete or overwrite them, for auditing purposes. Is there a way to do that within the confines of the Web Deployment Tool?
EDIT: Here's the applicable bits of the log4net configuration, in Web.Config.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net" />
</configSections>
<log4net>
<appender name="RollingLog" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Logs\Log.txt" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="20" />
<maximumFileSize value="10MB" />
<datePattern value="yyyyMMdd" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="{%level}%date{MM/dd HH:mm:ss} - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingLog" />
</root>
</log4net>
</configuration>
Found it by hunting around: there is a "skip" parameter you can tack on to the command when you call the pre-packaged deploy script. You HAVE to use a regular old CMD prompt for this; Powershell's crazy escaping of quotes makes it near-impossible to get right, so I gave up. Anyway, here's the end result I came up with:
.\MyProject.deploy.cmd /Y /M:MyServerName "-skip:skipAction=Delete,objectName=filePath,absolutePath=Logs"
"MyProject.deploy.cmd" being the name of the prepackaged deploy command, "MyServerName" being the name of the server I was deploying to, and "Logs" being the name of the folder I wanted to skip. This command seems to leave alone that Logs directory and deploy anything else that matters.
Source where I started to hone in on things: http://blogs.iis.net/msdeploy/archive/2009/04/23/what-has-changed-about-skip-replace-rules-in-rc.aspx
Set locking model of your appender to minimal lock and everything will be fine:
<appender name="RollingLog" type="log4net.Appender.RollingFileAppender">
...
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
...
</appender>
log4net.Appender.FileAppender (see remarks)

log4Net EventlogAppender does not work for Asp.Net 2.0 WebSite?

I have configured log4Net EventLogAppender for Asp.Net 2.0. However it does not log anything. I have following in my Web.Config.
<log4net>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<param name="LogName" value="Test Log" />
<param name="ApplicationName" value="Test-Web" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<root>
<priority value="ERROR"/>
<appender-ref ref="EventLogAppender"/>
</root>
<logger name="NHibernate">
<level value="ERROR" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
I already have Test-Log Event Log created and AspNet user has permission on the Event Log registry entry. I also have log4Net configured in Global.asax Application_Start.
log4net.Config.XmlConfigurator.Configure();
Update : I switched on the log4net internal debugging and found the following error in the trace.
log4net:ERROR XmlHierarchyConfigurator: Could not create Appender [EventLogAppender] of type [log4net.Appender.EventLogAppender]. Reported error follows.
System.Security.SecurityException: The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security.
at System.Diagnostics.EventLog.FindSourceRegistration(String source, String machineName, Boolean readOnly)
at System.Diagnostics.EventLog.SourceExists(String source, String machineName)
at System.Diagnostics.EventLog.SourceExists(String source)
at log4net.Appender.EventLogAppender.ActivateOptions()
at log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseAppender(XmlElement appenderElement)
Update 2 : It finally works if I create the Event Source (Test-Web) using a console based application in c# and then using the Web Application.
There's some very simple steps to get Log4Net working with the event log with ASP.NET.
Your options are:
Change the app pool
Run the application pool as LocalSystem
Or...set an application name, add a registry key
Configure your config file first so there is an application name.
This is important if you are having a permissions issue, because if you peer at the source you'll see the EventLogAppender defaults the application name (the source column in the event log) to:
System.Threading.Thread.GetDomain().FriendlyName
This requires your application to create a registry key each time the name changes, and is a bit messy. So the best solution is to set your application name. Here's an example EventLogAppender section that sends every error level, the ApplicationName line is the important part:
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<param name="ApplicationName" value="MY-AWESOME-APP" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="INFO" />
</evaluator>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO"/>
<param name="LevelMax" value="FATAL"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<!-- The event log already logs the date so just log the message -->
<conversionPattern value="%message" />
</layout>
</appender>
Before making this change, do the following:
Create a registry key
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application\MY-AWESOME-APP
Create a string value inside this
Name it EventMessageFile, set its value to
C:\Windows\Microsoft.NET\Framework\v2.0.50727\EventLogMessages.dll
That path appears to work in both 64 bit and 32 bit environments.
With this technique you don't need to set permissions in the registry, and once the key above is created it should just work.
I can't tell you exactly what might be wrong, but if you go here you will see "How do I enable log4net internal debugging?" way down at the bottom. Log4net will not throw exceptions if something is wrong, so you must enable internal debugging in order to get information from log4net.
http://logging.apache.org/log4net/release/faq.html
Edit: Also see the quesiton directly after that one that explains potential hangups with using the EventLogAppender.
I would suspect code access security is preventing you from accessing the event log. This article have information on the topic. Basically, if your ASP.Net application is running under medium trust the app will not have access to event logs.
Note: this is not a restriction built into log4net per se, it is a "feature" of the .Net Framework and ASP.Net.

Resources