configure log4j file - log4j

I have this log4j.config
<appender name="FileInfoStatistics" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="${log.dir}/T_Statistics.log" />
<param name="MaxFileSize" value="8000KB"/>
<!-- Keep one backup file -->
<param name="MaxBackupIndex" value="1"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %5p %c{1} - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="INFO" />
</filter>
</appender>
but I would like just when then file T_Statistics.log is created firt time and one line as e.g This a log file, Is this possible from log4j.config?
I saw this is possible en log4net with:
<param name="Header" value="xxxx"
Is there something like in log4j?

Well, After some research I found a solution to my problem, said if someone would be useful.
I have created a custom appender:
package com.mycompany.logger;
import org.apache.log4j.PatternLayout;
public class MyPatterLayout extends PatternLayout
{
#Override
public String getHeader()
{
return "message id, file name, start time, end time, status" + System.getProperty("line.separator");
}
}
And then I have configured my log4j.xml:
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="com.mycompany.logger.MyPatterLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
And this is the result:
message id, file name, start time, end time, status
DEBUG App - Here is some DEBUG
INFO App - Here is some INFO
WARN App - Here is some WARN
ERROR App - Here is some ERROR
FATAL App - Here is some FATAL

Related

log4cxx asyncappender flush all logs before exiting

I am using Asynappender and DOMConfigurator to load the xml file.
I am losing half of the logs. My application exits but only few logs appears in log file.
I have found that calling close() method of AsyncAppender class processes pending events before exiting.
Does this means that it flushes all the logs to log file? And if yes then, as I don't have that object as I am simply loading file using DOMConfigurator::configure().
How can I retrieve the Asynappender object to call close()?
Is there any other way to flush the logs before exiting? Using some configuration in xml file?
Below is my code for reference:
#include <log4cxx/logger.h>
#include <log4cxx/xml/domconfigurator.h>
#include<iostream>
using namespace log4cxx;
using namespace log4cxx::xml;
using namespace log4cxx::helpers;
LoggerPtr loggerMyMain(Logger::getLogger( "main"));
int main(int args, char **argv)
{
DOMConfigurator::configure("asynclog4cxxconfig.xml");
LOG4CXX_TRACE(perf, "this is a performance message!!!");
LOG4CXX_DEBUG(loggerMyMain, "this is a debug message.");
LOG4CXX_WARN (loggerMyMain, "this is a warn message, not too bad.");
LOG4CXX_ERROR(loggerMyMain, "this is a error message, something serious is happening.");
LOG4CXX_FATAL(loggerMyMain, "this is a fatal message!!!");
return 0;
}
Below is the XML file:
<?xml version="1.0" encoding="UTF-8" ?>
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="appxNormalAppender" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="logfile" />
<param name="MaxFileSize" value="1000KB" />
<param name="MaxBackupIndex" value="3" />
<param name="append" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%X{process} %d %-5p %C{2} (%F:%L) - %m%n" />
</layout>
</appender>
<appender name="async_appxNormalAppender" class="org.apache.log4cxx.AsyncAppender">
<appender-ref ref="appxNormalAppender"/>
</appender>
<root>
<priority value="debug" />
<appender-ref ref="async_appxNormalAppender"/>
</root>
</log4j:configuration>
The problem got solved, posting it here if it helps someone.
Added the below piece of code at the end.
LoggerPtr root_logger = Logger::getRootLogger();
AppenderPtr app_ptr = root_logger->getAppender("async_appxNormalAppender");
if(app_ptr != NULL)
app_ptr->close();

Passing log4net ConfigurationFile to a new AppDomain

What I need to do is get hold of the the :
<param name="File" value=".\MyExe.exe.log"/>
value but when I try to access the appender using the following :-
var rootAppender = ((Hierarchy)LogManager.GetRepository())
.Root.Appenders.OfType<RollingFileAppender>()
.FirstOrDefault();
var myFilePath = rootAppender != null ? rootAppender.File : string.Empty;
I find all I get is null. So how do I access my path?
This is my log4net config section :-
<log4net threshold="All">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value=".\MyExe.exe.log"/>
<param name="AppendToFile" value="true"/>
<param name="ImmediateFlush" value="true"/>
<param name="RollingStyle" value="size"/>
<param name="MaxSizeRollBackups" value="5"/>
<param name="MaximumFileSize" value="1MB"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
</layout>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
</appender>
<logger name="MYLOGGER">
<level value="All"/>
<appender-ref ref="RollingLogFileAppender"/>
</logger>
</log4net>
Thanks
The reason you can't find the file name is that you are querying the root logger - but you don't have a root logger defined in your config, and the default root does not have any appenders linked to it.
You would need to run this code instead which uses your defined logger to get the filename:
var loggerAppender = LogManager.GetLogger("MYLOGGER").Logger.Repository
.GetAppenders()
.OfType<RollingFileAppender>()
.FirstOrDefault();
var myFilePath = loggerAppender != null ? loggerAppender.File : string.Empty;

log4j isolating certain level from a class

I want to ask something on log4j. I have this config file for log4j on activemq. My problem is that I want to log all INFO level messages from every class I have, but I want to log all DEBUG level messages from "TransportConnection" class to a different file and, at the same time, log all only messages that are greater or equal to WARN level, to the rootLogger.
The problem with this configuration is that I log INFO level messages from "TransportConnection" class in the rootLogger. I want to pass only the WARN and above level to the rootLogger.
I dont want to set a Threshold to the "out" appender, because I want INFO level messages from other classes.
log4j.rootLogger=INFO,out
# Log these warnings
log4j.logger.org.apache.activemq.broker.BrokerRegistry=INFO
log4j.logger.org.apache.activemq.broker.TransportConnection=DEBUG,tc
# Standard logging
log4j.appender.out=org.apache.log4j.RollingFileAppender
log4j.appender.out.file=/var/lib/activemq/log/activemq.log
log4j.appender.out.maxFileSize=10240KB
log4j.appender.out.maxBackupIndex=100
log4j.appender.out.append=true
log4j.appender.out.layout=org.apache.log4j.PatternLayout
log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
# Transport Connections logging
log4j.appender.tc=org.apache.log4j.RollingFileAppender
log4j.appender.tc.file=/var/lib/activemq/log/tc.log
log4j.appender.tc.maxFileSize=10240KB
log4j.appender.tc.maxBackupIndex=100
log4j.appender.tc.append=true
log4j.appender.tc.layout=org.apache.log4j.PatternLayout
log4j.appender.tc.layout.ConversionPattern=%d [%t] %-5p %-30.30c{1} - %m%n
You could write your own custom filter. I suggest that implementation could be something like that:
public class MinLevelForParticularClassFilter extends Filter {
private boolean acceptOnMatch = false;
private Level level;
private String className;
#Override
public int decide(LoggingEvent event) {
if (this.className != null && this.level != null) {
if (event.getLocationInformation().getClassName().startsWith(className)) {
// this is event for specified class
if (!event.getLevel().isGreaterOrEqual(this.level)) {
// level of event is less than specified level
return Filter.DENY;
}
}
}
if (acceptOnMatch) {
return Filter.ACCEPT;
} else {
return Filter.NEUTRAL;
}
}
public boolean isAcceptOnMatch() { return acceptOnMatch; }
public void setAcceptOnMatch(boolean acceptOnMatch) { this.acceptOnMatch = acceptOnMatch; }
public Level getLevel() { return level; }
public void setLevel(Level level) { this.level = level; }
public String getClassName() { return className; }
public void setClassName(String className) { this.className = className; }
}
Note that if you change "className" variable to "packageName" variable, the implementation will be the same for filter by particular package.
The log4j configuration in XML (since filters are unsupported by configuration in property files):
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="out" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="activemq.log" />
<param name="MaxFileSize" value="10240KB" />
<param name="MaxBackupIndex" value="100" />
<param name="Append" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%-15.15t] %-5p %-30.30c{1} - %m%n"/>
</layout>
<!-- Apply filter to appender that's destined for root logger -->
<filter class="com.foo.log4j.filters.MinLevelForParticularClassFilter">
<param name="Level" value="WARN" />
<param name="ClassName" value="org.apache.activemq.broker.TransportConnection" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
<appender name="tc" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="tc.log" />
<param name="MaxFileSize" value="10240KB" />
<param name="MaxBackupIndex" value="100" />
<param name="Append" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %-30.30c{1} - %m%n"/>
</layout>
</appender>
<logger name="org.apache.activemq.broker.BrokerRegistry">
<level value="INFO" />
</logger>
<logger name="org.apache.activemq.broker.TransportConnection">
<level value="DEBUG" />
<appender-ref ref="tc" />
</logger>
<root>
<priority value ="INFO" />
<appender-ref ref="out" />
</root>
</log4j:configuration>

Can the log file path be changed on the fly (reguarly)

I've been experimenting with log4net as it appears that it does not support a particular logging feature my project needs. In short, I want to be able to control the log file path in code. This path will change constantly. The specific use case is a set of file system watchers, and a separate log file is required per instance.
Can this be done?
I want to be able to specify a variable that controls the logging destination in code.
For example:
var log4NetLogger1 = new Log4NetLogger("LogFileAppender1");
log4NetLogger1.InformationEvent("Log message 1");
var log4NetLogger2 = new Log4NetLogger("LogFileAppender2");
log4NetLogger2.InformationEvent("Log message 2");
In the above example, I am passing a string to the log4net wrapper, that matches an appender name in configuration. The idea is that the log4net wrapper changes the logging target by modifying the appender in use via GetLogger.
_log = log4net.LogManager.GetLogger(appenderName);
The result is that two different log files are created, but the log message is written to both. It appears that some aspect of the log4net configuration is global, and I am not able to change log path on the fly in this way.
Configuration file:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<log4net>
<root>
<appender-ref ref="LogFileAppender1"/>
<appender-ref ref="LogFileAppender2"/>
</root>
<appender name="LogFileAppender1" type="log4net.Appender.RollingFileAppender">
<threshold value="INFO"/>
<param name="File" value="C:\Tmp\EDP_TEST\LOG_DESTINATION\TestLog1.txt"/>
<param name="AppendToFile" value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n"/>
</layout>
</appender>
<appender name="LogFileAppender2" type="log4net.Appender.RollingFileAppender">
<threshold value="INFO"/>
<param name="File" value="C:\Tmp\EDP_TEST\LOG_DESTINATION\TestLog2.txt"/>
<param name="AppendToFile" value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n"/>
</layout>
</appender>
</log4net>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
Full wrapper class:
using System;
using log4net;
namespace Log4NetRunner
{
public enum LoggingLevel
{
Information,
Warning,
Error
}
public class Log4NetLogger
{
private readonly ILog _log;
public Log4NetLogger(Type type)
{
if (_log == null)
{
_log = log4net.LogManager.GetLogger(type);
}
}
public Log4NetLogger(string appenderName)
{
if (_log == null)
{
_log = log4net.LogManager.GetLogger(appenderName);
}
}
public void FatalErrorEvent(string messageText)
{
SendLog(messageText, LoggingLevel.Error);
}
public void WarningEvent(string messageText)
{
SendLog(messageText, LoggingLevel.Warning);
}
public void InformationEvent(string messageText)
{
SendLog(messageText, LoggingLevel.Information);
}
private void SendLog(string messageText, LoggingLevel logLevel)
{
ILog logger = _log;
switch (logLevel)
{
case LoggingLevel.Error:
logger.Error(messageText);
break;
case LoggingLevel.Warning:
logger.Warn(messageText);
break;
case LoggingLevel.Information:
logger.Info(messageText);
break;
default:
logger.Error("Unknown Logging level: " + messageText);
break;
}
}
}
}
Yes it can, you just need to use the loggers section of the config.
http://www.beefycode.com/post/Log4Net-Tutorial-pt-5-Using-Logger-Objects.aspx
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<log4net>
<root>
<!--<appender-ref ref="LogFileAppender1"/>
<appender-ref ref="LogFileAppender2"/>-->
</root>
<logger name="Logger1">
<level value="ALL" />
<appender-ref ref="LogFileAppender1" />
</logger>
<logger name="Logger2">
<level value="ALL" />
<appender-ref ref="LogFileAppender2" />
</logger>
<appender name="LogFileAppender1" type="log4net.Appender.RollingFileAppender">
<threshold value="INFO"/>
<param name="File" value="C:\Tmp\EDP_TEST\LOG_DESTINATION\TestLog1.txt"/>
<param name="AppendToFile" value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n"/>
</layout>
</appender>
<appender name="LogFileAppender2" type="log4net.Appender.RollingFileAppender">
<threshold value="INFO"/>
<param name="File" value="C:\Tmp\EDP_TEST\LOG_DESTINATION\TestLog2.txt"/>
<param name="AppendToFile" value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n"/>
</layout>
</appender>
</log4net>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

Is it possible to use Log4Net to write to log file within a CLR Stored Procedure?

Issue: Unable to debug (write) to a Log File using Log4net inside of a CLR Stored Procedure. Possibly a problem with the way I'm building the CLR project? I'm only importing the DLL's into sql server (create assembly....). Do I need to import the App.Config as well?
DLL Name:
CLRTest.dll
Source Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlTypes;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;
using log4net;
using log4net.Config;
public class MyClass
{
private readonly static ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string sContextConn = "Context Connection=true";
[Microsoft.SqlServer.Server.SqlProcedure]
public static void Select1()
{
XmlConfigurator.Configure();
log.Debug("Begin Select1()...");
using (SqlConnection connection = new SqlConnection(sContextConn))
{
connection.Open();
SqlCommand command = new SqlCommand("select 1", connection);
SqlDataReader r = command.ExecuteReader();
SqlContext.Pipe.Send(r);
}
log.Debug("End Select1()...");
}
}//end MyClass
Log4Net XML Config (App.Config):
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="C:\log\clrsql.log" />
<param name="AppendToFile" value="true" />
<datePattern value="yyyyMMdd-HHmm" />
<param name="rollingStyle" value="Size" />
<param name="maxSizeRollBackups" value="50" />
<param name="maximumFileSize" value="25MB" />
<param name="staticLogFileName" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [t-%t] [%c.%M(%L)] %m%n" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d %-5p [%c.%M(%L)] %m%n" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingFileAppender" />
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>
Permissions on SQL Server:
C:\log\ --
NETWORK SERVICE and MyDomain\sqlserveraccount have Full Control on the "log" folder.
SQL Scripts:
drop procedure clr_Select1
go
drop assembly CLRTest
go
create ASSEMBLY CLRTest FROM 'C:\Share\ClrSql\TEST\CLRTest.dll' WITH PERMISSION_SET = unsafe
go
CREATE PROCEDURE clr_Select1
AS EXTERNAL NAME CLRTest.MyClass.Select1
go
exec clr_Select1
SQL Output:
(No column name)
1
The log4net configurator call that you're making actually tries to find the AppDomain.CurrentDomain.SetupInformation.ConfigurationFile. I don't know what the AppDomain is for a stored procedure.
You might want to try a standalone configuration file and use the overload of that configurator.
log4net.Config.XmlConfigurator.Configure(new FileInfo("config.log4net"));

Resources