优化 .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;有意思的是这位朋友说他&#…

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

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

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

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

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

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

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

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

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

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

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

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

[Stardust]星尘配置中心

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

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

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

WPF 如何实现颜色值拾取

WPF开发者QQ群&#xff1a; 340500857 前言如何进行颜色值拾取&#xff1f;这里采用的是调用WindowsAPI进行实现。吸取 沙漠尽头的狼 的建议多写一些文字进行描述。效果图如下&#xff1a;第一步 注册WindowsAPI 代码如下&#xff1a;[DllImport("user32.dll")]stati…

仿Google+相册的动画

在使用Google的时候&#xff0c;查看某一相册&#xff0c;会经常看到&#xff0c;如下图所示的动画效果。 鼠标移入、移出时均有动画效果&#xff0c;咋一看估计是使用了css3的transform属性来实现动画效果的。 在网上搜索“Google 相册 效果”的时候发现有人使用CSS3做了这样的…

看见到洞见之引子(二)机器学习算法

《看见到洞见》系列文章汇聚、分享的是绿盟科技创新中心对于数据分析在安全领域应用的技战术思考与经验&#xff0c;力求由浅入深层次递进&#xff0c;实战到方法论双线剖析。此文为系列文章之引子第二篇&#xff0c;深入浅出的对常用的数据分析和机器学习的算法进行介绍。在上…

一图看懂 ASP.NET Core 中的服务生命周期

翻译自 Waqas Anwar 2020年11月8日的文章 《ASP.NET Core Service Lifetimes (Infographic)》 [1]ASP.NET Core 支持依赖关系注入&#xff08;DI&#xff09;软件设计模式&#xff0c;该模式允许我们注册服务、控制如何实例化这些服务并将其注入到不同的组件中。一些服务可以在…

看见到洞见之引子(一)机器学习算法

《看见到洞见》系列文章汇聚、分享的是绿盟科技创新中心对于数据分析在安全领域应用的技战术思考与经验&#xff0c;力求由浅入深层次递进&#xff0c;实战到方法论双线剖析。此文为系列文章之引子第一篇&#xff0c;深入浅出的对常用的数据分析和机器学习的算法进行介绍。文章…

支持向量回归代码_RDKit:基于支持向量回归(SVR)预测logP

RDKit一个用于化学信息学的python库。使用支持向量回归(SVR)来预测logP。 分子的输入结构特征是摩根指纹&#xff0c;输出是logP。代码示例&#xff1a;#导入依赖库import numpy as npfrom rdkit import Chemfrom rdkit.Chem.Crippen import MolLogPfrom rdkit import Chem, Da…

移除 ZooKeeper 的 kafka 2.8 ,更快了

这段时间招聘季&#xff0c;后台收到不少关于 Kafka 的问题&#xff0c;确实 Kafka 近两年的行情&#xff0c;可谓是水涨船高了。根本原因是&#xff0c;是 Apache Kafka 作为一款开源的消息引擎系统。凭借高可靠、高吞吐、高可用、可伸缩等优越特性&#xff0c;在数据采集、传…

浅议SSH协议

什么是SSH&#xff1f; SSH 为 Secure Shell 的缩写&#xff0c;由 IETF 的网络工作小组&#xff08;Network Working Group&#xff09;所制定&#xff1b;SSH 为建立在应用层和传输层基础上的安全协议。SSH 是目前较可靠&#xff0c;专为远程登录会话和其他网络服务提供安全性…

机器学习 vs 深度学习到底有啥区别,为什么更多人选择机器学习

机器学习和深度学习有什么区别&#xff1f;让我们从本文中寻找答案。目标本文中&#xff0c;我们将深度学习与机器学习作比较。我们将逐一了解他们。我们还会讨论他们在各个方面的不同点。除了深度学习和机器学习的比较&#xff0c;我们还将研究它们未来的趋势。对比介绍深度学…