Simplest correct way to configure log4net for a .Net Core 3.1 application

20,454

Solution 1

Editing my answer a little to be clear that Core does NOT include a normal file logger out of the box. My bad. (as of 5/19/2020)

I would recommend using the logging extensions from Microsoft instead of log4net, but this should do for you. Core now comes with a logger and it's pretty nice and plugs in easy for DI, and uses appsettings.json. I can provide a sample of that too if you want. But here's log4net basic example.

Sample console app that loads config from a file (file set to Copy Always)

using log4net.Repository;
using System;
using System.IO;
using System.Reflection;

namespace ConsoleApp1Core
{
    class Program
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        static void Main(string[] args)
        {
            try
            {

                ILoggerRepository repository = log4net.LogManager.GetRepository(Assembly.GetCallingAssembly());

                var fileInfo = new FileInfo(@"log4net.config");

                log4net.Config.XmlConfigurator.Configure(repository, fileInfo);

                log.Info("test");

                Console.WriteLine("press any key");
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("Press any key to exit");
                Console.ReadLine();
            }
        }
    }
}

Solution 2

I was able to respond with the following methods:

1-Install-Package log4net
2-Install-Package MicroKnights.Log4NetAdoNetAppender
3-Install-Package System.Data.SqlClient

First, I have created a Database and Table with this Code:

CREATE DATABSE Log4netDb
CREATE TABLE [dbo].[Log] (
    [Id] [int] IDENTITY (1, 1) NOT NULL,
    [Date] [datetime] NOT NULL,
    [Thread] [varchar] (255) NOT NULL,
    [Level] [varchar] (50) NOT NULL,
    [Logger] [varchar] (255) NOT NULL,
    [Message] [varchar] (4000) NOT NULL,
    [Exception] [varchar] (2000) NULL
)

Second, I have created log4net.config File in program . This is a simple configuration with no customization on the log message:

<?xml version="1.0" encoding="utf-8" ?>
<log4net debug="true">
  <!-- definition of the RollingLogFileAppender goes here -->
  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="Logs/WebApp.log" />
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="10MB" />
    <staticLogFileName value="true" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <layout type="log4net.Layout.PatternLayout">
      <!-- Format is [date/time] [log level] [thread] message-->
      <conversionPattern value="[%date] [%level] [%thread] %m%n" />
    </layout>
  </appender>
  <appender name="AdoNetAppender" type="MicroKnights.Logging.AdoNetAppender, MicroKnights.Log4NetAdoNetAppender">
    <bufferSize value="1" />
    <connectionType value="System.Data.SqlClient.SqlConnection, System.Data" />
    <connectionStringName value="log4net" />
    <connectionStringFile value="appsettings.json" />
    <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message]) VALUES (@log_date, @thread, @log_level, @logger, @message)" />
    <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="RollingLogFileAppender" />
    <appender-ref ref="AdoNetAppender" />
  </root>
</log4net>

Third, I have replaced the code below with IHostBuilder :

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .ConfigureLogging(logging =>
    {
        // clear default logging providers
        logging.ClearProviders();
        logging.AddConsole();  
        logging.AddDebug();
        logging.AddEventLog();
        // add more providers here
    })
    .UseStartup<Startup>();

Fourth, in appsettings.json I have inserted this code:

{
  "connectionStrings": {
    "log4net": "Server=MICKO-PC;Database=Log4netDb;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

At the end, I have used these commands to enjoy logging in

public class ValuesController : Controller
{
    private static readonly ILog log = LogManager.GetLogger(typeof(ValuesController));
    
    [HttpPost]
    public async Task<IActionResult> Login(string userName, string password)
    {
        log.Info("Action start");
        
        // More code here ...
        log.Info("Action end");
    }
    
    // More code here...
} 

Good luck.

Solution 3

Using Microsoft.Extensions.Logging.Log4Net.AspNetCore is easy to config.

Refer to: https://github.com/huorswords/Microsoft.Extensions.Logging.Log4Net.AspNetCore

Share:
20,454
user304582
Author by

user304582

Updated on May 17, 2021

Comments

  • user304582
    user304582 about 3 years

    I am struggling with understanding the simplest way to configure log4net to use in a .Net Core 3.1 application. The application is using log4net 2.0.8. So:

    Is there a way to use the application.runtimeconfig.json file to configure to do this? If so, what code would I add to the application to tell it to use these settings - something like:

    log4net.Config.XmlConfigurator.Configure();
    

    If this is not possible, then what's the simplest way to add a configuration file, say log4net.xml, and tell the application to use this?

    I want to direct all of the logging to a file for the moment, say Temp.log. I've looked at many log4net pages, but they either talk about using Assembly.Info.cs which does not exist in new .Net Core 3.1 projects, or seem to programmatically set the log4net configuration which I'd like to avoid. I was expecting this to be easy, so apologies if I have missed an obvious approach.