给微软的日志框架写一个基于委托的日志提供者

动手造轮子:给微软的日志框架写一个基于委托的日志提供者

Intro

微软的日志框架现在已经比较通用,有时候我们不想使用外部的日志提供者,但又希望提供一个比较简单的委托就可以实现日志记录,于是就有了后面的探索和实现。

Solution

基于委托的 LoggerProvider 实现代码:

自定义 Logger

微软的日志框架中记录日志是通过 ILogger 来做的,扩展支持其他日志框架的时候也需要实现相应的 ILogger 来适配

ILoggerProvider 会需要实现创建 ILogger 的接口 CreateLogger(stringcategoryName) ,所以我们可以先来实现对应的 ILogger,实现如下:

这里的实现简单化处理,默认处理所有级别的日志,如果要设定日志级别可以通过日志的 Fliter 来做,这里就不做检查和限制了

private class DelegateLogger : ILogger
{private readonly string _categoryName;private readonly Action<string, LogLevel, Exception, string> _logAction;public DelegateLogger(string categoryName, Action<string, LogLevel, Exception, string> logAction){_categoryName = categoryName;_logAction = logAction;}public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter){if (null != _logAction){var msg = formatter(state, exception);_logAction.Invoke(_categoryName, logLevel, exception, msg);}}public bool IsEnabled(LogLevel logLevel){return true;}public IDisposable BeginScope<TState>(TState state){return NullScope.Instance;}
}

自定义 ILoggerProvider

有了 ILogger 之后接着我们来定义我们的 ILoggerProvider,这里我们针对 Logger 名称(CategoryName)做了区分,如果不关注 Logger 名称的话也可以使用同一个 Logger 这样就不需要下面的并发字典了,只用一个 ILogger 对象就可以了,可以根据自己的需要进行定制

实现代码如下:

[ProviderAlias("Delegate")]
public class DelegateLoggerProvider : ILoggerProvider
{private readonly Action<string, LogLevel, Exception, string> _logAction;private readonly ConcurrentDictionary<string, DelegateLogger> _loggers = new ConcurrentDictionary<string, DelegateLogger>();public DelegateLoggerProvider(Action<string, LogLevel, Exception, string> logAction){_logAction = logAction;}public void Dispose(){_loggers.Clear();}public ILogger CreateLogger(string categoryName){return _loggers.GetOrAdd(categoryName, category => new DelegateLogger(category, _logAction));}
}

定义扩展方法

为了方便使用,我们需要定义两个扩展方法来优化我们使用的方式:

定义 ILoggerFactory 的扩展方法:

/// <summary>
/// AddDelegateLoggerProvider
/// </summary>
/// <param name="loggerFactory">loggerFactory</param>
/// <param name="logAction">logAction</param>
/// <returns>loggerFactory</returns>
public static ILoggerFactory AddDelegateLogger(this ILoggerFactory loggerFactory, Action<string, LogLevel, Exception, string> logAction)
{loggerFactory.AddProvider(new DelegateLoggerProvider(logAction));return loggerFactory;
}

定义 ILoggingBuilder 的扩展方法:

public static ILoggingBuilder AddDelegateLogger(this ILoggingBuilder loggingBuilder,Action<string, LogLevel, Exception, string> logAction)
{return loggingBuilder.AddProvider(new DelegateLoggerProvider(logAction));
}

使用示例

ILoggerFactory loggerFactory = new LoggerFactory();
//loggerFactory.AddConsole();
loggerFactory.AddDelegateLogger((category, logLevel, exception, msg) =>{Console.WriteLine($"{category}:[{logLevel}] {msg}\n{exception}");}
);

日志输出效果如下:

Reference

  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Logging/MicrosoftLoggingLoggerExtensions.cs

  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/DotNetCoreSample/Program.cs#L83

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++分析使用拷贝控制成员和调用构造函数的时机

我们来分析下面这段代码&#xff1a; #include <iostream> #include <vector>using namespace std;struct X {X() {cout << "构造函数X()" << endl;}X(const X &) {cout << "拷贝构造函数X(const X&)" << en…

mybatis mysql模糊查询_详解MyBatis模糊查询LIKE的三种方式

模糊查询也是数据库SQL中使用频率很高的SQL语句&#xff0c;使用MyBatis来进行更加灵活的模糊查询。直接传参法直接传参法&#xff0c;就是将要查询的关键字keyword,在代码中拼接好要查询的格式&#xff0c;如%keyword%,然后直接作为参数传入mapper.xml的映射文件中。public vo…

《C++ Primer》13.1.4节练习

练习13.14: 这是一个典型的应该定义拷贝控制成员的场合。如果不定义拷贝构造函数和拷贝赋值运算符&#xff0c;依赖合成的版本&#xff0c;则在拷贝构造和赋值时&#xff0c;会简单复制数据成员。对本问题来说&#xff0c;就是将序号简单复制给新对象。 因此&#xff0c;代码中…

十问十答 CDDL 许可证

今天我们来整理一下通用开发和发行许可证 CDDL 的十大问题清单。通用开发与发行许可证&#xff08;Common Development and Distribution License&#xff0c;CDDL&#xff09;由已被甲骨文公司收购的太阳微系统公司&#xff08;Sun Microsystems&#xff09;发布的一种开源许可…

浅谈java spring_浅谈Spring(一)

Spring是当前比较流行的基于Java语言的MVC框架,所谓框架也就是它已经实现好了诸多东西,使java开发人员能把精力尽量放在业务逻辑上.Spring技术的特点是IOC, 即反向注入,主要应用的是XML技术和POJO(简单Java对象),Spring要达到的目的其实很简单,就是尽量简化原来Java中的地层数据…

Http Server API路由请求到web程序

引言接上文&#xff0c;容器内web程序一般会绑定到http://0.0.0.0:{某监听端口}或http://:{某监听端口}&#xff0c;以确保使用容器IP可以访问到web应用。正如我们在ASP.NET Core官方镜像显示的&#xff0c;ASP.NET Core程序在容器内80端口监听请求This image sets the ASPNETC…

mysql 多行拼接注入_MySQL注入汇总

Mysql注释符&#xff1a;单行注释&#xff1a; # 在对URL使用过程中可能遇到Unicode编码问题&#xff0c;可常用%23代替多行注释&#xff1a;/**/单行注释&#xff1a; -- 此处需要注意后面存在空格&#xff0c;否则报错0.万能密码(基于SQL验证&#xff0c;SQL注入)aaa or 1#aa…

《C++ Primer》13.1.6节练习(部分)

练习13.18: #include <iostream> #include <string> using namespace std;class Employee {private:static int sn;public:Employee() {mysn sn;}Employee(const string &s) {name s;mysn sn;}const string &get_name() {return name;}int get_mysn() …

用Azure Custom Vision 零代码创建一个口罩识别模型

新冠肺炎下&#xff0c;地球是一家&#xff0c;不分国籍&#xff0c;不分种族&#xff0c;或者现在只能呆在家中&#xff0c;但是也是一种对抗疫的支持。停课不停学留在家中&#xff0c;不仅是对学生&#xff0c;对于所有人都是有用的。在现阶段&#xff0c;大家可能最需要的不…

C++拷贝构造函数调用时机分析

让我们来分析下面这段代码&#xff1a; #include <iostream> #include <string> using namespace std;class Employee {private:static int sn;public:Employee() {cout << "Employee()" << endl;mysn sn;}Employee(const string &s) …

java开发中准则怎么写_Java开发中通用的方法和准则20条

1. 不要在常量和变量中出现易混淆的字母包名全小写、类名首字母全大写、常量全部大写并下划线分割、变量采用驼峰命名等&#xff0c;这些是最基本的Java编码规范。public class TestDemo {public static void main(String[] args) {long i 1l;System.out.println("i的两倍…

百万年薪程序员的7点能力

作者介绍findyi&#xff0c;腾讯、360码农&#xff0c;前哒哒少儿英语技术VP&#xff0c;现任土豆教育CTO。几周前&#xff0c;微盟爆了个大雷&#xff0c;数据库让内部员工删库跑路。写了篇文章&#xff0c;做了一些我的判断&#xff1a;从微盟36小时故障&#xff0c;谈谈数据…

《C++ Primer》13.1.1节练习

练习13.1: 如果构造函数的第一个参数是自身类类型的引用&#xff0c;且所有其他参数&#xff08;如果有的话&#xff09;都有默认值&#xff0c;则此构造函数是拷贝构造函数。拷贝构造函数在以下几种情况下会被使用&#xff1a; ●拷贝初始化&#xff08;用定义变量&#xff09…

Java将五个整数存入整形数组_异常处理:从命令行输入5个整数,放入一整型数组,然后打印输出。。。...

从命令行输入5个整数&#xff0c;放入一整型数组&#xff0c;然后打印输出。要求&#xff1a;如果输入数据不为整数&#xff0c;要捕获输入不匹配异常&#xff0c;显示“请输入整数”&#xff1b;如果输入数据多余5个&#xff0c;捕获数组越界异常&#xff0c;显示“请输入5个整…

优秀的开发者从命名开始

有人说&#xff0c;命名能力也能体现一个程序员的基本编程素养。我很赞成这句话&#xff01;作为开发人员逃不过起名字这一关的,大到项目名、模块名&#xff0c;小到类名、方法名、参数名、参数名、变量名。而命名又对代码的质量和可读性起到很关键的决定。如何码出高质量的代码…

《C++ Primer》13.1.2节练习

练习13.6&#xff1a; 拷贝赋值运算符本身是一个重载的赋值运算符&#xff0c;定义为类的成员函数&#xff0c;左侧运算对象绑定到隐含的this参数&#xff0c;而右侧运算对象是所属类类型的&#xff0c;作为函数的参数&#xff0c;函数返回指向其左侧运算对象的引用。 当对类对…

PHP自动判断用户会员过期,php,_定时扣除用户过期积分,但平台用户量比较大,有没有好的解决方法?,php - phpStudy...

定时扣除用户过期积分&#xff0c;但平台用户量比较大&#xff0c;有没有好的解决方法&#xff1f;最近网站实行用户积分过期制度&#xff0c;只保留用户近三月积分&#xff0c;三月前未使用积分进行扣除但平台用户量比较大&#xff0c;感觉这样做会出问题&#xff0c;有没有好…

【复杂系统迁移 .NET Core平台系列】之认证和授权

源宝导读&#xff1a;微软跨平台技术框架—.NET Core已经日趋成熟&#xff0c;已经具备了支撑大型系统稳定运行的条件。本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验。一、背景随着ERP的产品线越来越多&#xff0c;业务关联也日益复杂&#xff0c;…

《C++ Primer》13.1.3节练习

练习13.9: 析构函数完成与构造函数相反的工作&#xff1a;释放对象使用的资源&#xff0c;销毁非静态数据成员。从语法上看&#xff0c;它是类的一个成员函数&#xff0c;名字是波浪号接类名&#xff0c;没有返回值&#xff0c;也不接受参数。 当一个类没有定义析构函数时&…

php冒泡程序讲解,PHP冒泡排序程序代码与源代码

冒泡排序是php中众多排序中的一个最简单的排序方法了下面一聚教程小伙伴就同各位介绍一个冒泡排序的例子&#xff0c;希望能帮助到各位。冒泡排序简介&#xff1a;冒泡排序(Bubble Sort)&#xff0c;是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的数列&#…