CA1873:避免可能成本高昂的日志记录

资产 价值
规则 ID CA1873
标题 避免可能成本高昂的日志记录
类别 性能
修复是中断修复还是非中断修复 Non-breaking
在 .NET 10 中默认启用 作为建议

原因

在许多情况下,日志记录被禁用或设置为日志级别,这会导致对日志记录参数进行不必要的评估。

规则说明

调用日志记录方法时,无论是否启用日志记录级别,都会评估其参数。 这可能会导致执行成本高昂的作,即使不会写入日志消息也是如此。 为了获得更好的性能,请使用检查 IsEnabled 或使用 LoggerMessage 模式保护昂贵的日志记录调用。

如何修复违规行为

若要修复此规则的冲突,请使用以下方法之一:

  • 使用检查来 IsEnabled保护日志记录调用。
  • LoggerMessage 模式与 LoggerMessageAttribute.
  • 确保除非必要,否则不会在日志记录参数中执行昂贵的作。

Example

以下代码片段显示了 CA1873 的冲突:

using Microsoft.Extensions.Logging;

class Example
{
    private readonly ILogger _logger;

    public Example(ILogger<Example> 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 });
    }
}
Imports Microsoft.Extensions.Logging

Class Example
    Private ReadOnly _logger As ILogger

    Public Sub New(logger As ILogger(Of Example))
        _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

以下代码片段修复了冲突:

using Microsoft.Extensions.Logging;

class Example
{
    private readonly ILogger _logger;

    public Example(ILogger<Example> logger)
    {
        _logger = logger;
    }

    public void ProcessData(int[] data)
    {
        // Fixed: guard with IsEnabled check.
        if (_logger.IsEnabled(LogLevel.Debug))
        {
            _logger.LogDebug($"Processing {string.Join(", ", data)} items");
        }

        // Fixed: guard with IsEnabled check.
        if (_logger.IsEnabled(LogLevel.Trace))
        {
            _logger.LogTrace("Data: {Data}", new { Count = data.Length, Items = data });
        }
    }
}
Imports Microsoft.Extensions.Logging

Class Example
    Private ReadOnly _logger As ILogger

    Public Sub New(logger As ILogger(Of Example))
        _logger = logger
    End Sub

    Public Sub ProcessData(data As Integer())
        ' Fixed: guard with IsEnabled check.
        If _logger.IsEnabled(LogLevel.Debug) Then
            _logger.LogDebug($"Processing {String.Join(", ", data)} items")
        End If

        ' Fixed: guard with IsEnabled check.
        If _logger.IsEnabled(LogLevel.Trace) Then
            _logger.LogTrace("Data: {Data}", New With {.Count = data.Length, .Items = data})
        End If
    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

有关详细信息,请参阅 如何禁止显示代码分析警告

另请参阅