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

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

问题描述

我一直在关注在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");

为什么 LogWarning扩展有一个 params对象[] 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($启用类别{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 作为参数值.

另一方面:

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.

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

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