-
Notifications
You must be signed in to change notification settings - Fork 652
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
sdk: shut down span processors automatically #280
sdk: shut down span processors automatically #280
Conversation
The BatchExportSpanProcessor is an asynchronous span processor that uses a worker thread to call the different exporters. Before this commit applications had to shut down the span processor explicitely to guarantee that all the spans were summited to the exporters, this was not very intuitive for the users. This commit removes that limitation by implementing the tracer's __del__ method and an atexit hook. According to __del__'s documentation [1] it is possible that sometimes it's not called, for that reason the atexit hook is also used to guarantee that the processor is shut down in all the cases. [1] https://docs.python.org/3/reference/datamodel.html#object.__del__
@@ -333,6 +334,13 @@ def __init__( | |||
self._current_span_slot = Context.register_slot(slot_name) | |||
self._active_span_processor = MultiSpanProcessor() | |||
self.sampler = sampler | |||
self._atexit_hanlder = atexit.register( |
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.
My personal preference would be to not do this by default, but have it as something the user can plug himself, or at least make this optional.
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.
@carlosalberto why not do this by default? Because it would be surprising that calling del
results in (blocking!) network calls?
I agree about making this configurable, but I think this is much better than the current default: call shutdown
or lose unexported spans.
Codecov Report
@@ Coverage Diff @@
## master #280 +/- ##
==========================================
+ Coverage 85.56% 85.61% +0.05%
==========================================
Files 33 33
Lines 1600 1592 -8
Branches 178 179 +1
==========================================
- Hits 1369 1363 -6
+ Misses 185 182 -3
- Partials 46 47 +1
Continue to review full report at Codecov.
|
Btw, in Java we have a |
Do you think it is a valid requirement to have a |
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 think this is a much-needed improvement to the API, and the right default behavior.
Heads up that __del__
can introduce some subtle bugs though; after this change, if we ever add a tracer
attribute to a SpanProcessor
we'll get a memory leak.
@@ -333,6 +334,13 @@ def __init__( | |||
self._current_span_slot = Context.register_slot(slot_name) | |||
self._active_span_processor = MultiSpanProcessor() | |||
self.sampler = sampler | |||
self._atexit_hanlder = atexit.register( |
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.
@carlosalberto why not do this by default? Because it would be surprising that calling del
results in (blocking!) network calls?
I agree about making this configurable, but I think this is much better than the current default: call shutdown
or lose unexported spans.
self._active_span_processor.shutdown | ||
) | ||
|
||
def __del__(self): |
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.
Why put this on Tracer
instead of SpanProcessor
?
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 think that having it in Tracer
makes it more general and other possible SpanProcessor
implementations would not have to take care of this.
This problem looks a little bit nasty to me and I am not sure what is the way to go. My proposal would be something like:
If you agree @carlosalberto @c24t I can update this PR with that approach. |
I also don't like However, even the |
I implemented the solution I proposed, I admit that I am not totally happy with that but I don't know a better solution now. |
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.
Looks good! I think there is room for improvement with a global object, but no need to block this valuable pr for that.
Any unit tests that should be written or modified along with this change?
- test that span processor (Simple and Batch) shut down exporters - test that trace shuts down span processor - test atexit hook in Tracer.shutdown()
I added some shutdown tests in 981f2ba. |
no available in python < 3.6
9c44761
to
e1bb798
Compare
- avoid using hasattr and assign member to None instead - use shutil.which to overcome problem in windows
tracer.add_span_processor(mock_processor) | ||
|
||
{tracer_shutdown} | ||
""" |
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.
Very weird, but it looks like it works!
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.
Indeed. I didn't find another way to do it!
@mauriciovasquezbernal FYI if you check "allow edits from maintainers" other people can push to this branch, e.g. to fix merge conflicts. My suggestions aren't blocking, but I'd appreciate if you commit them when you fix the merge conflicts here. I can merge this once it's fixed. |
@c24t I committed them by hand and also fix conflicts with master. |
The BatchExportSpanProcessor is an asynchronous span processor that uses a
worker thread to call the different exporters. Before this commit applications
had to shut down the span processor explicitely to guarantee that all the spans
were summited to the exporters, this was not very intuitive for the users.
This commit removes that limitation by implementing the tracer's del
method and an atexit hook. According to del's documentation [1] it is
possible that sometimes it's not called, for that reason the atexit hook is
also used to guarantee that the processor is shut down in all the cases.
[1] https://docs.python.org/3/reference/datamodel.html#object.__del__