.NET 项目默认情况下 日志是使用的 ILogger 接口,默认提供一下四种日志记录程序:
- 控制台
- 调试
- EventSource
- EventLog
这四种记录程序都是默认包含在 .NET 运行时库中。关于这四种记录程序的详细介绍可以直接查看微软的官方文档 https://docs.microsoft.com/zh-cn/dotnet/core/extensions/logging-providers
今天给大家分享自己实现一个日志记录程序,继承自 ILogger 接口,实现将日志记录到本地的 txt 文件中,并包含一个自动清理过期日志的功能任务。
类库的整体代码结构如下:

Models 文件夹中存放 LoggerSetting.cs 是 该模块注入服务时需要的配置参数- namespace Logger.LocalFile.Models
- {
- public class LoggerSetting
- {
- /// <summary>
- /// 保存天数
- /// </summary>
- public int SaveDays { get; set; } = 7;
- }
- }
复制代码
Tasks 文件夹中存放的 LogClearTask.cs 是用于自动清理过期日志的任务,会在日志服务注入的同时启动,会通过配置的保存天数参数,定期删除超过实现的日志文件- using Common;
- using Logger.LocalFile.Models;
- using Microsoft.Extensions.Hosting;
- using Microsoft.Extensions.Options;
- namespace Logger.LocalFile.Tasks
- {
- public class LogClearTask : BackgroundService
- {
- private readonly int saveDays;
- public LogClearTask(IOptionsMonitor<LoggerSetting> config)
- {
- saveDays = config.CurrentValue.SaveDays;
- }
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
- {
- while (!stoppingToken.IsCancellationRequested)
- {
- try
- {
- string basePath = Directory.GetCurrentDirectory().Replace("\", "/") + "/Logs/";
- if (Directory.Exists(basePath))
- {
- List<string> logPaths = IOHelper.GetFolderAllFiles(basePath).ToList();
- var deleteTime = DateTime.UtcNow.AddDays(-1 * saveDays);
- if (logPaths.Count != 0)
- {
- foreach (var logPath in logPaths)
- {
- var fileInfo = new FileInfo(logPath);
- if (fileInfo.CreationTimeUtc < deleteTime)
- {
- File.Delete(logPath);
- }
- }
- }
- }
- }
- catch
- {
- }
- await Task.Delay(1000 * 60 * 60 * 24, stoppingToken);
- }
- }
- }
- }
复制代码
ILoggingBuilderExtensions 是应用注入服务的扩展方法,内容如下- using Logger.LocalFile.Models;
- using Logger.LocalFile.Tasks;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Hosting;
- using Microsoft.Extensions.Logging;
- namespace Logger.LocalFile
- {
- public static class ILoggingBuilderExtensions
- {
- public static void AddLocalFileLogger(this ILoggingBuilder builder, Action<LoggerSetting> action)
- {
- builder.Services.Configure(action);
- builder.Services.AddSingleton<ILoggerProvider, LocalFileLoggerProvider>();
- builder.Services.AddSingleton<IHostedService, LogClearTask>();
- }
- }
- }
复制代码
LocalFileLogger 是日志的保存执行方法,内容如下- using Common;
- using Microsoft.Extensions.Logging;
- using System.Text;
- namespace Logger.LocalFile
- {
- public class LocalFileLogger : ILogger
- {
- private readonly string categoryName;
- private readonly string basePath;
- public LocalFileLogger(string categoryName)
- {
- this.categoryName = categoryName;
- basePath = Directory.GetCurrentDirectory().Replace("\", "/") + "/Logs/";
- if (Directory.Exists(basePath) == false)
- {
- Directory.CreateDirectory(basePath);
- }
- }
- public IDisposable BeginScope<TState>(TState state)
- {
- return default!;
- }
- public bool IsEnabled(LogLevel logLevel)
- {
- if (logLevel != LogLevel.None)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
- {
- if (IsEnabled(logLevel))
- {
- if (state != null && state.ToString() != null)
- {
- var logContent = state.ToString();
- if (logContent != null)
- {
- if (exception != null)
- {
- var logMsg = new
- {
- message = logContent,
- error = new
- {
- exception?.Source,
- exception?.Message,
- exception?.StackTrace
- }
- };
- logContent = JsonHelper.ObjectToJson(logMsg);
- }
- var log = new
- {
- CreateTime = DateTime.UtcNow,
- Category = categoryName,
- Level = logLevel.ToString(),
- Content = logContent
- };
- string logStr = JsonHelper.ObjectToJson(log);
- var logPath = basePath + DateTime.UtcNow.ToString("yyyyMMddHH") + ".log";
- File.AppendAllText(logPath, logStr + Environment.NewLine, Encoding.UTF8);
- }
- }
- }
- }
- }
- }
复制代码
LocalFileLoggerProvider 是Logger执行方法向外部的供应者,内容如下:- using Microsoft.Extensions.Logging;
- using System.Collections.Concurrent;
- namespace Logger.LocalFile
- {
- public class LocalFileLoggerProvider : ILoggerProvider
- {
- private readonly ConcurrentDictionary<string, LocalFileLogger> loggers = new();
- public ILogger CreateLogger(string categoryName)
- {
- return loggers.GetOrAdd(categoryName, new LocalFileLogger(categoryName));
- }
- public void Dispose()
- {
- loggers.Clear();
- GC.SuppressFinalize(this);
- }
- }
- }
复制代码
当我们其他项目想要使用我们这个 Logger.LocalFile 类库时,只要添加该类库的引用,然后在启动服务时进行注入即可,注入方法如下:
Web 项目注入方式- //注册本地文件日志服务
- builder.Logging.AddLocalFileLogger(options => { options.SaveDays = 7; });
复制代码
控制台项目注入方式- .ConfigureLogging((hostContext, builder) =>
- {
- //注册本地文件日志服务
- builder.AddLocalFileLogger(options => { options.SaveDays = 7; });
- })
- .Build();
复制代码
Web 项目直接在 builder 后面编写注入就可以,控制台项目需要先 .ConfigureLogging 才可以,这是两者的区别。
这样就注入了我们自己编写的日志记录程序,项目运行时会在项目的 Logs 文件夹中产生日志文件,如下图


至此 .NET 扩展 官方 Logger 实现将日志保存到本地文件就讲解完了,有任何不明白的,可以在文章下面评论或者私信我,欢迎大家积极的讨论交流,有兴趣的朋友可以关注我目前在维护的一个 .net 基础框架项目,项目地址如下https://github.com/berkerdong/NetEngine.githttps://gitee.com/berkerdong/NetEngine.git
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |