Skip to content

[Analyzers] Add diagnostic rule and code fix for ToString() on numeric types in log calls#8399

Open
lucaspimentel wants to merge 15 commits intolpimentel/analyzers-ai-docsfrom
lpimentel/allocation-analyzer-tostring-in-logs
Open

[Analyzers] Add diagnostic rule and code fix for ToString() on numeric types in log calls#8399
lucaspimentel wants to merge 15 commits intolpimentel/analyzers-ai-docsfrom
lpimentel/allocation-analyzer-tostring-in-logs

Conversation

@lucaspimentel
Copy link
Copy Markdown
Member

@lucaspimentel lucaspimentel commented Apr 1, 2026

Summary of changes

Add a new diagnostic rule (DDLOG010) and code fix to the existing LogAnalyzer that detects unnecessary .ToString() calls on numeric types passed as arguments to IDatadogLogger methods.

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

  • Diagnostic rule (DDLOG010): Added to the existing LogAnalyzer to avoid duplicate IDatadogLogger method resolution. Flags .ToString() calls on numeric types (int, long, double, etc.) when used as arguments to log methods (Debug, Information, Warning, Error, ErrorSkipTelemetry)
  • Code fix (RemoveNumericToStringCodeFixProvider): Removes the .ToString() call and updates explicit generic type arguments when present
    • Example: Log.Debug<string>("attempt {Attempt}", (attempt + 1).ToString())Log.Debug<int>("attempt {Attempt}", attempt + 1)
  • Enabled by default as error, also enforced via .editorconfig in tracer/src/Datadog.Trace/
  • Skips object[] overloads (removing .ToString() there would cause boxing, not save it)
  • Fixed existing violations in ContextTracker.cs, ExceptionCaseInstrumentationManager.cs, and HardcodedSecretsAnalyzer.cs

Test coverage

  • Detection of .ToString() on various numeric types (int, long, double, float, byte, decimal, etc.)
  • All log methods and overloads (with/without exception parameter, implicit/explicit generics, multi-argument)
  • Negative cases: non-numeric .ToString(), .ToString(format) with arguments, enum .ToString(), non-log-method calls, object[] overloads, different logger types
  • Code fix correctness for basic removal, explicit generic type argument updates, and expression arguments
  • Updated LogAnalyzer test helpers to include [CallerLineNumber]/[CallerFilePath] attributes and missing higher-arity overloads

Other details

Stacked on #8421

"I tried to call .ToString() on my code review skills, but the compiler said it was an unnecessary allocation of compliments." — Claude 🤖

@lucaspimentel lucaspimentel changed the title [Analyzers] Add DDALLOC001: detect ToString() on numeric types in log calls [Analyzers] Add analyzer to detect ToString() on numeric types in log calls Apr 1, 2026
@lucaspimentel lucaspimentel added area:builds project files, build scripts, pipelines, versioning, releases, packages AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos labels Apr 2, 2026
@lucaspimentel lucaspimentel changed the base branch from master to lpimentel/analyzers-ai-docs April 7, 2026 19:48
@lucaspimentel lucaspimentel force-pushed the lpimentel/allocation-analyzer-tostring-in-logs branch 2 times, most recently from 4f38f6c to 9705249 Compare April 7, 2026 20:33
@lucaspimentel lucaspimentel requested a review from Copilot April 7, 2026 20:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 + RemoveNumericToStringCodeFixProvider to avoid string allocations in numeric log arguments.
  • Add analyzer + code fix test coverage (new helper + new test suites).
  • Update a few Datadog.Trace logging 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.

@lucaspimentel lucaspimentel marked this pull request as ready for review April 7, 2026 20:57
@lucaspimentel lucaspimentel requested review from a team as code owners April 7, 2026 20:57
@lucaspimentel lucaspimentel changed the title [Analyzers] Add analyzer to detect ToString() on numeric types in log calls [Analyzers] Add DDALLOC001: detect ToString() on numeric types in log calls Apr 7, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

@lucaspimentel lucaspimentel changed the title [Analyzers] Add DDALLOC001: detect ToString() on numeric types in log calls [Analyzers] Add analyzer to detect ToString() on numeric types in log calls Apr 7, 2026
@lucaspimentel lucaspimentel force-pushed the lpimentel/allocation-analyzer-tostring-in-logs branch from 178b1d3 to 82aa121 Compare April 7, 2026 22:51
@lucaspimentel lucaspimentel changed the title [Analyzers] Add analyzer to detect ToString() on numeric types in log calls [Analyzers] Add analyzer and code fix for ToString() on numeric types in log calls Apr 7, 2026
Copy link
Copy Markdown
Member

@andrewlock andrewlock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member Author

@lucaspimentel lucaspimentel Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) 😅

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

for (var i = messageTemplateIndex + 1; i < arguments.Count; i++)
{
var argExpression = arguments[i].Expression;
CheckForNumericToString(context, argExpression);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why just numeric? Isn't calling ToString() basically always going to be not wanted, regardless of the type? 🤔

Copy link
Copy Markdown
Member Author

@lucaspimentel lucaspimentel Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@lucaspimentel lucaspimentel marked this pull request as draft April 8, 2026 14:42
🤖 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>
@lucaspimentel lucaspimentel force-pushed the lpimentel/analyzers-ai-docs branch from 11d35ce to 0b5278a Compare April 8, 2026 14:59
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>
@lucaspimentel lucaspimentel force-pushed the lpimentel/allocation-analyzer-tostring-in-logs branch from 82aa121 to f6c0c20 Compare April 8, 2026 20:44
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>
@lucaspimentel lucaspimentel changed the title [Analyzers] Add analyzer and code fix for ToString() on numeric types in log calls [Analyzers] Add DDLOG010 rule and code fix for ToString() on numeric types in log calls Apr 8, 2026
@lucaspimentel lucaspimentel changed the title [Analyzers] Add DDLOG010 rule and code fix for ToString() on numeric types in log calls [Analyzers] Add diagnostic rule and code fix for ToString() on numeric types in log calls Apr 8, 2026
@lucaspimentel lucaspimentel marked this pull request as ready for review April 8, 2026 22:44
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

@lucaspimentel lucaspimentel force-pushed the lpimentel/analyzers-ai-docs branch from d44e281 to 0955dd9 Compare April 9, 2026 21:51
@lucaspimentel lucaspimentel requested a review from a team as a code owner April 9, 2026 21:51
@lucaspimentel lucaspimentel added the status:do-not-merge Work is done. Can review, but do not merge yet. label Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos area:builds project files, build scripts, pipelines, versioning, releases, packages status:do-not-merge Work is done. Can review, but do not merge yet.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants