log4net ADO Stored Procedure - log4net

I am trying to call an existing Stored Procedure but can't get it to log. Seems to be parameter type conversion problem, but I can't figure it out.
Error on build is:
log4net:ERROR XmlHierarchyConfigurator: Cannot find Property
[conversionPattern] to set object on
[log4net.Layout.RawPropertyLayout]
web.config is:
<appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
<bufferSize value="1" />
<threshold value="ALL"/>
<param name="ConnectionType" value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<param name="ConnectionString" value="Data Source=central-db.canterbury.ac.uk\devel;Initial Catalog=SourceDB;Persist Security Info=True;/>
<param name="UseTransactions" value="False" />
<commandText value="dbo.usperrLogError" />
<commandType value="StoredProcedure" />
<parameter>
<parameterName value="#ApplicationId"/>
<dbType value="String"/>
<size value="2" />
<layout type="log4net.Layout.RawPropertyLayout">
<key value="EventGuid" />
<conversionPattern value="%property{APP-ID}"/>
</layout>
</parameter>
//
<parameter>
<parameterName value="#EventGuid"/>
<dbType value="String"/>
<size value="50" />
<layout type="log4net.Layout.RawPropertyLayout">
<key value="EventGuid" />
<conversionPattern value="%property{GUID}"/>
</layout>
</parameter>
Am setting Properties like this:
log4net.ThreadContext.Properties["GUID"] = eventGuid.ToString();
Following the log4net debug error there is an additional error here:
A first chance exception of type 'System.ArgumentNullException' occurred in mscorlib.dll
log4net:ERROR [AdoNetAppender] Failed in DoAppend
System.ArgumentNullException: Key cannot be null.
Parameter name: key
at System.Collections.Hashtable.get_Item(Object key)
at log4net.Util.PropertiesDictionary.get_Item(String key) in c:\work\svn_root\apache\log4net\tags\log4net-1.2.10-rc2\build\package\log4net-1.2.10\src\Util\PropertiesDictionary.cs:line 114
at log4net.Core.LoggingEvent.LookupProperty(String key) in c:\work\svn_root\apache\log4net\tags\log4net-1.2.10-rc2\build\package\log4net-1.2.10\src\Core\LoggingEvent.cs:line 1404
at log4net.Layout.RawPropertyLayout.Format(LoggingEvent loggingEvent) in c:\work\svn_root\apache\log4net\tags\log4net-1.2.10-rc2\build\package\log4net-1.2.10\src\Layout\RawPropertyLayout.cs:line 84
at log4net.Appender.AdoNetAppenderParameter.FormatValue(IDbCommand command, LoggingEvent loggingEvent) in c:\work\svn_root\apache\log4net\tags\log4net-1.2.10-rc2\build\package\log4net-1.2.10\src\Appender\AdoNetAppender.cs:line 1117
at log4net.Appender.AdoNetAppender.SendBuffer(IDbTransaction dbTran, LoggingEvent[] events) in c:\work\svn_root\apache\log4net\tags\log4net-1.2.10-rc2\build\package\log4net-1.2.10\src\Appender\AdoNetAppender.cs:line 560
at log4net.Appender.AdoNetAppender.SendBuffer(LoggingEvent[] events) in c:\work\svn_root\apache\log4net\tags\log4net-1.2.10-rc2\build\package\log4net-1.2.10\src\Appender\AdoNetAppender.cs:line 501
at log4net.Appender.BufferingAppenderSkeleton.Append(LoggingEvent loggingEvent) in c:\work\svn_root\apache\log4net\tags\log4net-1.2.10-rc2\build\package\log4net-1.2.10\src\Appender\BufferingAppenderSkeleton.cs:line 463
at log4net.Appender.AppenderSkeleton.DoAppend(LoggingEvent loggingEvent) in c:\work\svn_root\apache\log4net\tags\log4net-1.2.10-rc2\build\package\log4net-1.2.10\src\Appender\AppenderSkeleton.cs:line 316
A first chance exception of type 'System.ArgumentNullException' occurred in mscorlib.dll
log4net:ERROR [AdoNetAppender] Failed in DoAppend
System.ArgumentNullException: Key cannot be null.
Clearly I am not using RawPropertyLayout correctly but can't find good examples!

I do something like you, but I use the log4net.Layout.PatternLayout like this:
<parameter>
<parameterName value="#ProjectParam1"/>
<dbType value="String"/>
<size value="254" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{OrderNumber}" />
</layout>
</parameter>
If I understand the log4net.Layout.RawPropertyLayout correctly, you have to use it as follows:
<parameterName value="#EventGuid"/>
<dbType value="String"/>
<size value="50" />
<layout type="log4net.Layout.RawPropertyLayout">
<param name="Key" value="GUID" />
</layout>
</parameter>

Related

log4net write file is ok but cant insert to database

This is my configuration file contains log4net attributes, if I use "RollingLogFileAppender" appender it writes file correctly but I am using
"AdoNetAppender" and expect to see same string in message column of inserted row. But somehow this not work..
(table defination and query configurations are from apache documentation so it cant be wrong I though connection string is my problem, But application already have connection with the same db I also shared the connection string is being used by adonet)
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\\AkisLog\\Logs.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
</layout>
</appender>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="100" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=******\SQLTEST;initial catalog=LISANSSIZ_SANTRAL_PROJE_ONAY;persist security info=True;user id=user;password=pwd" />
<commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (#log_date, #thread, #log_level, #logger, #message, #exception)" />
<parameter>
<parameterName value="#log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="#thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="#log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="#logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="#message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="#exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="AdoNetAppender" />
</root>
</log4net>
...
<connectionStrings>
<add name="TedasDbContext" connectionString="metadata=res://*/Project.csdl|res://*/Project.ssdl|res://*/Project.msl;provider=System.Data.SqlClient;provider connection string="data source=****\SQLTEST;initial catalog=LISANSSIZ_SANTRAL_PROJE_ONAY;persist security info=True;user id=user;password=pwd;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
And .cs file:
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
if (log.IsErrorEnabled)
{
log.Error("Error ocurred here");
}
if (log.IsDebugEnabled)
{
log.Debug("Debug message");
}
Your buffersize is 100, which means that messages will be written after 100 messages. Change it to 1, it will flush the messages directly to the sql database:
<bufferSize value="1" />
If that does not work, enable log4net interal debugging to see if you have connection problems. Also check if you have the latest version of log4net.

DateTime format in log4net AdoNetAppender

I'm using log4net and trying to pass a custom DateTime property to a database using the AdoNetAppender. I can pass in the DateTime value just fine, but the database value excludes the milliseconds. The final value is rounded to the nearest second.
I know there's the date{} formatting, but I cannot get that to work with a custom property. So, is it possible to format a custom DateTime property to include the milliseconds?
Here's my config:
<log4net>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="0" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="{MyConnectionString}" />
<commandText value="INSERT INTO MyTestLog ([Date],[Thread],[Level],[Logger],[Message],[Exception],[StartDate]) VALUES (#log_date, #thread, #log_level, #logger, #message, #exception, #start_date)" />
<parameter>
<parameterName value="#log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="#thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="#log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="#logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="#message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="#exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
<parameter>
<parameterName value="#start_date"/>
<dbType value="DateTime" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{StartDate}" />
</layout>
</parameter>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="AdoNetAppender" />
</root>
</log4net>
My logging code is:
ThreadContext.Properties["StartDate"] = DateTime.Now.AddMinutes(-10);
log.Info("Info message w/ StartTime property");
The resulting value is correct (10 minutes ago), but the value is rounded to the nearest second.
I can get it to work if I first reformat the DateTime to a String, like this:
ThreadContext.Properties["StartDate"] = DateTime.Now.AddMinutes(-10).ToString("yyyy-MM-ddTHH:mm:ss.fffzzz");
However, this seems less than optimal. Any ideas??
Option 1
Use log4net.Layout.RawPropertyLayout instead; e.g:
<parameter>
<parameterName value="#start_date"/>
<dbType value="DateTime" />
<layout type="log4net.Layout.RawPropertyLayout">
<key value="StartDate" />
</layout>
</parameter>
Option 2
Create this (it could be a struct if you prefer and might reduce heap allocations depending on how you use it):
public class Log4NetDateTime
{
private DateTime _value;
public Log4NetDateTime(DateTime value)
{
_value = value;
}
public override string ToString()
{
return _value.ToString("yyyy-MM-dd HH:mm:ss.fff");
}
}
Then add Log4NetDateTime values instead of DateTime values.
log4net.Layout.PatternLayout (via log4net.Util.PatternConverter) just calls ToString() on the object, and by default this does not include milliseconds.

Write custom xml message to database

I am using log4net AdoNetAppender with C# to log a custom XML message into a database. I have a stored procedure that takes one parameter as a XML format.
Here is a part of my config file:
<appender name="AdoNetAppender" type="log4net.Appender.ADONetAppender">
<bufferSize value="1" />
<threshold value="ALL" />
<reconnectOnError value="true" />
<param name="ConnectionType" value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=xxxdfasdfas" />
<param name="ConnectionString" value="Data Source=myserver;integrated security=false;Initial Catalog=mydatabase; Persist Security Info=True;User ID=me;Password=me;" />
<param name="UseTransactions" value="False" />
<commandText value="dbo.InsertLog " />
<commandType value="StoredProcedure" />
<parameter>
<parameterName value="#LogEntries" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{LogEntries}" />
</layout>
</parameter>
</appender>
With log4net, I should be able to do something like this,
mylogger.Info(FormatToXML(ID,Date,LogLevel,message)); //FormatToXML takes these arguments, and create XMLElement
However, above line doesn't insert anything to the database. I have log4net debugger turned on, but I didn't see any errors/exception.
But, this works,
log4net.GlobalContext.Properties["LogEntries"] = FormatToXML(ID,Date,LogLevel,message);
mylogger.Info("");
I am sure I am doing something wrong where I should be able to just call mylogger.Info(...).
Can anybody see where I am doing wrong?
You're using custom property to get the value in the parameter in layout. Change the layout pattern by simply using the %message.
<parameter>
<parameterName value="#LogEntries" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
Now will work normally with mylogger.Info(...).

Cannot get log4net to work for database

I cannot get log4net to work, and having installed Glimpse for log4net, I notice the log4net tab is greyed out, so I guess I have not installed it properly, not sure where though.
In my assemblyInfo.cs I have:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
It may not be necessary, but in Global.asax.cs I have:
var logConfigFilePath = Server.MapPath("~/log4net.config");
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(logConfigFilePath));
In my log4net.config I have:
?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="100" />
<connectionType value="System.Data.SqlClient.SqlConnection,
System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=SQL_Mulalley;initial catalog=LogFiles;Persist Security Info=True;User ID=***;Password=****;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/>
<commandText value="INSERT INTO SCD4_Log4Net ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (#log_date, #thread, #log_level, #logger, #message, #exception)" />
<parameter>
<parameterName value="#log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="#thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="#log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="#logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="#message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="#exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
<root>
<level value="FATAL"/>
<appender-ref ref="RollingFileAppender"/>
</root>
</log4net>
</configuration>
I obtain the logger here:
private static readonly log4net.ILog log =
log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
And I call the log in my code as follows:
log.Info(string.Format("User {0} logged in.", model.UserName));
Nothing appears in my database where I have created the standard Log4Net table.
So what am I missing?
You did declare the appender but log4net is not actually using it.
As per your config file you're telling log4net to use an appender named RollingFileAppender (that is, additionally, not defined).
Change this:
<appender-ref ref="RollingFileAppender"/>
To:
<appender-ref ref="AdoNetAppender"/>
Finally pay attention to this section:
<root>
<level value="FATAL"/>
As per the line above, your (default) appender is not going to transmit any log unless you do the logs with Fatal level:
log.Fatal(string.Format("User {0} logged in.", model.UserName));
Or change the default log-level to debug:
<root>
<level value="DEBUG"/>
It can be the buffer size is 100 and hence you haven't hit the buffer limit to allow log4net to write to Db. Change it to one for testing
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="100" />
You can also see if the Adoappender is throwing any error by switching on Internal.Debug=true
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
I usually get issue with the SQL not being correct or the connection string is not correct.

how to insert into database from stored procedure in log4net?

I have to log thread context properties like this:
string logFilePath = AppDomain.CurrentDomain.BaseDirectory + "log4netconfig.xml";
FileInfo finfo = new FileInfo(logFilePath);
log4net.Config.XmlConfigurator.ConfigureAndWatch(finfo);
ILog logger = LogManager.GetLogger("Exception.Logging");
log4net.ThreadContext.Properties["MESSAGE"] = exception.Message;
log4net.ThreadContext.Properties["MODULE"] = "module1";
log4net.ThreadContext.Properties["COMPONENT"] = "component1";
logger.Debug("test");
and the configuration file is:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<log4net>
<logger name="Exception.Logging" level="Debug">
<appender-ref ref="AdoNetAppender"/>
</logger>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<connectionString value="Data Source=xe;User ID=test;Password=test;" />
<connectionType value="System.Data.OracleClient.OracleConnection, System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<bufferSize value="10000"/>
<commandText value="Log_Exception_Pkg.Insert_Log" />
<commandType value="StoredProcedure" />
<parameter>
<parameterName value="#p_Error_Message" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{MESSAGE}"/>
</layout>
</parameter>
<parameter>
<parameterName value="#p_Module" />
<dbType value="String" />
<size value="225" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{MODULE}"/>
</layout>
</parameter>
<parameter>
<parameterName value="#p_Component" />
<dbType value="String" />
<size value="225" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{COMPONENT}"/>
</layout>
</parameter>
</appender>
</log4net>
</configuration>
But it's not inserting them in the database. How can I get that to work?
Simple answer: Because this is an Oracle connection remove the # symbol from the parameter name and it will work.
Sample:
<parameter>
<parameterName value="#p_Module" />
<dbType value="String" />
<size value="225" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{MODULE}"/>
</layout>
</parameter>
I had similar problem, when log4net table was in different schema.
(it surely applies to stored procedure or package too if they are in different schema)
Don't forget to type your schema name before table or stored procedure then.
Sample:
<log4net>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<connectionType value="Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=4.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
<connectionString ..../>
<commandText value="INSERT INTO schemaName.LOG4NET (LOG_DATE, LOG_LEVEL, LOG_IDENTITY, LOG_MESSAGE, LOG_EXCEPTION) VALUES (:log_date, :log_level, :log_identity, :log_message, :log_exception)" />
....

Resources