[2core]Log和Log4net的配置使用

一、準備

儘管在asp.net core中幾乎把所有能DI化的技術、知識和概念都依賴注入,不過本人還是想不讓自己的項目那麼DI化,完全沒有必要“爲了DI而DI”。這篇文章記錄日誌在asp.net core中的使用,以應用實戰爲主,不講那麼多大道理。

在asp.net core中框架提供了四種日誌輸出方式,即Console日誌、Debug日誌、EventSource日誌和EventLog日誌。前兩種比較容易理解,EventSource提供程序寫入名稱爲 Microsoft-Extensions-Logging 的跨平臺事件源,EventLog提供程序將日誌輸出發送到 Windows 事件日誌。本文主要分析記錄Console日誌、Debug日誌和Log4net日誌的使用(前兩種無法輸出到文件)。

日誌類型
Trace=0,Debug=1,Information=2,Warning=3,Error=4,Critical=5,None=6

日誌等級

None > Critical > Error > Warning > Information > Debug > Trace

 

 

 

二、實戰

1.Console日誌和Debug日誌

1.1.準備
       a)打開VS2022,創建Asp.net core WebApi項目
       b)刪除簡化Program類代碼,如下:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();


var app = builder.Build();
app.MapControllers();


app.Run();

1.2.依賴注入模式

1.2.1.Console日誌

         a)通過nuget工具安裝依賴包。
               1.Microsoft.Extensions.Logging:基礎包
               2.Microsoft.Extensions.Logging.Console:輸出日誌到控制檯程序包
         b)在Program文件中,配置日誌。

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddLogging(logBuilder =>
{
    logBuilder.AddConsole();
});

var app = builder.Build();
app.MapControllers();


app.Run();

         c)修改測試文件WeatherForecastController的方法Get。

 public IEnumerable<WeatherForecast> Get()
        {
            _logger.LogTrace("LogTrace");
            _logger.LogDebug("LogDebug");
            _logger.LogInformation("LogInformation");
            _logger.LogWarning("LogWarning");
            _logger.LogError("LogError");
            _logger.LogCritical("LogCritical");

            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

         d)通過VS運行調試程序,查看輸出結果。
                 LogInformation
                 LogWarning
                 LogError
                 LogCritical

             不出意外會輸出上述四行結果,Why?請用1.4小節中配置文件,替換掉默認的配置信息就好。

1.2.2.Debug日誌

         a)通過nuget工具安裝依賴包。
              Microsoft.Extensions.Logging.Debug:輸出日誌到Debug程序包

         b)在Program文件中,配置日誌。

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddLogging(logBuilder =>
{
    logBuilder.AddConsole();
    logBuilder.AddDebug();
});

var app = builder.Build();
app.MapControllers();


app.Run();

         d)通過VS運行調試程序,此時就可以在VS的“輸出”窗口中,看到日誌的輸出信息了。

1.2.3.小節

         通過上述操作,你已經能夠以依賴注入的方式使用框架內置的日誌。如果你從.net framework升級到.net core的程序員,以及你理解DI/IOC的原理,不難看出所謂的依賴注入就是魔法糖。

 

1.3.工廠模式

在asp.net core中,不僅可以通過AddLogging()方法實現日誌的配置和啓用,還可以通過日誌工廠進行操作。
使用日誌工廠方式,appsettings.json配置文件中的日誌配置數據就無效了,而以編寫代碼的方式設置日誌輸出等級就生效了。

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
var loggerFactory = LoggerFactory.Create(logBuilder =>
{
    logBuilder.ClearProviders();
    logBuilder.AddConsole();
    logBuilder.AddDebug();
    logBuilder.SetMinimumLevel(LogLevel.Trace);
});
ILogger _logger = loggerFactory.CreateLogger<Program>();
_logger.LogTrace("LogTrace");
_logger.LogDebug("LogDebug");
_logger.LogInformation("LogInformation");
_logger.LogWarning("LogWarning");
_logger.LogError("LogError");
_logger.LogCritical("LogCritical");


var app = builder.Build();
app.MapControllers();


app.Run();

 

1.4.配置文件

特別提示,asp.net core項目中,配置文件的日誌配置數據的優先級要高於程序中編寫代碼,僅限於依賴注入模式。

{
  "Logging": {
    "Console": {
      "LogLevel": {
        "Default": "Trace",
        "Microsoft": "Warning",
        "Microsoft.Hosting.Lifetime": "Information"
      }
    },
    "Debug": {
      "LogLevel": {
        "Default": "Trace",
        "Microsoft": "Warning",
        "Microsoft.Hosting.Lifetime": "Information"
      }
    },
    "EventSource": {
      "LogLevel": {
        "Microsoft": "Warning"
      }
    },
    "EventLog": {
      "LogLevel": {
        "Microsoft": "Warning"
      }
    },
    "LogLevel": {
      "Default": "Trace",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

 

1.5.總結

通過上述兩種方式,實現了日誌輸出到Console和Debug,但是框架並沒有提供輸出到硬盤文件的程序包,所以需要藉助第三方的程序包實現將日誌輸出到文件的需求。

 

2.Log4net日誌

不能把日誌輸出到文件中或寫入到日誌系統裏,是無法保證系統安全穩定運行以及快速定位查找問題的,所以一定要實現在程序部署運行中,將日誌輸出到硬盤文件或專門的日誌系統裏的需求,所以此處用到了Log4net程序包。

2.1.依賴注入和工廠模式

在asp.net core中,使用log4net還是比較容易的,主要分爲三步:第一安裝程序包,第二設置配置文件,第三通過代碼啓用,如下:

2.1.1.安裝程序包

         1.log4net:基礎包
         2.Microsoft.Extensions.Logging.Log4Net.AspNetCore:適配AspNetCore程序的軟件包
2.1.2.配置文件

         1.特別說明:a)配置文件中<configuration>節點需要去掉;b)配置文件中包含了兩種配置,一種適用於AspNetCore,一種是傳統.net framework模式。
         2.配置文件內容:注意配置文件要輸出到根目錄,因爲程序包默認就是從根目錄查找加載。

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
    <!--DIOC日誌附加介質-->
    <!--根配置-->
    <root>
        <!--日誌級別: NONE > FATAL > ERROR > WARN > INFO > DEBUG > ALL -->
        <priority value="ALL"/>
        <level value="ALL"/>
        <appender-ref ref="DiocAppender" />
    </root>
    <!-- name屬性指定其名稱,type則是log4net.Appender命名空間的一個類的名稱,意思是,指定使用哪種介質-->
    <appender name="DiocAppender" type="log4net.Appender.RollingFileAppender">
        <!--日誌輸出到exe程序這個相對目錄下-->
        <param name="File" value="logs\\diocs\\" />
        <!--輸出的日誌不會覆蓋以前的信息-->
        <param name="AppendToFile" value="true" />
        <!--備份文件的個數-->
        <param name="MaxSizeRollBackups" value="50" />
        <!--最小鎖定模型以允許多個進程可以寫入同一個文件-->
        <param name="MaxFileSize" value="10240" />
        <!--當前日誌文件的最大大小-->
        <param name="lockingModel"  type="log4net.Appender.FileAppender+MinimalLock" />
        <!--是否使用靜態文件名-->
        <param name="StaticLogFileName" value="false" />
        <!--日誌文件名-->
        <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
        <!--文件創建的方式,這裏是以Date方式創建-->
        <param name="RollingStyle" value="Date" />
        <!--輸出級別在INFO和ERROR之間的日誌-->
        <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="ALL" />
            <param name="LevelMax" value="FATAL" />
        </filter>
        <!--信息日誌佈局-->
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
        </layout>
    </appender>

    <!--錯誤日誌類-->
    <logger name="logerror">
        <!--日誌類的名字-->
        <level value="ALL" />
        <!--定義記錄的日誌級別-->
        <appender-ref ref="ErrorAppender" />
    </logger>
    <!--信息日誌類-->
    <logger name="loginfo">
        <!--日誌類的名字-->
        <level value="ALL" />
        <!--定義記錄的日誌級別-->
        <appender-ref ref="InfoAppender" />
    </logger>
    <!--錯誤日誌附加介質-->
    <!-- name屬性指定其名稱,type則是log4net.Appender命名空間的一個類的名稱,意思是,指定使用哪種介質-->
    <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
        <!--日誌輸出到exe程序這個相對目錄下-->
        <param name="File" value="logs\\errors\\" />
        <!--輸出的日誌不會覆蓋以前的信息-->
        <param name="AppendToFile" value="true" />
        <!--備份文件的個數-->
        <param name="MaxSizeRollBackups" value="50"/>
        <!--最小鎖定模型以允許多個進程可以寫入同一個文件-->
        <param name="MaxFileSize" value="10240" />
        <!--當前日誌文件的最大大小-->
        <param name="lockingModel"  type="log4net.Appender.FileAppender+MinimalLock" />
        <!--是否使用靜態文件名-->
        <param name="StaticLogFileName" value="false" />
        <!--日誌文件名-->
        <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
        <!--文件創建的方式,這裏是以Date方式創建-->
        <param name="RollingStyle" value="Date" />
        <!--錯誤日誌佈局-->
        <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="[%t]異常類:%c [%x] 異常信息:%m%n"  />
        </layout>
    </appender>
    <!--信息日誌附加介質-->
    <!-- name屬性指定其名稱,type則是log4net.Appender命名空間的一個類的名稱,意思是,指定使用哪種介質-->
    <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
        <!--日誌輸出到exe程序這個相對目錄下-->
        <param name="File" value="logs\\infos\\" />
        <!--輸出的日誌不會覆蓋以前的信息-->
        <param name="AppendToFile" value="true" />
        <!--備份文件的個數-->
        <param name="MaxSizeRollBackups" value="50" />
        <!--最小鎖定模型以允許多個進程可以寫入同一個文件-->
        <param name="MaxFileSize" value="10240" />
        <!--當前日誌文件的最大大小-->
        <param name="lockingModel"  type="log4net.Appender.FileAppender+MinimalLock" />
        <!--是否使用靜態文件名-->
        <param name="StaticLogFileName" value="false" />
        <!--日誌文件名-->
        <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
        <!--文件創建的方式,這裏是以Date方式創建-->
        <param name="RollingStyle" value="Date" />
        <!--信息日誌佈局-->
        <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="%m%n"  />
        </layout>
    </appender>
</log4net>

 

2.1.3.程序代碼

         a)依賴注入模式

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddLogging(logBuilder =>
{
    logBuilder.AddConsole();
    logBuilder.AddDebug();
    logBuilder.AddLog4Net();
});

var app = builder.Build();
app.MapControllers();


app.Run();

 

         b)工廠模式

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
var loggerFactory = LoggerFactory.Create(logBuilder =>
{
    logBuilder.ClearProviders();
    logBuilder.AddConsole();
    logBuilder.AddDebug();
    logBuilder.AddLog4Net();
    logBuilder.SetMinimumLevel(LogLevel.Trace);
});
ILogger _logger = loggerFactory.CreateLogger<Program>();
_logger.LogTrace("LogTrace");
_logger.LogDebug("LogDebug");
_logger.LogInformation("LogInformation");
_logger.LogWarning("LogWarning");
_logger.LogError("LogError");
_logger.LogCritical("LogCritical");


var app = builder.Build();
app.MapControllers();


app.Run();

 

2.2.傳統模式

說實話,俺是一個比較純粹的人,不太喜歡黑魔法,所以使用傳統方式記錄日誌,我更加喜歡。傳統方式記錄日誌的過程沒有改變,簡單記錄一下使用過程:

a)設置配置文件,操作如上,此處不再贅述。

b)創建Log4Writer類

    public class Log4Writer
    {
        private static readonly log4net.ILog loginfo = log4net.LogManager.GetLogger("loginfo");
        private static readonly log4net.ILog logerror = log4net.LogManager.GetLogger("logerror");
        public static void WriteLog(string info)
        {
            if (loginfo.IsInfoEnabled)
            {
                loginfo.Info(info);
            }
        }

        public static void WriteLog(string info, Exception ex)
        {
            if (logerror.IsErrorEnabled)
            {
                logerror.Error(info, ex);
            }
        }
    }

 

c)創建Log4Helper類

    public class LogHelper
    {
        private static object _objLocker = new object();
        private static bool _isConfigure = false;
        public static void Configure()
        {
            if (!_isConfigure)
            {
                lock (_objLocker)
                {
                    if (!_isConfigure)
                    {
                        _isConfigure = true;
                        log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo("log4net.config"));
                    }
                }
            }
        }
    }

 

d)在Program中啓用log4net

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

var app = builder.Build();
app.MapControllers();


jks.core.test.log.LogHelper.Configure();

app.Run();

 

e)使用測試

public IEnumerable<WeatherForecast> Get()
        {

            Log4Writer.WriteLog("aaaaaaaaaaaaaaaaaaaaaaa");


            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

 

2.3.特別說明

很多同學可能會問,爲什麼使用log4net,而不是其他第三方日誌程序包?

第一,因爲.net framework時就在用;第二,就是因爲它比較獨立;第三,我不僅僅需要將日誌寫入到硬盤文件裏,還需要寫入到專門的日誌系統,且日誌內容設計了固定的結構。

簡單的說,使用日誌工具記錄日誌到硬盤文件是次要的,記錄到專門的日誌系統纔是主要的、核心的。

 

三、總結

通過上述內容的分析、實驗和記錄,應該能夠在使用asp.net core中使用日誌了吧?以及如何從.net framework升級到.net core。

好了,就此結束。

 

程序源碼:https://gitee.com/kinbor/jks.core.test.log

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章