次の方法で共有


CA1873: コストの高いログ記録を回避する

プロパティ 価値
ルール識別子 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

詳細については、「 コード分析の警告を抑制する方法」を参照してください。

こちらも参照ください