优化 .NET Core logging 中的泛型 logger

优化 .NET Core logging 中的泛型 logger

Intro

在微软的 logging 组件中,我们可以比较方便的使用泛型 Logger,如:ILogger<Generic> 这样的,

但是如果泛型 Logger 的类型是一个泛型类型就会有些问题,具体的泛型参数不会作为 categoryName 的一部分,我们可以实现一个自己的 ILogger<T> 来改变这个行为,详细可以参考下面的介绍

Reproduce

这个问题非常好重现,只需要一个测试的泛型类就可以了,我写了一个简单的测试类,定义如下:

private class GenericTest<T>
{private readonly ILogger<GenericTest<T>> _logger;public GenericTest(ILogger<GenericTest<T>> logger){_logger = logger;}public void Test() => _logger.LogInformation("test");
}

测试代码如下:

using var services = new ServiceCollection().AddLogging(builder => builder.AddConsole()).AddSingleton(typeof(GenericTest<>)).BuildServiceProvider();
services.GetRequiredService<GenericTest<int>>().Test();
services.GetRequiredService<GenericTest<string>>().Test();

这里使用了两个泛型类型,一个泛型参数是 int,一个是 string,来看上面代码的输出结果吧,输出结果如下:

可以看到,默认的日志行为我们没有办法区分泛型类的泛型参数具体是什么,这对于我们来说有时候是很不方便的

What's inside

我们可以在 Github 上找到 logging 组件的源代码,可以参考:https://github.com/dotnet/runtime/blob/fa06656c41947e22fc6efd909cce0a6a180f1078/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LoggerT.cs

通过源码我们可以看到默认的行为,并不会记录泛型参数,经过测试如果我们需要包含泛型参数信息只需要把 includeGenericParameters 参数设置为 true 即可,既然明确了如何实现我们期望的效果改起来就会很简单

Cutom Generic Logger

微软的 Logging 非常的依赖注入,泛型的 Logger 也是依赖注入的,我们只需要注入自己的泛型 Logger 实现就可以代替默认的行为了,可以参考:https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Logging/src/LoggingServiceCollectionExtensions.cs#L42


为了不造成 breaking change,我们可以加一个配置,默认还是与微软现在的行为保持一致,针对想要区分的类型使用带泛型参数的行为,实现代码如下:

// 泛型 logger 配置
public sealed class GenericLoggerOptions
{// 返回 true 则使用带泛型参数的 typeName,否则使用默认的行为public Func<Type, bool>? FullNamePredict { get; set; }
}internal sealed class GenericLogger<T> : ILogger<T>
{private readonly ILogger _logger;/// <summary>/// Creates a new <see cref="GenericLogger{T}"/>./// </summary>/// <param name="factory">The factory.</param>/// <param name="options">GenericLoggerOptions</param>public GenericLogger(ILoggerFactory factory, IOptions<GenericLoggerOptions> options){if (factory == null){throw new ArgumentNullException(nameof(factory));}// 通过配置的委托来判断是否要包含泛型参数var includeGenericParameters = options.Value.FullNamePredict?.Invoke(typeof(T)) == true;_logger = factory.CreateLogger(TypeHelper.GetTypeDisplayName(typeof(T), includeGenericParameters: includeGenericParameters, nestedTypeDelimiter: '.'));}/// <inheritdoc />IDisposable ILogger.BeginScope<TState>(TState state){return _logger.BeginScope(state);}/// <inheritdoc />bool ILogger.IsEnabled(LogLevel logLevel){return _logger.IsEnabled(logLevel);}/// <inheritdoc />void ILogger.Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter){_logger.Log(logLevel, eventId, state, exception, formatter);}public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) => throw new NotImplementedException();public bool IsEnabled(LogLevel logLevel) => throw new NotImplementedException();public IDisposable BeginScope<TState>(TState state) => throw new NotImplementedException();
}

TypeHelper 中的方法就是微软 Logging 中引用的 TypeNameHelper,因为是 internal,所以单独拷出来一份,

上面的 Logger 与微软默认的 logger 唯一的不同之处就在于多了一个配置。。

为了使用起来方便,定义了一个 ILoggingBuilder 的扩展方法,定义如下:

public static ILoggingBuilder UseCustomGenericLogger(this ILoggingBuilder loggingBuilder, Action<GenericLoggerOptions> genericLoggerConfig)
{Guard.NotNull(loggingBuilder, nameof(loggingBuilder));Guard.NotNull(genericLoggerConfig, nameof(genericLoggerConfig));loggingBuilder.Services.Configure(genericLoggerConfig);loggingBuilder.Services.AddSingleton(typeof(ILogger<>), typeof(GenericLogger<>));return loggingBuilder;
}

好了,现在我们来测试一下我们自己的泛型 logger 吧,测试代码如下:

using var services = new ServiceCollection().AddLogging(builder => builder.AddConsole().UseCustomGenericLogger(options => options.FullNamePredict = _ => true)).AddSingleton(typeof(GenericTest<>)).BuildServiceProvider();
services.GetRequiredService<GenericTest<int>>().Test();
services.GetRequiredService<GenericTest<string>>().Test();

输出结果如下:

可以看到现在的输出日志中已经包含了泛型类型的泛型参数,如果你对自己名称还不够满意,也可以自定义 GetTypeDisplayName 的行为

More

上面的测试代码有需要的可以从 Github 上获取:https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/DotNetCoreSample/LoggerTest.cs#L37

感觉泛型参数还是记录一下的比较好,这样我们才能知道具体是哪一个类型打印出来的日志,像第一种方式打印出来的日志,完全就是一脸懵逼,真正出现了问题,完全不知道是哪一个类型的日志,只能靠猜了,这体验就太不好了,不过还好我们可以比较方便的进行定制。

不知道你是否也有这样的想法呢,在 Github 上提了一个 issue https://github.com/dotnet/runtime/issues/51368,如果感兴趣,可以关注一下 ,留下你的看法

References

  • https://github.com/dotnet/runtime/issues/51368

  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/DotNetCoreSample/LoggerTest.cs#L37

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

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

相关文章

charts漏斗图表_ECharts漏斗图属性与实例介绍

ECharts漏斗图在 ECharts 系列中&#xff0c;漏斗图使用 series[i]-funnel 表示。漏斗图适用于业务流程比较规范、周期长、环节多的流程分析&#xff0c;通过漏斗各环节业务数据的比较&#xff0c;能够直观地发现和说明问题所在。示例&#xff1a;ECharts漏斗图属性type在漏斗图…

原来R语言还有这些不为人知的用处!

开学钜惠已经进行了好些天啦&#xff0c;前两天小天介绍了关于python课程的开学季限时优惠&#xff08;传送门&#xff09;&#xff0c;你以为这样就结束了吗&#xff1f;不不不&#xff0c;还有R语言系列的优惠没讲过呢。接下来&#xff0c;小天来详细说明一下&#xff01;19月…

记一次 .NET医院公众号程序 线程CPU双高分析

一&#xff1a;背景 1. 讲故事上周四有位朋友加wx咨询他的程序出现 CPU 线程 双高的情况&#xff0c;希望我能帮忙排查下&#xff0c;如下图&#xff1a;从截图看只是线程爆高&#xff0c;没看到 cpu 爆高哈????????????&#xff0c;有意思的是这位朋友说他&#…

各种学习资料收录

http://topic.csdn.net/u/20120111/18/2DACB0AB-1C29-4AB7-9EF9-F53D5B0A8CD6.html C#串口操作资料转载于:https://www.cnblogs.com/youshan/archive/2012/01/19/2327324.html

谷歌搜索,揭示人性最黑暗的5个秘密

《卫报》网站发布文章指出&#xff0c;我们能够从我们在网上问的问题获得对自己更多的了解呢。美国数据科学家塞斯斯蒂芬斯-大卫多维茨&#xff08;Seth Stephens-Davidowitz&#xff09;通过分析谷歌的匿名搜索数据&#xff0c;揭示了我们最黑暗的一些秘密&#xff0c;揭露了我…

通过Dapr实现一个简单的基于.net的微服务电商系统(七)——一步一步教你如何撸Dapr之服务限流...

在一般的互联网应用中限流是一个比较常见的场景&#xff0c;也有很多常见的方式可以实现对应用的限流比如通过令牌桶通过滑动窗口等等方式都可以实现&#xff0c;也可以在整个请求流程中进行限流比如客户端限流就是在客户端通过随机数直接返回成功失败来决定是否发起请求。也可…

(转)完美画质 3D游戏反锯齿技术浅析 .

完美的画面已经离我们不再遥远——反锯齿技术浅析 不管现今的游戏画面有多完美&#xff0c;人物和环境有多真实&#xff0c;但游戏画面的构成的主要方式仍然没有得到改善&#xff1a;一帧画面由成千上万像素构成。这意味着物体多边形的轮廓最终是锯齿状的图形。所以画面质量不可…

业余时间学数据分析,如何快速上手

广泛被应用的数据分析谷歌的数据分析可以预测一个地区即将爆发的流感&#xff0c;从而进行针对性的预防&#xff1b;淘宝可以根据你浏览和消费的数据进行分析&#xff0c;为你精准推荐商品&#xff1b;口碑极好的网易云音乐&#xff0c;通过其相似性算法&#xff0c;为不同的人…

java连接mysql数据库连接池_java使用原生MySQL实现数据的增删改查以及数据库连接池技术...

一、工具类及配置文件准备工作1.1 引入jar包使用原生MySQL&#xff0c;只需要用到MySQL连接的jar包&#xff0c;maven引用方式如下&#xff1a;mysqlmysql-connector-java5.1.481.2 jdbc.properties文件配置在resources文件夹根目录&#xff0c;新增jdbc.properties配置文件&am…

64位Visual Studio 2022,微软在下一盘大棋!

有没有跟我一样奇怪过&#xff0c;都2021年了&#xff0c;用的还是VS2019&#xff1f;原来微软是憋大招去了&#xff0c;4月18号Amanda的一篇博文宣布了一则重磅消息——Visual Studio 2022 首个预览版将于今年夏季发布 &#xff0c;并且终于成为万众期待的 64 位版&#xff01…

如何添加自定义icon

(1)一般命令行程序编译后是一个方框图标。 我们可以自定义&#xff1a; Project -> Add to project -> New... 选择Resource Script&#xff0c;新建一个资源脚本&#xff0c;这样左面就多了一个资源视图 然后Project -> Add to project -> File&#xff0c;加进…

mysql 5.7.17 源码安装_mysql5.7.17源码安装

创建用户和目录groupadd mysqluseradd -r -g mysql mysqlmkdir -p /data/mysql/standby/datamkdir -p /data/mysql/standby/tmpmkdir -p /data/mysql/standby/elogmkdir -p /data/mysql/standby/blogchown -R mysql:root /data/mysql配置yum源cd /etc/yum.repos.d/rm -rf *vi c…

跟几个程序员聊了聊他们的每月薪资收入

阅读本文大概需要6分钟。我一直有一个技术小群&#xff0c;这个群最初是在360当新人入职导师带的几个人&#xff0c;和大家挺聊得来就建了一个群&#xff0c;没想到居然存在了6年之久。压力大的时候就在群里和大家相互调侃或者拉拉家常&#xff0c;偶尔谁跳槽了也会喷喷前东家&…

开通博客

今天注册了博客园并且开通了博客&#xff01; 我想用博客来记录并分享我学习编程过程和知识。 希望大家予以支持和帮助。转载于:https://www.cnblogs.com/crislina/archive/2012/01/28/2330629.html

【重磅】MIT发布2018年“全球十大突破性技术”

“有些技术已经应用多年&#xff0c;有些则是意外之喜。无论如何&#xff0c;以下是我们认为将在未来的几年对我们的工作和生活产生巨大影响的技术突破。”北京时间2018年2月21日&#xff0c;《麻省理工科技评论》揭晓了2018年“全球十大突破性技术”&#xff0c;这份全球新兴科…

mysql必须的组件_mysql innodb的重要组件

innodb包涵如下几个组件一、innodb_buffer_pool&#xff1a;1  它主要用来缓存数据与索引(准确的讲由于innodb中的表是由聚集索引组织的&#xff0c;所以数据只不是过主键这个索引的叶子结点)。二、change buffer:1  如果更新语句要更新二级索引的记录&#xff0c;但是记录…

[Stardust]星尘配置中心

在分布式系统开发中&#xff0c;配置中心必不可少。在中通几年时间里&#xff0c;为了配合大数据计算平台&#xff0c;统一管理数百个微小应用&#xff0c;设计了一套轻量级配置中心。星尘配置中心在其理念基础上改进&#xff0c;针对中小团队而全新设计&#xff01;源码&#…

oracle中v$database视图详解

SQL> desc v$database 名称 是否为空? 类型 ----------------- -------- ------------ DBID NUMBER NAME VARCHAR2(9) CREATED DATE RESETLOGS_CHANGE# NUMBER RESETLOGS_T…

大数据可视化设计到底是啥,该怎么用

大数据可视化是个热门话题&#xff0c;在信息安全领域&#xff0c;也由于很多企业希望将大数据转化为信息可视化呈现的各种形式&#xff0c;以便获得更深的洞察力、更好的决策力以及更强的自动化处理能力&#xff0c;数据可视化已经成为网络安全技术的一个重要趋势。文章目录一…

九度 1376 最近零子序列

http://ac.jobdu.com/problem.php?id1376 N^2的算法超时 优化算法想了好久没想出来&#xff0c;就当是学习一下STL的set了吧 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <math.h> 4 #include <set> 5 #include <iostream> 6 #defi…