下面直接贴出实现代码

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. Codeforces 1332G - No Monotone Triples(数据结构综合)

    Codeforces 题目传送门 & 洛谷题目传送门 首先打表即可发现对于任意长度 \(\ge 5\) 的序列总存在一个 Monotone triple,证明不会实在不行直接 \(5^5\) ...

  2. Codeforces 585E - Present for Vitalik the Philatelist(简单莫反+狄利克雷前缀和)

    Codeforces 题目传送门 & 洛谷题目传送门 一道不算太难的 D1E 罢--虽然我不会做/kk u1s1 似乎这场 Div1 挺水的?F 就是个 AC 自动机板子还被评到了 3k2-- ...

  3. wget 命令用法

    wget 命令用法 1. 用法/命令格式 wget [OPTION]... [URL]... wget [参数列表] [目标软件.网页的网址] 长选项所必须的参数在使用短选项时也是必须的 2. 常用参 ...

  4. 【3】蛋白鉴定软件之Mascot

    目录 1.简介 2.配置 2.1在线版本 2.2 服务器版本 3.运行 3.1 在线版本 3.2 服务器版本 4.结果 1.简介 Mascot是非常经典的蛋白鉴定软件,被Frost & Sul ...

  5. 68-Binary Tree Postorder Traversal

    Binary Tree Postorder Traversal My Submissions QuestionEditorial Solution Total Accepted: 97358 Tota ...

  6. SourceTree使用图解-转

    这篇文档的目的是:让使用Git更轻松. 看完这篇文档你能做到的是: 1.简单的用Git管理项目. 2.怎样既要开发又要处理发布出去的版本bug情况. SourceTree是一个免费的Git图形化管理工 ...

  7. zabbix 内网机器通信状态

    a=0 for xgip in ${xgipset[*]} do let a+=1 fping $xgip|grep alive >/dev/null if [ $a != 3 ];then i ...

  8. 使用 CliWrap 让C#中的命令行交互举重若轻

    在代码中进行命令行交互是一个很常见的场景, 特别是在一些CI CD 自动化流程中, 在这之前我们会使用 System.Diagnostics.Process API, 现在有一个更灵活的工具 CliW ...

  9. 零基础学习java------40---------Maven(maven的概念,安装,maven在eclipse中使用),springboot(spring整合springmvc(注解),spring整合mybatis(常见的配置文件)),前端页面(bootstrap软件)

    一 maven 1. Maven的相关概念 1.1 项目开发中遇到的问题 (1)都是同样的代码,为什么在我的机器上可以编译执行,而在他的机器上就不行? (2)为什么在我的机器上可以正常打包,而配置管理 ...

  10. C++福尔摩斯的约会

    这道题的要求总结如下: 1.DAY 星期 大写字母:A B C D E F G2.HH 时 数字+大写字母 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M ...