C#idiomatic C#
ca1873fundamentals/code-analysis/quality-rules

Code analysis

CA1873: Avoid potentially expensive logging

Learn about code analysis rule CA1873: Avoid potentially expensive logging

CA1873 Performance enabled by default in .NET 10: As suggestion
Fix is breaking or non-breaking Non-breakingApplicable languages C# and Visual Basic

Cause

In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for logging arguments.

Rule description

When logging methods are called, their arguments are evaluated regardless of whether the logging level is enabled. This can result in expensive operations being executed even when the log message won't be written. For better performance, guard expensive logging calls with a check to Microsoft.Extensions.Logging.ILogger.IsEnabled or use source-generated logging with the Microsoft.Extensions.Logging.LoggerMessageAttribute attribute.

How to fix violations

To fix a violation of this rule, use one of the following approaches:

Example

The following code snippet shows violations of CA1873:

sample · csharpdocs/fundamentals/code-analysis/quality-rules/snippets/ca1873/csharp/CA1873Example/Violation.csViolationExample

csharp
using Microsoft.Extensions.Logging;

// <ViolationExample>
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 });
    }
}
// </ViolationExample>

sample · vbdocs/fundamentals/code-analysis/quality-rules/snippets/ca1873/vb/CA1873Example/Violation.vbViolationExample

vb
Imports Microsoft.Extensions.Logging

' <ViolationExample>
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
' </ViolationExample>

The following code snippet fixes the violations by using source-generated logging:

sample · csharpdocs/fundamentals/code-analysis/quality-rules/snippets/ca1873/csharp/CA1873Example/Fix.csFixExample

csharp
using Microsoft.Extensions.Logging;

// <FixExample>
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);
}
// </FixExample>

sample · vbdocs/fundamentals/code-analysis/quality-rules/snippets/ca1873/vb/CA1873Example/Fix.vbFixExample

vb
Imports Microsoft.Extensions.Logging

' <FixExample>
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
' </FixExample>

When to suppress warnings

It's safe to suppress a warning from this rule if performance isn't a concern or if the logging arguments don't involve expensive operations.

Suppress a warning

If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.

csharp
#pragma warning disable CA1873
// The code that's violating the rule is on this line.
#pragma warning restore CA1873

To disable the rule for a file, folder, or project, set its severity to none in the configuration file.

ini
[*.{cs,vb}]
dotnet_diagnostic.CA1873.severity = none

For more information, see How to suppress code analysis warnings.

See also