.NET 扩展 官方 Logger 实现将日志保存到本地文件
.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 实现将日志保存到本地文件的更多相关文章
- C#中使用Log4net日志输出到本地文件、Textbox或Listview
网上很多配置log4net的方法,但是排行靠前的 根本就没有说明清除,导致浪费了两个小时来搞清楚如何配置,真是无语,特写此文,给那些刚接触log4net的朋友 1.参考链接:http://blog.s ...
- Java读取oracle数据库中blob字段数据文件保存到本地文件(转载)
转自:https://www.cnblogs.com/forever2698/p/4747349.html package com.bo.test; import java.io.FileOutput ...
- Python3.4 获取百度网页源码并保存在本地文件中
最近学习python 版本 3.4 抓取网页源码并且保存在本地文件中 import urllib.request url='http://www.baidu.com' #上面的url一定要写明确,如果 ...
- 【Jmeter】jmeter提取response中的返回值,并保存到本地文件--BeanShell后置处理器
有个需求,需要在压测环境中,创建几十万的账号数据,然后再根据创建结果,查询到某些账号信息. 按照之前我的做法,直接Python调用API,然后再数据库查询: 但是近期所有开发人员的数据库访问权限被限制 ...
- Android View转为图片保存为本地文件,异步监听回调操作结果;
把手机上的一个View或ViewGroup转为Bitmap,再把Bitmap保存为.png格式的图片: 由于View转Bitmap.和Bitmap转图片都是耗时操作,(生成一个1M的图片大约500ms ...
- winform程序生成条形码并且并且保存到本地文件中。
今天公司让做一个输入数字.字母生成条形码并且可以以图片格式保存到本地.当看到这个需求时候感觉很搞笑,明明可以用文本框搞定的东西非得做个程序.哎,寄人篱下,不多说了,这就是养兵千日用兵一时. 我在网上找 ...
- C#中将String类型保存到本地文件的方法
今天刚刚遇到,要在WinForm中把一个xml保存到本地, 由于之前是学习java的,一时间还真不知道怎么写, 没想到C#居然那么方便,就3句代码就实现了我要的功能: StreamWriter sw ...
- 将nosetests的echo结果保存到本地文件
nose是很好用的python 测试框架. 但是一直很纠结如何将结果保存到本地.采用nosetests -h查看相关的options,找到一个xunit的东西,似乎可以实现功能. 测试结果: 可见,已 ...
- C# 中从网络上下载文件保存到本地文件
下面是C#中常用的从Internet上下载文件保存到本地的一些方法,没有太多的技巧. 1.通过 WebClient 类下载文件 WebClient webClient = new WebClien ...
随机推荐
- HMS Core AR Engine 2D图片/3D物体跟踪技术 助力打造更智能AR交互体验
AR技术已经被广泛应用于营销.教育.游戏.展览等场景.通过2D图像跟踪技术和3D物体跟踪技术,用户只需使用一台手机进行拍摄,即可实现海报.卡牌等平面物体以及文物.手办等立体物体的AR效果.尽管近年来2 ...
- Win10系统下怎么让局域网内其他电脑通过IP访问网站
最近,有位win10系统用户在电脑上制作好网站后,希望能让局域网内的其他电脑通过IP直接访问自己电脑的网站,以便得到更好地测试效果.可是,该用户操作了很久都没成功.那么,我们如何配置win10电脑的I ...
- 微信小程序开发 记录
采坑了 微信小程序--TabBar不出现的一种原因 学习微信小程序中,遇到底部的TabBar不出现的问题.经过多番尝试,终于解决问题.在此记录问题产生的原因和对策.下面先描述错误现象,接着指出错误原因 ...
- 国内GPU 厂商产品分布
抽空理了理国内目前已知显卡厂商的各类产品(来源与各个公司产品网站),可能不全,后续会实时更新. 目前来看,显卡市场还是国外两巨头+intel 占据了绝大数的市场,intel 在igpu上深耕了很多年, ...
- Java变量, 常量和作用域
目录 变量 作用域 局部变量 实例变量 类变量 常量 命名规范 视频课程 变量 变量就是可以变化的量 Java是一种强类型的语言, 每个变量都必须声明其类型 Java变量是程序中最基本的存储单元, 其 ...
- ExtJS 布局-Accordion布局(Accordion layout)
更新记录: 2022年6月2日 开始. 2022年6月3日 发布. 1.说明 accordion(手风琴)布局一次仅显示一个子组件,内置支持 折叠 和 展开.当需要堆叠多个子组件,并每次只显示一次时, ...
- C++ 炼气期之变量的生命周期和作用域
1. 前言 什么是变量的生命周期? 从变量被分配空间到空间被收回的这一个时间段,称为变量的生命周期. 什么是变量的作用域? 在变量的生命周期内,其存储的数据并不是在任何地方都能使用,变量能使用的范围, ...
- JS:函数
Function:函数 1. 定义一个函数:function functionname(argument) { 代码块 return }: 调用此函数:fn() 2.函数是定义了一种方法,只有被调用才 ...
- Docker 与 K8S学习笔记(二十四)—— 工作负载的使用
我们前面讲了很多关于Pod的使用,但是在实际应用中,我们不会去直接创建Pod,我们一般通过Kubernetes提供的工作负载(Deployment.DeamonSet.StatefulSet.Job等 ...
- 【python】自动更新pu口袋校园活动
[python]自动更新pu口袋校园活动 脚本目标: 1. 自动爬取pu口袋校园活动,筛选出需要的活动,此处我的筛选条件是线上活动,因为可以不用去就可以白嫖学时 2. 自动发送邮件到QQ邮箱,每次只发 ...