Logs from java.util.logging in ICM - intershop

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.

Related

How to stop node from logging node.conf during startup

How do I stop the node from printing the node.conf in the logs?
I understand we can change the logging level since the node.conf is printed at INFO level, but I want to avoid that as much as possible since I still want some other information that is at INFO level to be printed out.
The contents of node.conf are printed at INFO level by the net.corda.node.services.config.ConfigHelper class. To prevent the contents of node.conf from being printed to the logs, you'd have to specify a custom logging configuration so that for the net.corda.node.services.config.ConfigHelper class, only messages at WARN or above should be printed to the logs.
The process for providing a custom Log4J2 logging configuration file for your node is documented here. You need to:
Create the custom logging file (e.g. test.xml)
Point your node to the custom logging file when starting the node (e.g. java -Dlog4j.configurationFile=test.xml -jar corda.jar)
Here's an example test.xml that prevents the contents of node.conf being printed to the logs:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Properties>
<Property name="log-path">logs</Property>
<Property name="log-name">node-${hostName}</Property>
<Property name="archive">${log-path}/archive</Property>
</Properties>
<Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout pattern="%highlight{%level{length=1} %d{HH:mm:ss} %T %c{1}.%M - %msg%n}{INFO=white,WARN=red,FATAL=bright red blink}"/>
</Console>
<RollingFile name="RollingFile-Appender"
fileName="${log-path}/${log-name}.log"
filePattern="${archive}/${log-name}.%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="[%-5level] %d{ISO8601}{GMT+0} [%t] %c{1} - %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy min="1" max="10">
<Delete basePath="${archive}" maxDepth="1">
<IfFileName glob="${log-name}*.log.gz"/>
<IfLastModified age="60d">
<IfAny>
<IfAccumulatedFileSize exceeds="10 GB"/>
</IfAny>
</IfLastModified>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console-Appender"/>
<AppenderRef ref="RollingFile-Appender"/>
</Root>
<Logger name="net.corda" level="error" additivity="false">
<AppenderRef ref="Console-Appender"/>
<AppenderRef ref="RollingFile-Appender"/>
</Logger>
<Logger name="net.corda.node.services.config.ConfigHelper" level="warn" additivity="false">
<AppenderRef ref="RollingFile-Appender"/>
</Logger>
</Loggers>
</Configuration>
Note the final Logger block. We specify that any messages from net.corda.node.services.config.ConfigHelper (e.g. the contents of node.conf) should only be printed if they are at level WARN or above.
#Joel is there any way to point all the nodes to one custom logging file? I.e, when executing runnodes.jar, could you pass a single logfile as a paramater, i.e:
java -jar -Dlog4j.configurationFile=/Users/username/Desktop/Prototype/config/dev/log4j2.xml runnodes.jar
This doesn't seem to work... so curious.

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.

ArangoDB and gremlin: How to reduce LOGGING

I have installed gremlin (v. 2.6.0) and ArangoDB (v. 2.8.11) and when I run any request through the gremlin.sh shell I get all the debug messages like
11:17:39.713 [main] DEBUG com.arangodb.http.HttpManager - [REQ]http-GET: url=http://localhost:8529/_api/gharial/myDB/edge/E/12712, headers={}
11:17:39.716 [main] DEBUG com.arangodb.http.HttpManager - [RES]http-GET: statusCode=200
11:17:39.716 [main] DEBUG com.arangodb.http.HttpManager - [RES]http-GET: text={"error":false,"code":200,"edge":{"_id":"E/12712"," . . .
I see those are DEBUG messages, so I want to suppress in order not to be flooded by those and only get important messages, like errors or warnings.
To reduce logging one has to change the log level on both server and client side.
Complete steps to fix this:
create config PATH_TO/confs/ directory with inside:
a. file confs/arangod.conf
b. file confs/logback.xml
set env. variable CLASSPATH:
export CLASSPATH=PATH_TO/confs
you can start arangod as follows:
arangod --daemon --pid-file /etc/arangodb/arangodb.pid -c PATH_TO/confs/arangod.conf
The content of confs/arangod.conf should contain:
[log]
## info, warning, or error
level = info
file = PATH_TO/logs/arangodb.log
The content of the confs/logback.xml
<configuration>
<!-- Arango log4j conf -->
<appender name="CONSOLE"
class="ch.qos.logback.core.ConsoleAppender">
<!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>
%-4relative [%thread] %-5level %logger{30} - %msg%n
</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

.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