为什么 Logging 不使用字符串插值 [英] Why Logging doesn't use string interpolation

查看:27
本文介绍了为什么 Logging 不使用字符串插值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在关注 登录 ASP.NET Core 运行良好.

I have been following Logging in ASP.NET Core Which is working just fine.

我对这条线有疑问

_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);

我想知道他们为什么不使用 $ -字符串插值?

I am wondering why they are not using $ - string interpolation?

_logger.LogWarning(LoggingEvents.GetItemNotFound, $"GetById({ID}) NOT FOUND");

为什么 Warm 扩展有一个 params object[] args 参数?

Why would the LogWarning extension have a params object[] args paramater?

什么时候你可以只发送字符串消息中的所有内容.

Whats the point when you can just send everything in string message.

我认为这是有原因的,但我无法在任何地方找到解释.我想知道我应该使用哪种方法才能正确登录 .net 核心.

I assume there is a reason for this but i haven't been able to find an explanation anywhere. I am wondering which method i should be using in order to log properly in .net core.

推荐答案

我怀疑这个问题可以改写为:

I suspect the question can be rephrased to :

为什么他们不提供接受 FormattableString 使用字符串插值语法传递消息模板和参数,就像 EF Core 对参数化查询所做的那样?

Why didn't they provide overloads that accept a FormattableString to pass message templates and parameters using string interpolation syntax, like EF Core does for parameterized queries?

我会说他们做对了.此时使用 FormattableString 带来的好处微乎其微,但会造成很多的混乱.

I'd say they got it right. At this point in time using FormattableString offers minimal benefits but creates a lot of confusion.

我刚刚发现 Serilog 的作者解释了为什么会这样'这是一个好主意即使语义日志库看起来很适合这种情况

I just found that Serilog's author explains why this isn't such a good idea even though a semantic logging library looks like a natural fit for this scenario

语义记录

有人可能会争辩说,FormattableString 将是对 Serilog 等语义日志库的一个很好的补充.在这种情况下,内插字符串确实会丢失重要信息.

One can argue that FormattableString would be a great addition to semantic logging libraries like Serilog. In this case an interpolated string does lose important information.

电话

Log.Information("Logged in {UserId}", loggedInUserId);

不会仅仅基于模板记录一个字符串,它会保留参数的名称和值并将它们提供给过滤器和目标.用 :

Won't just log a string based on the template, it will keep the names and values of the parameters and provide them to filters and targets. Wouldn't it be great to get the same result with :

Log.Information($"Logged in {loggedInUserId}");

Serilog 的作者不这么认为并解释说:

  1. 好的变量名不一定是好的属性名
  2. 孔并不总是有明显的名称,例如 Log.Information($"Enabling Categories {new[]{1, 2, 3}}");

并得出结论

字符串插值是一项很棒的功能,我在 C# 中期待已久.为 Serilog 提供直接支持的想法非常有趣,值得探索,但我越来越相信这是不必要的.

String interpolation is a great feature, one I’ve looked forward to in C# for a long time. The idea of providing direct support for Serilog is a very interesting one and worth exploring, but I’m increasingly convinced it’s unnecessary.

插值是很好的,它可以保持代码 DRY,消除 {0} 和 {1} 的冗余混乱并防止参数不匹配.

Interpolation is nice when it keeps code DRY, cutting out the redundant clutter of {0} and {1} and preventing parameter mismatches.

就 Serilog 而言,我认为将 {UserId} 之类的属性名称视为多余是不正确的;在实施良好的日志记录策略中,它们是值得他们自己考虑的图片中非常重要的部分.您不会让变量名决定关系数据库中的表名和列名——这与此处考虑的权衡完全相同.

In the case of Serilog, I think it’s incorrect to consider the property names like {UserId} as redundant; in a well-implemented logging strategy they’re an incredibly important part of the picture that deserve their own consideration. You wouldn’t let variable names determine the table and column names in a relational database – it’s exactly the same trade-off being considered here.

原文说明

这实际上是 EF Core 最具争议的特性之一,并且很容易导致人们希望通过使用参数避免的 SQL 注入和转换问题.

That's one of the most controversial features of EF Core actually, and can easily result in the very SQL injection and conversion problems one wants to avoid by using parameters.

这个电话:

string city = "London";
var londonCustomers = context.Customers
    .FromSql($"SELECT * FROM Customers WHERE City = {city}");

调用 FromSql(FormattableString) 并将创建一个参数化查询:

calls FromSql(FormattableString) and will create a parameterized query :

SELECT * FROM Customers WHERE City = @p0

并通过 London 作为参数值.

And pass London as a parameter value.

另一方面:

string city = "London";
var query=$"SELECT * FROM Customers WHERE City = {city}";
var londonCustomers = context.Customers.FromSql(query);

调用 FromSql(string) 并生成:

SELECT * FROM Customers WHERE City = London

这是无效的.即使您确实知道风险,也很容易落入这个陷阱.

Which is invalid. It's far too common to fall in this trap even when you do know about the risk.

当您已经有预定义的查询或消息时,它根本没有帮助.这种用法在日志记录中更为常见,您(应该)使用在众所周知的位置定义的特定消息模板,而不是在每个日志位置散布看起来相似的字符串.

It doesn't help at all when you already have predefined queries or messages. This usage is far more common in logging, where you (should) use specific message templates defined in well known locations, instead of sprinkling similar looking strings in every log location.

有人可能会争辩说这一添加使 EF Core 2.0 更加安全因为人们已经开始在 EF Core 1.0 中使用字符串插值,从而导致无效查询.添加 FormattableString 重载后,EF Core 团队能够缓解这种情况,同时更容易意外地导致不同的问题.

One could argue that this addition made EF Core 2.0 somewhat safer because people had already started using string interpolation in EF Core 1.0, resulting in invalid queries. Adding the FormattableString overload the EF Core team was able to mitigate that scenario while making it easier to accidentally cause a different problem.

此时日志设计者决定避免这种混淆.记录原始字符串不会产生如此灾难性的后果.

At this point in time the logging designers decided to avoid this confusion. Logging a raw string doesn't have such catastrophic consequences.

这篇关于为什么 Logging 不使用字符串插值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆