| 资产 | 价值 |
|---|---|
| 规则 ID | CA1873 |
| 标题 | 避免可能成本高昂的日志记录 |
| 类别 | 性能 |
| 修复是中断修复还是非中断修复 | Non-breaking |
| 在 .NET 10 中默认启用 | 作为建议 |
原因
在许多情况下,日志记录被禁用或设置为日志级别,这会导致对日志记录参数进行不必要的评估。
规则说明
调用日志记录方法时,无论是否启用日志记录级别,都会评估其参数。 这可能会导致执行成本高昂的作,即使不会写入日志消息也是如此。 为了获得更好的性能,请使用检查来IsEnabled保护昂贵的日志记录调用,或使用属性的源生成的日志记录LoggerMessageAttribute。
如何修复违规行为
若要修复此规则的冲突,请使用以下方法之一:
- 使用检查来 IsEnabled保护日志记录调用。
- 将源生成的日志记录与属性一 LoggerMessageAttribute 起使用。
- 确保除非必要,否则不会在日志记录参数中执行昂贵的作。
Example
以下代码片段显示了 CA1873 的冲突:
class ViolationExample
{
private readonly ILogger _logger;
public ViolationExample(ILogger<ViolationExample> logger)
{
_logger = logger;
}
public void ProcessData(int[] data)
{
// Violation: expensive operation in logging argument.
_logger.LogDebug($"Processing {string.Join(", ", data)} items");
// Violation: object creation in logging argument.
_logger.LogTrace("Data: {Data}", new { Count = data.Length, Items = data });
}
}
Class ViolationExample
Private ReadOnly _logger As ILogger
Public Sub New(logger As ILogger(Of ViolationExample))
_logger = logger
End Sub
Public Sub ProcessData(data As Integer())
' Violation: expensive operation in logging argument.
_logger.LogDebug($"Processing {String.Join(", ", data)} items")
' Violation: object creation in logging argument.
_logger.LogTrace("Data: {Data}", New With {.Count = data.Length, .Items = data})
End Sub
End Class
以下代码片段使用源生成的日志记录修复了冲突:
partial class FixExample
{
private readonly ILogger _logger;
public FixExample(ILogger<FixExample> logger)
{
_logger = logger;
}
public void ProcessData(int[] data)
{
// Fixed: use source-generated logging.
// The data array is passed directly; no expensive operation executed unless log level is enabled.
LogProcessingData(data);
// Fixed: use source-generated logging.
LogTraceData(data.Length, data);
}
[LoggerMessage(Level = LogLevel.Debug, Message = "Processing {Data} items")]
private partial void LogProcessingData(int[] data);
[LoggerMessage(Level = LogLevel.Trace, Message = "Data: Count={Count}, Items={Items}")]
private partial void LogTraceData(int count, int[] items);
}
Partial Class FixExample
Private ReadOnly _logger As ILogger
Public Sub New(logger As ILogger(Of FixExample))
_logger = logger
End Sub
Public Sub ProcessData(data As Integer())
' Fixed: use source-generated logging.
' The data array is passed directly; no expensive operation executed unless log level is enabled.
LogProcessingData(data)
' Fixed: use source-generated logging.
LogTraceData(data.Length, data)
End Sub
<LoggerMessage(Level:=LogLevel.Debug, Message:="Processing {Data} items")>
Private Partial Sub LogProcessingData(data As Integer())
End Sub
<LoggerMessage(Level:=LogLevel.Trace, Message:="Data: Count={Count}, Items={Items}")>
Private Partial Sub LogTraceData(count As Integer, items As Integer())
End Sub
End Class
何时禁止显示警告
如果性能不关心或日志记录参数不涉及昂贵的作,则禁止显示此规则的警告是安全的。
禁止显示警告
如果只想抑制单个冲突,请将预处理器指令添加到源文件以禁用该规则,然后重新启用该规则。
#pragma warning disable CA1873
// The code that's violating the rule is on this line.
#pragma warning restore CA1873
若要禁用文件、文件夹或项目的规则,请在none中将其严重性设置为。
[*.{cs,vb}]
dotnet_diagnostic.CA1873.severity = none
有关详细信息,请参阅 如何禁止显示代码分析警告。