Skip to content

Commit

Permalink
Add CA1873: Avoid potentially expensive logging (#7290)
Browse files Browse the repository at this point in the history
* Add CA1873: Avoid potentially expensive logging

This analyzer detects calls to 'ILogger.Log', extension methods in
'Microsoft.Extensions.Logging.LoggerExtensions' and methods decorated
with '[LoggerMessage]'.
It then checks if they evaluate expensive arguments without checking if
logging is enabled with 'ILogger.IsEnabled'.

* Use loop for IsGuardedByIsEnabled instead of recursion

* Rename TryGetLogLevel to IsLogInvocation

* Rework how expensive argument evaluation is detected

Previously, some specific operations were treated as non-expensive and
the rest were. This is not really future-proof as the language evolves,
and is generally more prone to false positives.

So this has now been changed to the opposite: Treat certain operations
as expensive, and the rest are not expensive by default and do not
trigger a diagnostic.

* Fix same instance detection when using conditional access

* Run msbuild pack

* Reorder tests

* Fix constant interpolation string detection

* Cleanup and add missing tests

* Add StringSyntax attribute to highlight test source

* Allow nameof, consts and literals in interpolated strings

* Use SymbolEqualityComparer to check same instance symbol

* Check all parent blocks for IsEnabled guard
  • Loading branch information
mpidash authored Jan 31, 2025
1 parent 3746107 commit 8fe7aeb
Show file tree
Hide file tree
Showing 22 changed files with 6,293 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
CA1873 | Performance | Info | AvoidPotentiallyExpensiveCallWhenLoggingAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1873)
CA2023 | Reliability | Warning | LoggerMessageDefineAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2023)
CA2024 | Reliability | Warning | DoNotUseEndOfStreamInAsyncMethods, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2024)
Original file line number Diff line number Diff line change
Expand Up @@ -2132,6 +2132,15 @@ Widening and user defined conversions are not supported with generic types.</val
<data name="UseStringMethodCharOverloadWithSingleCharactersTitle" xml:space="preserve">
<value>Use char overload</value>
</data>
<data name="AvoidPotentiallyExpensiveCallWhenLoggingDescription" xml:space="preserve">
<value>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</value>
</data>
<data name="AvoidPotentiallyExpensiveCallWhenLoggingMessage" xml:space="preserve">
<value>Evaluation of this argument may be expensive and unnecessary if logging is disabled</value>
</data>
<data name="AvoidPotentiallyExpensiveCallWhenLoggingTitle" xml:space="preserve">
<value>Avoid potentially expensive logging</value>
</data>
<data name="AvoidSingleUseOfLocalJsonSerializerOptionsMessage" xml:space="preserve">
<value>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead.</value>
</data>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">Vyhněte se konstantním polím jako argumentům</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">Vyhněte se vytvoření nové instance JsonSerializerOptions pro každou operaci serializace. Místo toho ukládejte instance do mezipaměti a znovu je používejte. Instance JsonSerializerOptions pro jedno použití můžou výrazně snížit výkon vaší aplikace.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">Konstantenmatrizen als Argumente vermeiden</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">Erstellen Sie für Serialisierungsvorgänge nicht jeweils eine neue JsonSerializerOptions-Instanz. Speichern Sie stattdessen Instanzen zwischen, und verwenden Sie sie wieder. Die einmalige Verwendung von JsonSerializerOptions-Instanzen kann die Leistung Ihrer Anwendung erheblich beeinträchtigen.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">Evitar matrices constantes como argumentos</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">Evite crear una nueva instancia de "JsonSerializerOptions" para cada operación de serialización. En su lugar, almacene en caché y reutilice instancias. Las instancias "JsonSerializerOptions" de uso único pueden degradar considerablemente el rendimiento de la aplicación.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">Éviter les tableaux constants en tant qu’arguments</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">Évitez de créer une instance « JsonSerializerOptions » pour chaque opération de sérialisation. Mettez en cache et réutilisez les instances à la place. Les instances « JsonSerializerOptions » à usage unique peuvent considérablement dégrader les performances de votre application.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">Evitare matrici costanti come argomenti</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">Evitare di creare una nuova istanza di 'JsonSerializerOptions' per ogni operazione di serializzazione. Memorizzare nella cache le istanze e riutilizzarle. Le istanze monouso di 'JsonSerializerOptions' possono ridurre notevolmente le prestazioni dell'applicazione.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">引数として定数配列を使用しない</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">シリアル化操作ごとに新しい 'JsonSerializerOptions' インスタンスを作成しないでください。代わりにインスタンスをキャッシュして再利用します。'JsonSerializerOptions' インスタンスの単独使用では、アプリケーションのパフォーマンスが大幅に低下する可能性があります。</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">상수 배열을 인수로 사용하지 않습니다.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">모든 직렬화 작업에 대해 새 'JsonSerializerOptions' 인스턴스를 만들지 마세요. 대신 인스턴스를 캐시하고 다시 사용합니다. 단일 사용 'JsonSerializerOptions' 인스턴스는 애플리케이션의 성능을 크게 저하시킬 수 있습니다.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">Unikaj tablic stałych jako argumentów</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">Unikaj tworzenia nowego wystąpienia „JsonSerializerOptions” dla każdej operacji serializacji. Zamiast tego buforuj i ponownie wykorzystuj wystąpienia. Jednorazowe użycie wystąpienia „JsonSerializerOptions” może znacznie obniżyć wydajność aplikacji.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">Evite matrizes constantes como argumentos</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">Evite criar uma nova instância 'JsonSerializerOptions' para cada operação de serialização. Em vez disso, armazene em cache e reutilize instâncias. Instâncias 'JsonSerializerOptions' de uso único podem degradar substancialmente o desempenho de seu aplicativo.</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
<target state="translated">Избегайте использования константных массивов в качестве аргументов</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingDescription">
<source>In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</source>
<target state="new">In many situations, logging is disabled or set to a log level that results in an unnecessary evaluation for this argument.</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingMessage">
<source>Evaluation of this argument may be expensive and unnecessary if logging is disabled</source>
<target state="new">Evaluation of this argument may be expensive and unnecessary if logging is disabled</target>
<note />
</trans-unit>
<trans-unit id="AvoidPotentiallyExpensiveCallWhenLoggingTitle">
<source>Avoid potentially expensive logging</source>
<target state="new">Avoid potentially expensive logging</target>
<note />
</trans-unit>
<trans-unit id="AvoidSingleUseOfLocalJsonSerializerOptionsDescription">
<source>Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application.</source>
<target state="translated">Избегайте создания нового экземпляра "JsonSerializerOptions" для каждой операции сериализации. Выполняйте кэширование и повторно используйте экземпляры. Однократное использование экземпляров "JsonSerializerOptions" может значительно снизить производительность приложения.</target>
Expand Down
Loading

0 comments on commit 8fe7aeb

Please sign in to comment.