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.
Related
Currently, I already config my project, but I got the issue
I can't query any message when the site is running.
When I stop the site, I can query it on database again and I see them.
Why do I just see message when I stop the site?
This is my code.
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="asyncForwarder" />
</root>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="4096" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=***;initial catalog=***;integrated security=false;persist security info=True;User ID=***;Password=***" />
<commandText value="INSERT INTO LogAPI ([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>
<appender name="asyncForwarder" type="Log4Net.Async.ParallelForwardingAppender,Log4Net.Async">
<appender-ref ref="AdoNetAppender" />
<bufferSize value="4096" />
</appender>
</log4net>
I dont know what is correct concept on the log4net.
I have an ADO.Net appender with the two parameter:
<parameter>
<parameterName value="#stacktrace" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%stacktrace{4}" />
</layout>
</parameter>
<parameter>
<parameterName value="#stacktracedetail" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%stacktracedetail{5}" />
</layout>
</parameter>
Edit: The code above works now fine.
Eg %stacktrace{4} would show you the top four functions of the stack trace.
See also documentaton:
https://logging.apache.org/log4net/log4net-1.2.13/release/sdk/log4net.Layout.PatternLayout.html
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.
My issue is that my Database logging does not display seconds (default format seems to be "yyyy-MM-dd hh:mm:00".
Is there any way to change this and get something with seconds at least (miliseconds would be a plus)?
Here is my appender config:
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=MyDB;initial catalog=LogSpace;integrated security=True;persist security info=True;Application Name="MyApp "" />
<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>
Thank you for your help!
EDIT: Just as suggested by leppie, I checked my Date type in database, which was smalldatetime. I changed it to datetime and now my logs are as expected (with seconds & milliseconds)
Change #log_date parameter like this:
<parameter>
<parameterName value="#log_date"/>
<dbType value="DateTime"/>
<layout type="log4net.Layout.PatternLayout"
value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}"/>
</parameter>
I have configured my application to use log4net as follows:
<log4net>
<appender name="SQL_Comandos" 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="X" />
<commandText value="INSERT INTO X ([Date],[Thread],[Level],[Logger],[Message],[Exception],[Usuario]) VALUES (#log_date, #thread, #log_level, #logger, #message, #exception, #usuario)" />
<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="#usuario" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%X{usuario}" />
</layout>
</parameter>
</appender>
<appender name="SQL_Hibernate" 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="X" />
<commandText value="INSERT INTO X ([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 name="INFO" />
<appender-ref ref="SQL_Comandos" />
</root>
<logger name="NHibernate" additivity="false" >
<level name="ERROR" />
<appender-ref ref="SQL_Hibernate" />
</logger>
They work perfectly but all logging is saving DEBUG messages, even having configured not to do so. What am I missing here?
It should work when you configure it like this:
<logger name="NHibernate" additivity="false" >
<level value="ERROR" />
...
Note: that I use value instead of name in the level node (do this for the root "level" element as well). Turning on internal debugging would reveal this kind of problem.
Just a thought, check your log appenders to see if they have something like the following configured:
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ALL"/>
</filter>
DEBUG is a lower level than INFO, so I suspect that the DEBUG messages are being logged because the root logger is set to log at the INFO level.
See this post if you want to get the INFO messages but not the DEBUG messages.