我一直在关注Logging in ASP.NET Core哪个工作正常。
我对这条线有疑问
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);
我想知道为什么他们不使用 $ - string interpolation ?
_logger.LogWarning(LoggingEvents.GetItemNotFound, $"GetById({ID}) NOT FOUND");
为什么 LogWarning扩展有一个 params object[] args
参数?
当您可以将所有内容都发送到字符串消息中时,有什么意义呢?
我认为这是有原因的,但我无法在任何地方找到解释。我想知道我应该使用哪种方法才能正确登录 .net 核心。
最佳答案
我怀疑这个问题可以改写为:
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 的好处微乎其微,但会造成很多困惑。
我刚发现 Serilog's author explains why this isn't such a good idea尽管语义日志库看起来很适合这种情况
语义日志记录
可以说 FormattableString
将是 Serilog 等语义日志库的一个很好的补充。在这种情况下,内插字符串确实丢失了重要信息。
电话
Log.Information("Logged in {UserId}", loggedInUserId);
不会只记录基于模板的字符串,它会保留参数的名称和值并将它们提供给过滤器和目标。用 :
获得相同的结果不是很好吗?Log.Information($"Logged in {loggedInUserId}");
Serilog's author doesn't think so并解释说:
- 好的变量名不一定是好的属性名
- 漏洞并不总是有明显的名称,例如
Log.Information($"Enabling categories {new[]{1, 2, 3}}");
并得出结论
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.
Interpolation is nice when it keeps code DRY, cutting out the redundant clutter of {0} and {1} and preventing parameter mismatches.
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 注入(inject)和转换问题。
这个电话:
string city = "London";
var londonCustomers = context.Customers
.FromSql($"SELECT * FROM Customers WHERE City = {city}");
调用 FromSql(FormattableString)
并将创建一个参数化查询:
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
这是无效的。即使您确实知道风险,落入这个陷阱也太常见了。
当您已经有预定义的查询或消息时,它根本无济于事。这种用法在日志记录中更为常见,您(应该)使用在众所周知的位置定义的特定消息模板,而不是在每个日志位置散布看起来相似的字符串。
有人可能会争辩说 this addition made EF Core 2.0 somewhat safer因为人们已经开始在 EF Core 1.0 中使用字符串插值,导致查询无效。添加 FormattableString
重载后,EF Core 团队能够缓解那种场景,同时更容易意外导致不同的问题。
此时日志设计者决定避免这种混淆。记录原始字符串不会造成如此灾难性的后果。
关于c# - 为什么 Logging 不使用字符串插值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52200484/