Skip to content

feat(metrics): Trace-connected Metrics (Analyzers)#4840

Draft
Flash0ver wants to merge 20 commits intomainfrom
feat/trace-connected-metrics-analyzers
Draft

feat(metrics): Trace-connected Metrics (Analyzers)#4840
Flash0ver wants to merge 20 commits intomainfrom
feat/trace-connected-metrics-analyzers

Conversation

@Flash0ver
Copy link
Member

@Flash0ver Flash0ver commented Jan 15, 2026

based on

My little weekend-project:
Add a Diagnostic-Analyzer to our Compiler-Extensions, that warn users when a metric would not be emitted due to an unsupported numeric value type.

Context:
For the numeric type of a Metric, we currently allow 64-bit sized integral (signed) and floating-point numbers.
That means that e.g. ulong, System.Int128, or decimal are currently not supported by Sentry.
The compile-time constraint of Sentry.SentryMetric<T> only constrains to non-nullable value types.
Alternatively, we could have implemented respectively types overloads for the method groups:

public void EmitCounter(string name, long value);
public void EmitCounter(string name, float value);
public void EmitCounter(string name, double value);
public void EmitCounter(string name, long value, Scope? scope)
public void EmitCounter(string name, float value, Scope? scope)
public void EmitCounter(string name, double value, Scope? scope)
public void EmitCounter ..

public void EmitGauge ..
public void EmitDistribution ..

To avoid this explosion of overloads per method group,
and be similar to the implementation of System.Diagnostics.Metrics,
we are not compile-time constraining unsupported types,
but are instead run-time constraining unsupported types (no-op and Debug-Diagnostic-Logging).

To still warn users unfamiliar with the System.Diagnostics.Metrics.Meter-based APIs,
I built an Analyzer over some weekends to guide new users.

options.Experimental.SetBeforeSendMetric(static SentryMetric? (SentryMetric metric) =>
{
    if (metric.TryGetValue<int>(out int int32) && int32 < 0)
    {
        return null;
    }

    if (metric.TryGetValue<uint>(out uint uint32) && uint32 == 0) //SENTRY1001
    {
        return null;
    }

    return metric;
});

SentrySdk.Experimental.Metrics.EmitCounter("my.counter", 1);
SentrySdk.Experimental.Metrics.EmitCounter("my.counter", 1m); //SENTRY1001
SentrySdk.Experimental.Metrics.EmitCounter("my.counter", StringComparison.CurrentCultureIgnoreCase); //SENTRY1001
SentrySdk.Experimental.Metrics.EmitCounter<ulong>("my.counter", default); //SENTRY1001

#skip-changelog

@Flash0ver Flash0ver self-assigned this Jan 15, 2026
@Flash0ver Flash0ver added Roslyn The .NET Compiler Platform, Roslyn Components and Extensions, Microsoft.CodeAnalysis Metrics labels Jan 15, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 15, 2026

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 70a58d0

@codecov
Copy link

codecov bot commented Jan 15, 2026

Codecov Report

❌ Patch coverage is 77.77778% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.88%. Comparing base (9a88d5e) to head (70a58d0).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...ensions/Analyzers/TraceConnectedMetricsAnalyzer.cs 75.51% 6 Missing and 6 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4840      +/-   ##
==========================================
+ Coverage   73.85%   73.88%   +0.03%     
==========================================
  Files         494      498       +4     
  Lines       17868    17981     +113     
  Branches     3509     3522      +13     
==========================================
+ Hits        13197    13286      +89     
- Misses       3815     3829      +14     
- Partials      856      866      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Flash0ver and others added 5 commits January 16, 2026 13:21
Provides hierarchical constants for metric units supported by Sentry Relay,
organized into Duration, Information, and Fraction categories.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@Flash0ver Flash0ver marked this pull request as ready for review January 16, 2026 14:41
@Flash0ver Flash0ver marked this pull request as draft January 19, 2026 15:26
Base automatically changed from feat/trace-connected-metrics to main February 8, 2026 21:37
@github-actions
Copy link
Contributor

github-actions bot commented Feb 13, 2026

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


This PR will not appear in the changelog.


🤖 This preview updates automatically when you update the PR.


Rule ID | Category | Severity | Notes
--------|----------|----------|-------
SENTRY1001 | Support | Warning | TraceConnectedMetricsAnalyzer No newline at end of file
Copy link
Member Author

Choose a reason for hiding this comment

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

question: ID

I'm a a bit certain about the ID.
Also, I'm not sure if it should be two separate IDs, one for the Emit* methods, and one for SentryMetric.TryGetValue<TValue>(out TValue value) method.

https://github.com/SimonCropp/Polyfill
-->
<ItemGroup>
<PackageReference Include="Polyfill" Version="9.8.1" PrivateAssets="all" />
Copy link
Member Author

Choose a reason for hiding this comment

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

note: see also #4879

defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: Description,
helpLinkUri: null
Copy link
Member Author

Choose a reason for hiding this comment

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

question: docs

Should we document the Analyzer?
If so, we could provide a link to the documentation page here.

private static readonly string Description = "Integers should be a 64-bit signed integer, while doubles should be a 64-bit floating point number.";

private static readonly DiagnosticDescriptor Rule = new(
id: DiagnosticIds.Sentry1001,
Copy link
Member Author

Choose a reason for hiding this comment

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

question: CHANGELOG

Should we mention this Analyzer, and Analyzer in general, in the CHANGELOG?
If so, in the Features category, or a separate category?

/// Guide consumers to use the public API of <see href="https://develop.sentry.dev/sdk/telemetry/metrics/">Sentry Trace-connected Metrics</see> correctly.
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class TraceConnectedMetricsAnalyzer : DiagnosticAnalyzer
Copy link
Member Author

Choose a reason for hiding this comment

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

question: do we want to do this in general?

This started off as a weekend-project for me.
Do we want to provide this Analyzer in the first place?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Metrics Roslyn The .NET Compiler Platform, Roslyn Components and Extensions, Microsoft.CodeAnalysis

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants