1. 程式人生 > 其它 >如何建立自定義的日誌記錄---Net Core 3.1

如何建立自定義的日誌記錄---Net Core 3.1

技術標籤:.Netc#.net

最近寫了一個webapi 的專案,發現專案裡沒有寫日誌。導致一些問題出現後,無法定位到。所以必須新增上日誌,沒辦法誰讓我寫的程式碼沒有測試那麼多,出現的情況考慮的不是那麼周全。閒話不多說。下面開始

首先呢Net Core 上Logging 是由幾個介面的,ILoggerFactory,ILoggerProvider,ILogger。這三個之間的關係,很多文章都說過了。我這裡就不再說了。我當時記得看過這樣一句話。說的是ILoggerFactory 可以生成Logger,ILoggerProvider 也可以生成Logger,但是呢,生成的東西是不一樣的。ILoggerFactory 生成的ILogger 內部是根據ILoggerProvider生成的,可以說,還是ILoggerProvider 生成的Logger.

在net core 是存在ILoggerFactory的例項

的名字就是LoggerFactory ,所以我們不用去做類實現它,那麼我們需要做類去實現另外的兩個。下面我摘出一下我的程式碼。

public class CustomLoggerConfiguration
    {
        public int EventId { get; set; }
        public LogLevel LogLevel { get; set; } = LogLevel.Information;
        public string FilePath { get; set; } = Path.Combine(AppContext.BaseDirectory, "log.txt");
    }

這個類是做了一下配置,主要是設定一下檔案的儲存路徑

public class CustomLogger : ILogger
    {
        private readonly string _name;
        private readonly CustomLoggerConfiguration _config;

        public CustomLogger(string name, CustomLoggerConfiguration config) => (_name, _config) = (name, config);
        public IDisposable BeginScope<TState>(TState state)
        {
            return default;
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return logLevel == _config.LogLevel;
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }
            if (_config.EventId == 0 || _config.EventId == eventId.Id)
            {
                WriteToFile($"[{eventId.Id,2}: {logLevel,-12}]");

                WriteToFile($"     {_name} - {formatter(state, exception)}");
            }
        }
        public void WriteToFile(string content)
        {
            try
            {
                string logFile = _config.FilePath;

                FileStream fs;
                StreamWriter sw;
                if (File.Exists(logFile))
                    fs = new FileStream(logFile, FileMode.Append, FileAccess.Write);
                else
                    fs = new FileStream(logFile, FileMode.Create, FileAccess.Write);

                sw = new StreamWriter(fs);
                sw.WriteLine(content);
                sw.Close();
                fs.Close();
            }
            catch
            { }
        }
    }

這個類就是實現ILogger 的介面的類,主要就是實現介面,能夠寫入到檔案中

另外的兩個類,CustomLogProvider ,CustomLogExtension 是參照官方文件上抄寫的

public static class CustomLogExtensions
    {
        public static ILoggingBuilder AddCustomLogger(this ILoggingBuilder builder, CustomLoggerConfiguration configure)
        {
            ILoggerProvider provider = new CustomLogProvider(configure);
            builder.AddProvider(provider);
            return builder;
        }
        public static ILoggingBuilder AddCustomLogger(
         this ILoggingBuilder builder) =>
         builder.AddCustomLogger(
             new CustomLoggerConfiguration());

        public static ILoggingBuilder AddCustomLogger(
            this ILoggingBuilder builder,
            Action<CustomLoggerConfiguration> configure)
        {
            var config = new CustomLoggerConfiguration();
            configure(config);

            return builder.AddCustomLogger(config);
        }
    }
public class CustomLogProvider : ILoggerProvider
    {
        private readonly CustomLoggerConfiguration _config;
        private readonly ConcurrentDictionary<string, CustomLogger> _loggers =
        new ConcurrentDictionary<string, CustomLogger>();
        public CustomLogProvider(CustomLoggerConfiguration configure)
        {
            _config = configure;
        }
        public ILogger CreateLogger(string categoryName) =>
         _loggers.GetOrAdd(categoryName, name => new CustomLogger(name, _config));

        public void Dispose() => _loggers.Clear();
    }

下面就是最主要的了,如何使用這些類

需要在Program.cs 這個類裡面進行操作,找到方法

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureLogging(builder =>
                builder.ClearProviders()
                .AddProvider(
                    new CustomLogProvider(
                        new CustomLoggerConfiguration
                        {
                            LogLevel = LogLevel.Error
                        }))
                .AddCustomLogger()
                .AddCustomLogger(configuration =>
                {
                    configuration.LogLevel = LogLevel.Warning;
                }))
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

注意:這裡我添加了三個loggerProvider,因為我寫的實現的時候,寫的一個provider 只能處理一種級別的日誌,從程式碼中可以看出來,一個是LogLevel.Error 處理錯誤的。一個是處理警告的,還有一個是處理Information的,應該比較容易理解

由於依賴注入的關係,我們在需要用日誌的地方,在他的建構函式中,直接注入ILogger<T> 就行了,比如下面的程式碼

public readonly IMongoCollection<ElementDtoNew> _collection;
        private readonly ILogger<ElementDtoNew> _logger;
        public ElementDtoNewService(IDatabaseSettings databaseSettings,ILogger<ElementDtoNew> logger)
        {
            var client = new MongoClient(databaseSettings.ConnectionString);
            var db = client.GetDatabase(databaseSettings.DatabaseName);

            var collection = db.ListCollectionNames();

            _logger = logger;
            _logger.LogInformation("Hello World!");
        }

這樣記錄就會寫到你定義的位置了。

結語

寫這篇文章的目的呢,其實就是讓我自己記住,不要忘了,其實理解並不是很深,我好像看他的原始碼,我記得之前有人說,可以找到原始碼,但是我現在不知道在哪可以看到。