-
Notifications
You must be signed in to change notification settings - Fork 667
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
Add general timeout mechanism in the export layer #385
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,8 +13,10 @@ | |
# limitations under the License. | ||
|
||
import datetime | ||
import signal | ||
import threading | ||
from collections import OrderedDict, deque | ||
from contextlib import contextmanager | ||
|
||
try: | ||
# pylint: disable=ungrouped-imports | ||
|
@@ -26,6 +28,31 @@ | |
from collections import Sequence | ||
|
||
|
||
def set_timeout_signal_handler(): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function defines a inner function and then registers it into |
||
"Signal timeout setter." | ||
|
||
def signal_handler_function(signum, frame): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a function, there is no need to add |
||
raise TimeoutError | ||
|
||
return signal.signal(signal.SIGALRM, signal_handler_function) | ||
|
||
|
||
@contextmanager | ||
def timeout_in_seconds(seconds=None): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea of having a general purpose timeout mechanism is great, but keep in mind that the specification requires Please consider making a decorator that is then applied directly to the functions def timeout(function):
def inner(*args, timeout=90, **kwargs):
print(timeout)
function(*args, **kwargs)
return inner
@timeout
def export(first, second):
print(first)
print(second)
export(1, 2, timeout=9)
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exporters might have a better way to implement timeouts, e.g. in the zipkin exporter we'd pass a I think a general purpose timeout in processor is fine, but exporters should implement timeout logic themselves: #346 (comment). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think is better if you document the function attribute instead of using the name of the function as documentation for the attribute itself, something like this: def timeout(time):
"""
...
time: time to wait before timing out, in seconds
"""
... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ocelotl you and @toumorokoshi can duke it out over hungarian notation. 😄 |
||
"""A general timeout mechanism.""" | ||
|
||
if seconds is None: | ||
yield | ||
else: | ||
if threading.current_thread() is threading.main_thread(): | ||
set_timeout_signal_handler() | ||
signal.alarm(seconds) | ||
try: | ||
yield | ||
finally: | ||
signal.alarm(0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For this to be a general-purpose timeout func, shouldn't it reset the old signal handler after cancelling the alarm? |
||
|
||
|
||
def ns_to_iso_str(nanoseconds): | ||
"""Get an ISO 8601 string from time_ns value.""" | ||
ts = datetime.datetime.utcfromtimestamp(nanoseconds / 1e9) | ||
|
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 looks like you're setting the handler here because
export
runs in a worker thread? But since we initialize the span processor right at startup, this is going to change the SIGALRM handler for the entire life of the process, not just while we're waiting for an export to timeout.