-
Notifications
You must be signed in to change notification settings - Fork 772
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
Refactor exporter - step 3 #1083
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1083 +/- ##
==========================================
- Coverage 76.66% 76.59% -0.08%
==========================================
Files 223 224 +1
Lines 6158 6165 +7
==========================================
+ Hits 4721 4722 +1
- Misses 1437 1443 +6
|
@@ -46,9 +47,10 @@ public ConsoleExporter(ConsoleExporterOptions options) | |||
this.serializerOptions.Converters.Add(new ActivityTraceIdConverter()); | |||
} | |||
|
|||
public override Task<ExportResult> ExportAsync(IEnumerable<Activity> activityBatch, CancellationToken cancellationToken) | |||
[MethodImpl(MethodImplOptions.Synchronized)] |
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.
I didn't even notice this until I read the description. My initial reaction... feels a little hackish. We shouldn't rely on users to add this, we should wrap the call in a lock if we want to make sure it isn't called concurrently? The spec says something about Export shouldn't be called concurrently, it doesn't say Exporters should implement Export so it isn't callable concurrently, which is what this feels like. 🤷
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.
Or how about having the SimpleExportActivityProcessor
taking a parameter which allows people to specify whether it is reentrant or not (and by default use lock), I was thinking about ETW/LTTng scenario where folks want ultimate concurrency.
Something like this.
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.
I like the idea of a flag to opt into different behavior than what the spec says. We could also have a SimpleProcessor and a BatchingProcessor that are fully spec-compliant but also ship something like a ConcurrentProcessor or ReentrantProcessor that can be explicit in its changing of the rules?
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.
That's works, too! 😄
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.
I moved the current logic to ReentrantExportActivityProcessor
, and changed SimpleExportActivityProcessor
to simply call the reentrant one with a lock guard.
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.
Now the PR got merged and OOP fans are staring at us - "Why are you guys making a non-reentrant class a child of reentrant one" 😂
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.
It is a bit odd, isn't it? I know you were shooting for code re-use, maybe the flag/option idea would be better? You could make a base class that has everything but the OnEnd part?
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.
Tracked by #898.
{ | ||
private readonly ActivityExporterSync exporter; | ||
private bool stopped; | ||
private readonly object lck = new object(); |
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.
nit: Looks like "ick" 😄 Probably syncObject or lockObject is more common?
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.
I'm not a C# developer, borrowed/learned this from @cijothomas 😺
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.
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.
:D Thanks for fixing the names throughout.
/// </summary> | ||
/// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param> | ||
protected override void Dispose(bool disposing) | ||
{ |
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.
@reyang Just noticed you're not calling Shutdown from Dispose. You did that on purpose, right?
You know, TracerProviderSdk doesn't seem to call Shutdown on anything, only Dispose. Why don't we just remove Shutdown methods across the board? I know the spec says we need it, but we have Dispose pattern in .NET for shutdown. Breaking with the spec here (in name only) might actually lead to a simpler, more easy-to-use & implement library?
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.
Tracked by #1024.
Yep, I think Dispose
is essentially the language idiomatic version of Shutdown
. Dispose
doesn't take any parameter, Shutdown
might potentially take a timeout value, and that can be engineered as a property of the object instead of an argument to the function.
This is a follow up PR of #1078.
Changes
ConsoleExporter
to the new path.[MethodImpl(MethodImplOptions.Synchronized)]
.For significant contributions please make sure you have completed the following items: