What is log4net.Layout.PatternLayout value to output DateTimeOffset data type to database?
This is what I have currently in configuration file for log4net:
<log4net>
....
<parameter>
<parameterName value="#log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.PatternLayout" value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}" />
</parameter>
...
</log4net>
And I want to have something like:
<log4net>
....
<parameter>
<parameterName value="#log_date" />
<dbType value="DateTimeOffset" />
<layout type="log4net.Layout.PatternLayout" value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff **OFFSET**}" />
</parameter>
...
</log4net>
Basically we reuse the same DB to log events from clients located in different time zones - so we want to know an exact local time of the event.
Thanks,
Alex
You should be able to use any valid DateTime format string. Try this:
%date{yyyy-MM-ddTHH:mm:ss.fffzzz}
Would defining your DB column as DateTime and using %utcdate instead of %date help? That should make all of the timestamps compatible.
Related
Writing db for base lognet columns fine, but I added another column called "clientIp" and set data to Ilog object bofore log but it writes same data with Message column to ClintIp column.. here my config and file and db screenshot:
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
...
<commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception],[ClientIp]) VALUES (#log_date, #thread, #log_level, #logger, #message, #exception, #clientip)" />
<parameter>
<parameterName value="#log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
...
<parameter>
<parameterName value="#exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
<parameter>
<parameterName value="#clientip" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout" />
</parameter>
</appender>
and my logger class:
public static class Logger
{
private static ILog log {get; set;}
static Logger()
{
log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
public static void Error(object msg, string userip)
{
log4net.LogicalThreadContext.Properties["ClientIp"] = userip;
if (log.IsErrorEnabled)
{
log.Error(msg);
}
}
whats is problem here ?
EDITED:
Its obvious, it writes db with for message and clientip with given parameter: for exmp: log.Error('Your Ip is::1'); how can I tell log4net use log4net.LogicalThreadContext.Properties["ClientIp"] for ClientIp column and log.error(message) for Message column
Your code is not correct, it should be:
public static void Error(object msg, string userip)
{
log4net.LogicalThreadContext.Properties["ClientIp"] = userip;
if (log.IsErrorEnabled)
{
log.Error(msg); //<----Here is your error
}
}
And add in the ip column:
<parameter>
<parameterName value="#clientip" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout" >
<conversionPattern value="%property{ClientIp}" />
</layout>
</parameter>
In case this helps anyone else, I had the same problem: the data in my added column was "somewhat" repeated from the Message column.
For example, I was simply logging "accessed home page" as the message. My added column had "accessed home pageac" showing up in it.
My first mistake was having a value attribute after the layout type:
Removing the value attribute from above prevented the data from being duplicated in the added column, but now the column was null.
My second mistake was that for some unknown reason, log4net does NOT like 'machinename'. I don't know if the problem is the column name, or the parameter name, but I changed all instances of 'machinename' to 'server' (including renaming the column in the DB of course), and it all started working.
EDIT
Ok so I think I just realized that the problem was the Properties value is case sensitive, so I was using .Properites["MachineName"] but should have been using .Properties["machinename"].
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.
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(...).
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.
I'm new to log4net and been reading and reading and come to no conclusion of what my problem is.
Here is the configuration:
<root>
<level value="DEBUG" />
<appender-ref ref="AdoNetAppender"/>
</root>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="Server=XXXXX;Database=XXX;Network=XXXXX;User ID=XXXXX;Password=XXXXX" />
<commandType value="StoredProcedure" />
<commandText value="dbo.LogWrite" />
<parameter>
<parameterName value="#LogDate" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="#LogLevel" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout" value="%level" />
</parameter>
<parameter>
<parameterName value="#Logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout" value="%logger" />
</parameter>
<parameter>
<parameterName value="#UserID" />
<dbType value="Int32" />
<layout type="log4net.Layout.PatternLayout" value="%property{UserID}" />
</parameter>
<parameter>
<parameterName value="#Message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout" value="%message" />
</parameter>
<parameter>
<parameterName value="#Exception" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.ExceptionLayout"/>
</parameter>
</appender>
When I go to a .NET page and in Page_Load this statement executes:
log.Error("hi")
i get this error as an entry in my database table. But if i go to this page again rather quickly i get a total of 3 entries? It seemes that if i wait ~10sec before reloading the page i get only one more entry. I have set the buffersize to 1. Anyone who had the same problem? The most part of the community tends to say that if there is a problem then it's most likely in your configuration but to me me my configuration looks fine.
Greatly appreciate any who can shed som lights over this!
//Daniel
Log4Net is probably working just fine. It is logging what is happening.
You need to figure out why Page_Load is executing when you don't expect it.