下面直接贴出实现代码

FileLoggerProvider

/// <summary>
/// 文件记录器提供商
/// </summary>
public class FileLoggerProvider : ILoggerProvider
{ /// <summary>
/// 配置
/// </summary>
private readonly IConfiguration configuration; /// <summary>
/// 构造方法
/// </summary>
/// <param name="configuration">配置</param>
public FileLoggerProvider(IConfiguration configuration)
{
this.configuration = configuration;
} /// <summary>
/// 创建记录器
/// </summary>
/// <param name="categoryName">类别名称</param>
/// <returns></returns>
public ILogger CreateLogger(string categoryName)
{
return new FileLogger(configuration, categoryName);
} /// <summary>
/// 释放方法
/// </summary>
public void Dispose()
{
}
}
  Lock
/// <summary>
/// IO锁
/// </summary>
public static class Lock
{ /// <summary>
/// 文件读写锁
/// </summary>
public static readonly ReaderWriterLockSlim fileLockSlim = null; ///// <summary>
///// 数据库读写锁
///// </summary>
//public static readonly ReaderWriterLockSlim dbLockSlim = null; /// <summary>
/// 构造方法
/// </summary>
static Lock()
{
fileLockSlim = new ReaderWriterLockSlim();
//dbLockSlim = new ReaderWriterLockSlim();
}
}

  FileLogger

/// <summary>
/// 文件记录器
/// </summary>
public class FileLogger : ILogger
{ /// <summary>
/// 配置
/// </summary>
private readonly IConfiguration configuration; /// <summary>
/// 类别名称
/// </summary>
private readonly string categoryName; /// <summary>
/// 构造方法
/// </summary>
/// <param name="configuration">配置</param>
/// <param name="categoryName">类别名称</param>
public FileLogger(IConfiguration configuration, string categoryName)
{
this.configuration = configuration;
this.categoryName = categoryName;
} /// <summary>
/// 开始范围
/// </summary>
/// <typeparam name="TState">状态类型</typeparam>
/// <param name="state">状态</param>
/// <returns></returns>
public IDisposable BeginScope<TState>(TState state)
{
return null;
} /// <summary>
/// 是否使用
/// </summary>
/// <param name="logLevel">日志级别</param>
/// <returns></returns>
public bool IsEnabled(LogLevel logLevel)
{
var list = new List<IConfigurationSection>();
list.AddRange(configuration.GetSection("Logging:LogLevel").GetChildren());
list.AddRange(configuration.GetSection("Logging:FileLog:LogLevel").GetChildren()); var category = list.LastOrDefault(f => this.categoryName.StartsWith(f.Key)); if (category == null)
{
category = list.LastOrDefault(f => f.Key == "Default");
} if (category != null && Enum.TryParse(typeof(LogLevel), category.Value, out var level))
{
return (int)(LogLevel)level <= (int)logLevel;
}
return 2 <= (int)logLevel;
} /// <summary>
/// 日志
/// </summary>
/// <typeparam name="TState">状态类型</typeparam>
/// <param name="logLevel">日志级别</param>
/// <param name="eventId">事件ID</param>
/// <param name="state">状态</param>
/// <param name="exception">异常</param>
/// <param name="formatter">格式化委托</param>
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (IsEnabled(logLevel))
{
try
{
Lock.fileLockSlim.EnterWriteLock();
var baseDirectory = configuration.GetSection("Logging:FileLog:BaseDirectory").Value;
var fileName = configuration.GetSection("Logging:FileLog:FileName").Value;
var extensionName = configuration.GetSection("Logging:FileLog:ExtensionName").Value; var directory = Path.Combine(AppContext.BaseDirectory, string.IsNullOrWhiteSpace(baseDirectory) ? "app_log" : baseDirectory); if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
if (string.IsNullOrWhiteSpace(fileName))
{
fileName = DateTime.Now.ToString("yyyy-MM-dd");
}
else
{
fileName = DateTime.Now.ToString(fileName);
}
extensionName = string.IsNullOrWhiteSpace(extensionName) ? ".log" : extensionName; var path = Path.Combine(directory, $"{fileName}{extensionName}");
var flag = true;
if (File.Exists(path))
{
var maxSize = configuration.GetSection("Logging:FileLog:MaxFileSize").Value;
var fileInfo = new FileInfo(path);
flag = fileInfo.Length / 1024.00 > (string.IsNullOrWhiteSpace(maxSize) ? 2048.00 : Convert.ToDouble(maxSize));
} var streamWrite = flag ? File.CreateText(path) : File.AppendText(path);
var dateTimeFormart = configuration.GetSection("Logging:FileLog:DateTimeFormat").Value; var logTime = DateTime.Now.ToString((string.IsNullOrWhiteSpace(dateTimeFormart) ? "yyyy-MM-dd HH:mm:ss.fff" : dateTimeFormart));
var message = formatter(state, exception); var stackTrace = exception?.StackTrace; var template = configuration.GetSection("Logging:FileLog:Template").Value; if (string.IsNullOrWhiteSpace(template))
{
streamWrite.WriteLine($"日志时间:{logTime} 类别名称:{categoryName} 日志级别:{logLevel} 消息:{message}"); if (!string.IsNullOrWhiteSpace(stackTrace))
{
streamWrite.WriteLine(stackTrace);
}
}
else
{
template = template.Replace("{logTime}", logTime, StringComparison.OrdinalIgnoreCase);
template = template.Replace("{catetoryName}", categoryName, StringComparison.OrdinalIgnoreCase);
template = template.Replace("{eventId}", eventId.Id.ToString(), StringComparison.OrdinalIgnoreCase);
template = template.Replace("{eventName}", eventId.Name, StringComparison.OrdinalIgnoreCase);
template = template.Replace("{logLevel}", logLevel.ToString(), StringComparison.OrdinalIgnoreCase);
template = template.Replace("{message}", message, StringComparison.OrdinalIgnoreCase);
template = template.Replace("{stackTrace}", stackTrace, StringComparison.OrdinalIgnoreCase);
template = template.Trim();
streamWrite.WriteLine(template);
} streamWrite.WriteLine();
streamWrite.Close(); var directoryInfo = new DirectoryInfo(directory);
var fileInfos = directoryInfo.GetFiles();
var fileCount = Convert.ToInt32(configuration.GetSection("Logging:FileLog:MaxFileCount").Value);
if (fileInfos.Length > fileCount && fileCount > 0)
{
var removeFileInfo = fileInfos.OrderBy(o => o.CreationTime).ThenBy(o => o.LastWriteTime).SkipLast(fileCount);
foreach (var item in removeFileInfo)
{
File.Delete(item.FullName);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"写入文件日志异常:{ex.Message}");
Console.WriteLine(ex.StackTrace);
}
finally
{
Lock.fileLockSlim.ExitWriteLock();
}
}
}
}
  ILoggingBuilderExtensions
/// <summary>
/// 日志构造扩展类
/// </summary>
public static class ILoggingBuilderExtensions
{ /// <summary>
/// 添加文件日志
/// </summary>
/// <param name="loggingBuilder">日志构建</param>
public static ILoggingBuilder AddFileLog(this ILoggingBuilder loggingBuilder)
{
loggingBuilder.Services.AddSingleton<FileLoggerProvider>();
var sevices = loggingBuilder.Services.BuildServiceProvider();
return loggingBuilder.AddProvider(sevices.GetService<FileLoggerProvider>());
} }

  

Json配置格式示例

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
},
"FileLog": {
"LogLevel": {
"Default": "Information"
},
"BaseDirectory": "app_log",
"FileName": "yyyy-MM-dd",
"ExtensionName": ".log",
"Template": "LogTime:{LogTime} CatetoryName:{CatetoryName} LogLevel:{LogLevel}\r\n{Message}\r\n{StackTrace}\r\n",
"MaxFileCount": 10,
"MaxFileSize": 2048,
"DateTimeFormat": "yyyy-MM-dd HH:mm:ss.fff"
}
}
}

  

分享 NET 5.x 自定义文件日志实现 原汁原味的更多相关文章

  1. (Unity)Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进展混淆,避免被反编译

    Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进行混淆,避免被反编译. 1.打开VS,博主所用版本是Visual Studio 2013. 2.新建一个VC项目 ...

  2. log4j.xml配置,包含自定义log4j日志级别及输出日志到不同文件

      一.配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configura ...

  3. 【分享】我们用了不到200行代码实现的文件日志系统,极佳的IO性能和高并发支持,附压力测试数据

    很多项目都配置了日志记录的功能,但是,却只有很少的项目组会经常去看日志.原因就是日志文件生成规则设置不合理,将严重的错误日志跟普通的错误日志混在一起,分析起来很麻烦. 其实,我们想要的一个日志系统核心 ...

  4. 【腾讯Bugly干货分享】微信mars 的高性能日志模块 xlog

    本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/581c2c46bef1702a2db3ae53 Dev Club 是一个交流移动 ...

  5. 简单的php自定义错误日志

    平时经常看php的错误日志,很少有机会去自己动手写日志,看了王健的<最佳日志实践>觉得写一个清晰明了,结构分明的日志还是非常有必要的. 在写日志前,我们问问自己:为什么我们有时要记录自定义 ...

  6. 自定义log4j日志级别

    转载自:  http://blog.csdn.net/seven_cm/article/details/26849821 自定义log4j日志级别 参考了网上资料:http://www.360doc. ...

  7. 装饰者模式的学习(c#) EF SaveChanges() 报错(转载) C# 四舍五入 保留两位小数(转载) DataGridView样式生成器使用说明 MSSQL如何将查询结果拼接成字符串 快递查询 C# 通过smtp直接发送邮件 C# 带参访问接口,WebClient方式 C# 发送手机短信 文件 日志 写入 与读取

    装饰者模式的学习(c#) 案例转自https://www.cnblogs.com/stonefeng/p/5679638.html //主体基类 using System;using System.C ...

  8. DJANGO-天天生鲜项目从0到1-005-FastDFS与Nginx打造自定义文件存储系统

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  9. (16)-Python3之--自定义logging日志模块

    1.自定义的日志模块如下: import logging from logging.handlers import TimedRotatingFileHandler import datetime f ...

随机推荐

  1. .NET E F(Entity Framework)框架 DataBase First 和 Code First 简单用法。

    EF是微软.NET平台官方的ORM(objet-relation mapping),就是一种对象-关系 映射,是将关系数据库种的业务数据用对象的形式表现出来,并通过面向对象的方式讲这些对象组织起来,实 ...

  2. Nginx在make时报错[objs/Makefile:469: objs/src/core/ngx_murmurhash.o] Error

    Nginx在make时报错[objs/Makefile:469: objs/src/core/ngx_murmurhash.o] Error   在安装目录下执行 vim obj/Markfile 把 ...

  3. R语言与医学统计图形【7】低级绘图函数

    R语言基础绘图系统 基础绘图包之低级绘图函数--气泡图.一页多图.背景网格.添加线条和散点.数学表达式 4.气泡图 symbols是高级绘图函数,可在图上添加标记,标记的形状包括:circles,sq ...

  4. R语言与医学统计图形【4】直方图、金字塔图

    R语言基础绘图系统 基础图形--直方图.金字塔图 3.直方图 参数设置及比较. op <- par(mfrow=c(2,3)) data <- rnorm(100,10,5) hist(d ...

  5. centos 安装reids

    1.安装tcl支持 yum install tcl 2.安装redis我们以最新的2.8.9为例 $ wget http://download.redis.io/releases/redis-2.8. ...

  6. SimpleNVR如何把安防监控画面推流到微信公众号直播

    背景需求 进入移动互联网时代以来,微信已成为许多企业除官网以外必备的宣传渠道,当3.2亿直播用户与九亿微信用户的势能增加,在微信上开启直播已成为越来越多企业的不二选择. 需求分析 微信公众号作为平台来 ...

  7. flink-----实时项目---day06-------1. 获取窗口迟到的数据 2.双流join(inner join和left join(有点小问题)) 3 订单Join案例(订单数据接入到kafka,订单数据的join实现,订单数据和迟到数据join的实现)

    1. 获取窗口迟到的数据 主要流程就是给迟到的数据打上标签,然后使用相应窗口流的实例调用sideOutputLateData(lateDataTag),从而获得窗口迟到的数据,进而进行相关的计算,具体 ...

  8. 转 android开发笔记之handler+Runnable的一个巧妙应用

    本文链接:https://blog.csdn.net/hfreeman2008/article/details/12118817 版权 1. 一个有趣Demo: (1)定义一个handler变量 pr ...

  9. oracle 外部表查alter日志

    --创建文件夹,路径是alter日志的路径 create or replace directory data_dir as '/u01/app/oracle/diag/rdbms/orcl/orcl/ ...

  10. 【Linux】【Basis】Grub

    GRUB(Boot Loader):   1. grub: GRand Unified Bootloader grub 0.x: grub legacy grub 1.x: grub2   2. gr ...