如何建立自定義的日誌記錄---Net Core 3.1
最近寫了一個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!");
}
這樣記錄就會寫到你定義的位置了。
結語
寫這篇文章的目的呢,其實就是讓我自己記住,不要忘了,其實理解並不是很深,我好像看他的原始碼,我記得之前有人說,可以找到原始碼,但是我現在不知道在哪可以看到。