Skip to content

fix: populate sentry.sdk.name and sentry.sdk.version for console apps - #5483

Open
zkasuran wants to merge 1 commit into
getsentry:mainfrom
zkasuran:fix/sdkversion-empty-for-console
Open

fix: populate sentry.sdk.name and sentry.sdk.version for console apps#5483
zkasuran wants to merge 1 commit into
getsentry:mainfrom
zkasuran:fix/sdkversion-empty-for-console

Conversation

@zkasuran

Copy link
Copy Markdown

Closes #5352

What changed and why

Structured logs and trace metrics from a plain console app were going out with no
sentry.sdk.name and no sentry.sdk.version attribute. The same code under
ASP.NET Core was fine. These attributes identify the SDK that produced the data, so
a whole class of apps was shipping logs and metrics that could not be attributed to
the .NET SDK.

Root cause: SentryAttributes.SetDefaultAttributes reads the SDK fields off the
SdkVersion it is handed:

if (sdk.Name is { } name)       { SetAttribute("sentry.sdk.name", name); }
if (sdk.Version is { } version) { SetAttribute("sentry.sdk.version", version); }

On the logs path (SentryLog.cs:153) and the metrics path
(SentryMetric.Factory.cs:23) the value passed in is scope.Sdk. Both sites try to
fall back with ?? SdkVersion.Instance, but that fallback is dead: Scope.Sdk is a
non-null auto-initialized property (Scope.cs:277, public SdkVersion Sdk { get; } = new();),
so scope?.Sdk ?? SdkVersion.Instance always resolves to scope.Sdk. In a console
app nothing populates that object, so Name and Version stay null and both guards
above are false. Framework integrations do not hit this: ASP.NET Core fills
scope.Sdk in SentryMiddleware.cs:257-258, so its logs carry the attributes.

The fix falls back per field to the populated SdkVersion.Instance at the one place
both paths share:

if ((sdk.Name ?? SdkVersion.Instance.Name) is { } name)
{
    SetAttribute("sentry.sdk.name", name);
}
if ((sdk.Version ?? SdkVersion.Instance.Version) is { } version)
{
    SetAttribute("sentry.sdk.version", version);
}

When an integration has already set scope.Sdk.Name, that value is non-null so the
?? short circuits and the integration still wins. The fallback only supplies a
value where the field would otherwise be null. SdkVersion.Instance is the same
object the envelope header uses, so logs and metrics now agree with the envelope.

Tests

  • New: SentryLogTests.SetDefaultAttributes_EmptyScopeSdk_UsesSdkInstance builds a
    log with a fresh new Scope(options) (the console case) and asserts
    sentry.sdk.name == "sentry.dotnet" with a non-empty sentry.sdk.version.
  • New: SentryMetricTests.SetDefaultAttributes_EmptySdk_UsesSdkInstance does the
    same for a metric built with new SdkVersion().
  • Updated: SentryLogTests.WriteTo_Envelope_MinimalSerializedSentryLog and
    SentryMetricTests.WriteTo_Envelope_MinimalSerializedSentryMetric were pinning the
    old payload with no SDK attributes. They now include the SDK name and version,
    which is the correct serialized form after the fix.

The existing Protocol_Default_VerifyAttributes tests never caught this because they
pre-populate the Sdk before calling SetDefaultAttributes.

Verification

Verified locally in Docker (mcr.microsoft.com/dotnet/sdk:10.0.302, the exact SDK
pinned by global.json, host runs net10.0):

dotnet test test/Sentry.Tests/Sentry.Tests.csproj -f net10.0
  • With the fix: Failed: 0, Passed: 2533, Skipped: 5, Total: 2538.
  • Reverting only SentryAttributes.cs while keeping the tests: Failed: 4, Passed: 2529.
    The four failures are the two new tests plus the two corrected serialization tests,
    which reproduces the bug.
  • dotnet format --verify-no-changes on the changed files: no changes.

Changelog

The commit and this PR lead with fix:, so craft categorizes it under Fixes at
release time. Per CONTRIBUTING.md I have not edited CHANGELOG.md by hand. Let me
know if you want a custom ### Changelog Entry with more detail than the title.

AI disclosure

AI assistance (Claude, Anthropic) was used to trace the root cause, write the fix and
the tests, then run the suite. I own the change, reviewed it and verified it locally
before submitting. Verified: the full Sentry.Tests suite on net10.0 (2533 passing,
0 failing); the bug reproduced by reverting only the source file (4 failing);
dotnet format --verify-no-changes clean on the changed files.

Co-Authored-By: Claude (Anthropic) <noreply@anthropic.com>
@github-actions github-actions Bot added the risk: medium PR risk score: medium label Aug 13, 2026
@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.72%. Comparing base (3fe027d) to head (36a0d63).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5483      +/-   ##
==========================================
- Coverage   74.73%   74.72%   -0.02%     
==========================================
  Files         513      513              
  Lines       18744    18744              
  Branches     3666     3666              
==========================================
- Hits        14009    14007       -2     
- Misses       3863     3864       +1     
- Partials      872      873       +1     

☔ View full report in Codecov by Harness.
📢 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.

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

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SdkVersion.Name and SdkVersion.Version are empty for Console-Apps

1 participant