Skip to content

Conversation

jamescrosswell
Copy link
Collaborator

@jamescrosswell jamescrosswell changed the base branch from main to version6 October 13, 2025 00:34
Copy link

codecov bot commented Oct 13, 2025

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (version6@6377b49). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/Sentry/Internal/NoOpSpan.cs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             version6    #4627   +/-   ##
===========================================
  Coverage            ?   73.08%           
===========================================
  Files               ?      479           
  Lines               ?    17389           
  Branches            ?     3431           
===========================================
  Hits                ?    12709           
  Misses              ?     3821           
  Partials            ?      859           

☔ 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.

@jamescrosswell
Copy link
Collaborator Author

@Flash0ver I'm trying to force an analyzer warning for the CA2000 (so that I can build and test a way to suppress this). I've added this to the csproj file for samples/Sentry.Samples.Console.Basic/Sentry.Samples.Console.Basic.csproj:

<WarningsAsErrors>CA2000</WarningsAsErrors>

However I can't seem to get it to work:
image

The warning does appear for the undisposed use of Foo (which I added to test the warning was enabled)... but we're not seeing it for our newly disposable ISpan classes. StartTransaction returns an ITransactionTracer that descends from ISpan, which implements IDisposable.

Any ideas/thoughts?

@Flash0ver
Copy link
Member

Flash0ver commented Oct 13, 2025

Oh ... perhaps I totally misunderstood CA2000 😟

DisposeObjectsBeforeLosingScope.cs

Hmmm ... it seems that the CA2000-DiagnosticAnalyzer does some Control-Flow-Analysis, that either tries to "see through" the implementation and does not report when it can't statically figure it out, or just does not report for some usage patterns.

var instance1 = new MyDisposable(); //CA2000
var instance2 = new MyFactory().CreateInstance(); //CA2000
var instance3 = MyFactory.CreateStatic(); //CA2000
var instance4 = MyFactory.Instance.CreateInstance(); // does not report CA2000

public sealed class MyDisposable : IDisposable
{
    public void Dispose()
    {
    }
}
public interface IMyFactory
{
    IDisposable CreateInstance();
}
public sealed class MyFactory : IMyFactory
{
    public static IMyFactory Instance { get; } = new MyFactory();
    public static IDisposable CreateStatic() => new MyDisposable();
    public IDisposable CreateInstance() => new MyDisposable();
}

Not sure if that analysis behavior is intended or not.
Perhaps the Analyzer cannot "see through" our rather complex control flow from SentrySdk, via the IHub, to some extension-methods.


Now, as a follow-up, I'm wondering:
We do have 2 public types that inherit ISpan, and with that IDisposable:

var transaction = new TransactionTracer(null!, null!); //CA2000
var span = new SpanTracer(null!, transaction, default, default, null!); //CA2000
span.Finish();
transaction.Finish();

Are there valid/intended usage scenarios to instantiate these types directly from user code, which would report CA2000, even when properly Finished?
Or ... perhaps we do not need a DiagnosticSuppressor for CA2000, since it's not reported for our implementation ... which may change in the future 🤔

@jamescrosswell
Copy link
Collaborator Author

Are there valid/intended usage scenarios to instantiate these types directly from user code, which would report CA2000,

I can't think of any scenario in which people would want to construct those manually... so I suspect not.

Or ... perhaps we do not need a DiagnosticSuppressor for CA2000, since it's not reported for our implementation ...

That's possibly the case yes... and without being able to reproduce the warning that it's supposed to suppress, it's relatively difficult to test. I think this PR might be ready for review then...

}

[Fact]
public void Dispose_Finished_Finishes()
Copy link
Member

Choose a reason for hiding this comment

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

question: Are part of the names here inverted from what each test case actually tests?

-public void Dispose_Finished_Finishes()
+public void Dispose_Unfinished_Finishes()

-public void Dispose_Unfinished_DoesNothing()
+public void Dispose_Finished_DoesNothing()

Or am I reading this wrongly?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Per the CONTRIBUTING.md, the first part is the method Dispose.

The second part is the context (Finished or Unfinished... this could be more elaborate like TransactionIsFinsished and TransactionIsUnfinished but I figured that was clear from both the SUT and the implementation.

The last part is the expectation (e.g. DoesNothing).

Copy link
Member

@Flash0ver Flash0ver Oct 15, 2025

Choose a reason for hiding this comment

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

Sorry ... I phrased it poorly.
What I meant was that Dispose_Finished_Finishes should actually be Dispose_Unfinished_Finishes,
and that Dispose_Unfinished_DoesNothing should be Dispose_Finished_DoesNothing.
It was just the name of the middle "context" portion what was flipped.

This is fixed now.

Copy link
Member

@Flash0ver Flash0ver Oct 15, 2025

Choose a reason for hiding this comment

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

But I believe that the names are still not quite correct:

  • Dispose_TransactionIsUnfinished_FinishesTransaction
  • Dispose_TransactionIsFinsished_DoesNothing

But both of these tests are in the SpanTracerTests.cs.
I guess it should say "SpanIs(Un)Finished" and "FinishesSpan".

But I am actually fine with the shorter version ... as it does make sense within the context of the respective test type:

  • Dispose_Unfinished_Finishes
  • Dispose_Finished_DoesNothing

Since we have the same test names then on TransactionTracerTests.cs as well.
Same test name, but in a different test class.

/// <inheritdoc />
public void Finish()
{
// TODO: Replace with InterlockedBoolean once this has been merged into version6
Copy link
Member

Choose a reason for hiding this comment

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

TODO (as a "resolvable" comment)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ITransactionTracer should implement IDisposable

2 participants