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
Related
I made a log4net project with WinForm about keeping logs in the database. I contacted SQL Server and wrote logs here. But when I try to contact to Oracle and save log in Oracle database, it didn't work. Why? I am sure the connection string is correct, but it does not work. Is there something wrong with the connection string or is there something else I need to implement for Oracle?
Here is my Log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigrationSectionHandler,log4net"/>
</configSections>
<log4net>
<root>
<level value="All"></level>
<appender-ref ref="AdoNetAppender_Oracle"></appender-ref>
</root>
<appender name="AdoNetAppender_Oracle" type="log4net.Appender.AdoNetAppender">
<connectionType value="Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess,Version=2.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
<connectionString value="Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=MYHOST)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=MYDBNAME)));User Id=MYUSERID;Password=MYPASSWORD;" />
<commandText value="INSERT INTO Log (Datetime,Thread,Log_Level,Logger,Message) VALUES (:log_date, :thread, :log_level, :logger, :message)" />
<bufferSize value="1" />
<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>
</appender>
</log4net>
</configuration>
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'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.
Log4Net isn't able to load the appender for the DB2 connection and I cannot see why. It writes the logs to the file system fine, however, the DB2 logging isn't occurring. The version of Log4Net is v1.2.10.0.
<log4net>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="100" />
<connectionType value="IBM.Data.DB2.DB2Connection,IBM.Data.DB2, Version=8.1.2.1" />
<connectionString value="server=db2Server;database=dbName;user Id=userId1;password=password;persist security info=true" />
<commandText value="INSERT INTO GOSDDL.EXCEPTION_LOG (APP_LOG_TS,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">
<conversionPattern value="%utcdate" />
</layout>
</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="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="../logs" />
<appendToFile value="true"/>
<maximumFileSize value="512KB"/>
<maxSizeRollBackups value="2"/>
<rollingStyle value="Date"/>
<datePattern value=".yyyy-MM-dd.lo" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d %l %-2p - %m%n"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO"/>
<levelMax value="FATAL"/>
</filter>
</appender>
<root>
<level value="INFO"/>
<appender-ref ref="RollingFile"/>
</root>
</log4net>
At the risk of pointing out the obvious, the config file you posted does not actually use AdoNetAppender. Would this be a matter of replacing RollingFile with AdoNetAppender in the second last line?
If not, can you post the rest of the config file.
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.