[Analyzers] Add diagnostic rule and code fix for ToString() on numeric types in log calls#8399
Conversation
ToString() on numeric types in log calls
4f38f6c to
9705249
Compare
There was a problem hiding this comment.
Pull request overview
Adds a new Roslyn allocation analyzer (DDALLOC001) + code fix to detect and remove unnecessary .ToString() calls on numeric values passed into IDatadogLogger methods, and updates a few call sites/tests accordingly.
Changes:
- Introduce
NumericToStringInLogAnalyzer+RemoveNumericToStringCodeFixProviderto avoid string allocations in numeric log arguments. - Add analyzer + code fix test coverage (new helper + new test suites).
- Update a few
Datadog.Tracelogging call sites to use generic overloads instead of.ToString().
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tracer/src/Datadog.Trace.Tools.Analyzers/AllocationAnalyzer/NumericToStringInLogAnalyzer.cs | New analyzer that reports .ToString() on numeric receiver expressions in logger calls |
| tracer/src/Datadog.Trace.Tools.Analyzers/AllocationAnalyzer/Diagnostics.cs | New diagnostic descriptor/constants for DDALLOC001 |
| tracer/src/Datadog.Trace.Tools.Analyzers.CodeFixes/AllocationAnalyzer/RemoveNumericToStringCodeFixProvider.cs | New code fix that removes .ToString() and adjusts/adds generic type arguments |
| tracer/src/Datadog.Trace.Tools.Analyzers.CodeFixes/Datadog.Trace.Tools.Analyzers.CodeFixes.csproj | Links allocation Diagnostics into code-fixes project |
| tracer/test/Datadog.Trace.Tools.Analyzers.Tests/AllocationAnalyzer/NumericToStringInLogAnalyzerTests.cs | New analyzer tests |
| tracer/test/Datadog.Trace.Tools.Analyzers.Tests/AllocationAnalyzer/RemoveNumericToStringCodeFixTests.cs | New code-fix tests |
| tracer/test/Datadog.Trace.Tools.Analyzers.Tests/AllocationAnalyzer/Helpers.cs | Test helper with logger stub + log method list |
| tracer/src/Datadog.Trace/Iast/Analyzers/HardcodedSecretsAnalyzer.cs | Replace numeric .ToString() in log arg with generic log overload |
| tracer/src/Datadog.Trace/Debugger/ExceptionAutoInstrumentation/ExceptionCaseInstrumentationManager.cs | Replace numeric .ToString() in log arg with generic log overload |
| tracer/src/Datadog.Trace/ContinuousProfiler/ContextTracker.cs | Replace numeric .ToString() in log args with generic log overload(s) |
| tracer/src/Datadog.Trace/.editorconfig | Adds configuration line for DDALLOC001 severity |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
tracer/src/Datadog.Trace.Tools.Analyzers/AllocationAnalyzer/NumericToStringInLogAnalyzer.cs
Outdated
Show resolved
Hide resolved
...g.Trace.Tools.Analyzers.CodeFixes/AllocationAnalyzer/RemoveNumericToStringCodeFixProvider.cs
Outdated
Show resolved
Hide resolved
ToString() on numeric types in log callsThere was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 97052492e2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
.../Datadog.Trace.Tools.Analyzers.CodeFixes/LogAnalyzer/RemoveNumericToStringCodeFixProvider.cs
Show resolved
Hide resolved
ToString() on numeric types in log calls
178b1d3 to
82aa121
Compare
ToString() on numeric types in log callsToString() on numeric types in log calls
andrewlock
left a comment
There was a problem hiding this comment.
I like this as an idea, but I think instead of creating new analyzers, we should probably extend the existing LogAnalyzer instead as that already does a bunch of this work 🙂
| return document.WithSyntaxRoot(root); | ||
| } | ||
|
|
||
| // Check if the log call already has explicit generic type arguments |
There was a problem hiding this comment.
Gah, this is much harder than I would have liked 😂 I'm kind of surprised this whole analyzer doesn't already exist tbh, given there are similar analyzers for both Serilog and ILogger 🤔 Did you look for existing examples first, or is this entirely new?
There was a problem hiding this comment.
This is entirely new, I did zero research. It is based entirely on the few cases that Claude found in the code based (also fixed in this PR) 😅
There was a problem hiding this comment.
this is much harder than I would have liked
Not sure if that's what you meant, but I moved the new diagnostics into LogAnalyzer, as per your other comments.
tracer/src/Datadog.Trace.Tools.Analyzers/AllocationAnalyzer/Diagnostics.cs
Outdated
Show resolved
Hide resolved
tracer/src/Datadog.Trace.Tools.Analyzers/AllocationAnalyzer/NumericToStringInLogAnalyzer.cs
Outdated
Show resolved
Hide resolved
| for (var i = messageTemplateIndex + 1; i < arguments.Count; i++) | ||
| { | ||
| var argExpression = arguments[i].Expression; | ||
| CheckForNumericToString(context, argExpression); |
There was a problem hiding this comment.
Why just numeric? Isn't calling ToString() basically always going to be not wanted, regardless of the type? 🤔
There was a problem hiding this comment.
This analyzer was based only on observed behavior in the code base. It looks like int.ToString() is being used in a few places to get around an issue where this call is ambiguous:
int value;
Log.Warning(e, "message {value}", value);the code was doing this in some places:
Log.Warning(e, "message {value}", value.ToString());instead of this, which resolves the ambiguous call and is more correct:
Log.Warning<int>(e, "message {value}", value);The issue is the optional sourceLine parameter in signatures like this one:
void Error(string messageTemplate, [CallerLineNumber] int sourceLine = 0, [CallerFilePath] string sourceFile = "");I don't think this would happen with anything other than int.
tracer/test/Datadog.Trace.Tools.Analyzers.Tests/AllocationAnalyzer/Helpers.cs
Outdated
Show resolved
Hide resolved
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
Add code fix guidance, diagnostic message tips, performance tips, and remove duplicated Diagnostics.cs linking instruction. 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
RS2008 is already suppressed via <NoWarn> in the .csproj. 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
The .csproj already suppresses RS2008; no need to mention it in the checklist or code templates. 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
11d35ce to
0b5278a
Compare
Adds a Roslyn analyzer and code fix that flags unnecessary .ToString() calls on numeric types passed to IDatadogLogger methods. The generic log overloads handle formatting without allocating a string, so the .ToString() is wasteful. The code fix removes the call and updates explicit generic type arguments when present. 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
When explicit generic type arguments already exist, preserve the original syntax nodes and only replace the one being fixed. This avoids MinimallyQualifiedFormat potentially producing uncompilable type names. 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
… test 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
82aa121 to
f6c0c20
Compare
Move the standalone AllocationAnalyzer (DDALLOC001) into the existing LogAnalyzer to avoid duplicate IDatadogLogger resolution work per invocation. Consolidate test helpers and reuse the LogAnalyzer stub. 🤖 Co-Authored-By: Claude Code <noreply@anthropic.com>
ToString() on numeric types in log callsToString() on numeric types in log calls
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 668c849bf9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
.../Datadog.Trace.Tools.Analyzers.CodeFixes/LogAnalyzer/RemoveNumericToStringCodeFixProvider.cs
Show resolved
Hide resolved
d44e281 to
0955dd9
Compare
Summary of changes
Add a new diagnostic rule (
DDLOG010) and code fix to the existingLogAnalyzerthat detects unnecessary.ToString()calls on numeric types passed as arguments toIDatadogLoggermethods.Reason for change
The generic log overloads (
Log.Debug<int>(...)) handle numeric formatting without allocating a string. Calling.ToString()on the numeric value before passing it to the log method causes an unnecessary heap allocation on every log call.Implementation details
DDLOG010): Added to the existingLogAnalyzerto avoid duplicateIDatadogLoggermethod resolution. Flags.ToString()calls on numeric types (int,long,double, etc.) when used as arguments to log methods (Debug,Information,Warning,Error,ErrorSkipTelemetry)RemoveNumericToStringCodeFixProvider): Removes the.ToString()call and updates explicit generic type arguments when presentLog.Debug<string>("attempt {Attempt}", (attempt + 1).ToString())→Log.Debug<int>("attempt {Attempt}", attempt + 1).editorconfigintracer/src/Datadog.Trace/object[]overloads (removing.ToString()there would cause boxing, not save it)ContextTracker.cs,ExceptionCaseInstrumentationManager.cs, andHardcodedSecretsAnalyzer.csTest coverage
.ToString()on various numeric types (int,long,double,float,byte,decimal, etc.).ToString(),.ToString(format)with arguments, enum.ToString(), non-log-method calls,object[]overloads, different logger typesLogAnalyzertest helpers to include[CallerLineNumber]/[CallerFilePath]attributes and missing higher-arity overloadsOther details
Stacked on #8421