0
votes

I'm using Log4net in ASP.Net MVC for logging to different output types (file & DB). I'm able to log data to RollingFileAppender but not to AdoNetAppender

Added new log4net.config to project with file-appender section & DBLog-appender section

<log4net>
  <root>
    <level value="ALL" />
    <appender-ref ref="file" />
    <appender-ref ref="DBLog" />
  </root>
  <!--Rolling File Appender-->
  <appender name="file" type="log4net.Appender.RollingFileAppender">
    <file value="C:\Trinadh\Dot.Net\Web Applications\ASP.NetMVC\PartialViewApplSol\PartialViewApplSol\myapp.log" />
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="5" />
    <maximumFileSize value="5MB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-7p%d{yyyy-MM-dd HH:mm:ss tt} –%X{user}– %m method:%method %n stacktrace:%stacktrace{5} %n %logger %n type:%type %n line: %line %n" />
    </layout>
  </appender>
<!--Database Table Appender-->
  <appender name="DBLog" 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="Server=DBServer;Database=DemoDB;integrated security=false;persist security info=True;User ID=sysAdmin;Password=XyzAbc;" />
    <commandText value="INSERT INTO dbo.Log4net_Log ([Date],[Level],[Logger],[User],[Message],[Exception])
 VALUES (@log_date, @log_level, @logger, @user, @message, @exception)" />
    <parameter>
      <parameterName value="@log_date" />
      <dbType value="DateTime" />
      <layout type="log4net.Layout.RawTimeStampLayout" />
    </parameter>
    <parameter>
      <parameterName value="@log_level" />
      <dbType value="String" />
      <size value="50" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%p" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@logger" />
      <dbType value="String" />
      <size value="255" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%c" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@user" />
      <dbType value="String" />
      <size value="50" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%X{user}" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@message" />
      <dbType value="String" />
      <size value="4000" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%m" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@exception" />
      <dbType value="String" />
      <size value="2000" />
      <layout type="log4net.Layout.ExceptionLayout" />
    </parameter>
  </appender>
</log4net>

In 'DBLog' appender section, i'm using connection string of my DB to which logs would be written, but i'm already using same connection string in 'web.config' to fetch data and populate on UI.

  • How to use the same connection string specified in web.config for logging data to table using log4net without using it here again in 'log4net.config'.
  • As i'm logging different parameters to file such as time, userName, method and stacktrace; All log levels (Info, warn,
    error) log complete parameters, which i'm not interested in. How to
    log only time, userName, method under INFO level & time, userName,
    method, stacktrace under WARN/ Error level

Added a new log4netHelper.cs to project

public class log4netHelper  
{    
    private static readonly ILog log4Net = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);    
    public log4netHelper()    
    {    
        if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)    
            MDC.Set("user", HttpContext.Current.User.Identity.Name);    
    }    
    public static void LogMessage(string message)    
    {    
        log4Net.Info(message);    
    }    

    public static void LogError(string message, Exception ex)    
    {    
        log4Net.Error(message, ex);    
    }    
}

RollingFileAppenderis logging following

INFO 2018-07-23 19:27:06 PM –(null)– Index Action End method:LogMessage
stacktrace:System.Threading.Tasks.Task.ExecutionContextCallback > System.Threading.Tasks.Task.Execute > System.Threading.Tasks.Task.InnerInvoke > PartialViewApplSol.Controllers.HomeController+<>c.b__3_1 > PartialViewApplSol.App_Start.log4netHelper.LogMessage
PartialViewApplSol.App_Start.log4netHelper
type:PartialViewApplSol.App_Start.log4netHelper line: 19

  • How to get current caller method which is calling log4net.Message()? It's always showing method names in 'log4netHelper.cs' (LogMessage/ LogError). MSDN says to use 'System.Runtime.CompilerServices.CallerMemberName' attribute, but how to incorporate this into my logic.

  • Current log4net.config have both RollingFileAppender & AdoNetAppender but only RollingFileAppender is logging data to file, nothing is logged to Database table.

1

1 Answers

0
votes

If the problem is in log4net, you can best enable log4net internal debugging:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
    <add key="log4net.Internal.Debug" value="true"/>
</appSettings>
</configuration>

And write it to file:

<configuration>
...

<system.diagnostics>
    <trace autoflush="true">
        <listeners>
            <add 
                name="textWriterTraceListener" 
                type="System.Diagnostics.TextWriterTraceListener" 
                initializeData="C:\tmp\log4net.txt" />
        </listeners>
    </trace>
</system.diagnostics>

...
</configuration>

If there is any exception you will find it in the log file. You already have set the buffersize to 1, that will flush each message directly.

more on Log4net Troubleshooting