-
-
Notifications
You must be signed in to change notification settings - Fork 225
QOL: Allow finishing spans and transactions with using
#4627
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: version6
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## version6 #4627 +/- ##
===========================================
Coverage ? 73.10%
===========================================
Files ? 479
Lines ? 17388
Branches ? 3431
===========================================
Hits ? 12711
Misses ? 3819
Partials ? 858 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
@Flash0ver I'm trying to force an analyzer warning for the <WarningsAsErrors>CA2000</WarningsAsErrors> However I can't seem to get it to work: The warning does appear for the undisposed use of Any ideas/thoughts? |
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. Now, as a follow-up, I'm wondering: 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 |
I can't think of any scenario in which people would want to construct those manually... so I suspect not.
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... |
/// Transaction span tracer. | ||
/// </summary> | ||
public class SpanTracer : IBaseTracer, ISpan | ||
public sealed class SpanTracer : IBaseTracer, ISpan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Is it worth a consideration to make SpanTracer
internal, too? (in a potential follow-up)
So that users cannot run into CA2000
var span = new SpanTracer(null!, transaction, default, default, null!); //CA2000
span.Finish();
Or is it a potential user code scenario to try to cast?
if (SentrySdk.StartSpan("operation", "description") is SpanTracer span)
But this could have quite a large impact.
|
||
/// <summary> | ||
/// Automatically finishes the span at the end of a <c>using</c> block. This is a convenience method only. Disposing | ||
/// is not required (and analyser warnings are suppressed). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion:
- shall we remove the note about
(and analyser warnings are suppressed)
... as it seems we cannot reproduceCA2000
, unless aSpanTracer
is directlynew
ed. - should we mention that
Dispose
finishes the span as "OK" / Successful- is equivalent to
<see cref="Finish()"/>
- and to use any of these overloads to finish as error / unsuccessfully
<see cref="Finish(SpanStatus)"/>
<see cref="Finish(Exception)"/>
<see cref="Finish(Exception, SpanStatus)"/>
/// Transaction tracer. | ||
/// </summary> | ||
public class TransactionTracer : IBaseTracer, ITransactionTracer | ||
public sealed class TransactionTracer : IBaseTracer, ITransactionTracer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Is it worth a consideration to make TransactionTracer
internal, too? (in a potential follow-up)
So that users cannot run into CA2000
var transaction = new TransactionTracer(null!, null!); //CA2000
transaction.Finish();
Or is it a potential user code scenario to try to cast?
if (SentrySdk.StartTransaction("name", "operation") is TransactionTracer transaction)
But this could have quite a large impact.
|
||
/// <summary> | ||
/// Automatically finishes the span at the end of a <c>using</c> block. This is a convenience method only. Disposing | ||
/// is not required (and analyser warnings are suppressed). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion:
- shall we remove the note about
(and analyser warnings are suppressed)
... as it seems we cannot reproduceCA2000
, unless aTransactionTracer
is directlynew
ed. - should we mention that
Dispose
finishes the transaction as "OK" / Successful- is equivalent to
<see cref="Finish()"/>
- and to use any of these overloads to finish as error / unsuccessfully
<see cref="Finish(SpanStatus)"/>
<see cref="Finish(Exception)"/>
<see cref="Finish(Exception, SpanStatus)"/>
} | ||
|
||
[Fact] | ||
public void Dispose_Finished_Finishes() |
There was a problem hiding this comment.
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?
/// <inheritdoc /> | ||
public void Finish() | ||
{ | ||
// TODO: Replace with InterlockedBoolean once this has been merged into version6 |
There was a problem hiding this comment.
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)
public void Finish() | ||
{ | ||
// TODO: Replace with InterlockedBoolean once this has been merged into version6 | ||
if (Interlocked.Exchange(ref _hasFinished, 1) == 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Shall we create a dedicated test for double-Disposal / double-Finishing?
Or is it actually sufficiently covered already by TransactionTracerTests.Dispose_Finished_DoesNothing
?
I can imagine it is, as this new test drove this guard, right?
### BREAKING CHANGES | ||
|
||
- SentryOptions.IsEnvironmentUser now defaults to false on MAUI. The means the User.Name will no longer be set, by default, to the name of the device ([#4606](https://github.com/getsentry/sentry-dotnet/pull/4606)) | ||
- Spans and Transactions now implement `IDispose` so that they can be used with `using` statements that will automatically finish the span when it passes out of scope, to be consistent with `Activity` classes when using OpenTelemetry ([#4627](https://github.com/getsentry/sentry-dotnet/pull/4627)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion:
IDispose
->IDisposable
- also mention using-declarations alongside using-statements
- specify "Successfully"
- Spans and Transactions now implement `IDispose` so that they can be used with `using` statements that will automatically finish the span when it passes out of scope, to be consistent with `Activity` classes when using OpenTelemetry ([#4627](https://github.com/getsentry/sentry-dotnet/pull/4627)) | |
- Spans and Transactions now implement `IDisposable` so that they can be used with `using` statements/declarations that will automatically finish the span successfully when it passes out of scope, to be consistent with `Activity` classes when using OpenTelemetry ([#4627](https://github.com/getsentry/sentry-dotnet/pull/4627)) |
/// Transaction span tracer. | ||
/// </summary> | ||
public class SpanTracer : IBaseTracer, ISpan | ||
public sealed class SpanTracer : IBaseTracer, ISpan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: CHANGELOG
Is it worth a note in the CHANGELOG that both
SpanTracer
TransactionTracer
are no longer inheritable?
Resolves #4321