-
Notifications
You must be signed in to change notification settings - Fork 222
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
Make OT binding support explicit timestamps. #824
Make OT binding support explicit timestamps. #824
Conversation
💚 CLA has been signed |
fc0541b
to
af058fc
Compare
💚 Build Succeeded
Expand to view the summary
Build stats
Test stats 🧪
💚 Flaky test reportTests succeeded. 🤖 GitHub commentsTo re-run your PR in the CI, just comment with:
|
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.
This looks good to me but I'm going to wait on a review from @beniwohli because he wrote the opentracing bridge. (Also need to wait on the tests)
jenkins run the tests please |
Also, @AndreiPashkin, please sign the CLA when you get a chance. |
Hmm, but I've signed it, here is the PDF: Why doesn't the check turn green? I'm also puzzled - how can I run tests so that I can use PDB for debugging locally? Could you please advise? I'd like to add one test case. |
Looks like CLA went green, maybe it was delayed.
I don't tend to use PDB, but running the tests should be as simple as installing the requirements file that is most relevant (at minimum, reqs-base.txt), and then run |
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.
Great work!
Ideally, we'd have a test for this, but I'm fine with merging and adding tests after that.
Let me actually write a test. |
@basepi, @beniwohli, I've observed some strange when tested my changes. Here is my test-script:
When I install the latest release with When I install my changes (
I've also captured payload that was sent to the Elastic APM instance in both cases. Without changes:
With changes:
Does anyone have any ideas about what could be wrong? |
@beniwohli, can you also please explain this code: Why is |
af058fc
to
36cece9
Compare
elasticapm/utils/time.py
Outdated
limit=limit | ||
) | ||
return ( | ||
clocks_measurements.destination + |
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.
line break after binary operator
elasticapm/utils/time.py
Outdated
if self.__measurements_ttl is None or self.__measurements_ttl == 0: | ||
return | ||
if ((self.__clocks_measurement_cache[0] + self.__measurements_ttl) > | ||
time.time()): |
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.
visually indented line with same indent as next logical line
elasticapm/utils/time.py
Outdated
return | ||
if self.__measurements_ttl is None or self.__measurements_ttl == 0: | ||
return | ||
if ((self.__clocks_measurement_cache[0] + self.__measurements_ttl) > |
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.
line break after binary operator
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.
@basepi, I'm not sure, how should I re-format this line? Without breaks it is going to become too long.
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 a little surprised that black
isn't reformatting this for you...
Our enforced line length limit is actually 120 columns, so I think you can just do this on one line. I try to keep my code down to around 90 columns, but if it hurts readability I think it's not worth chasing.
elasticapm/utils/time.py
Outdated
src_now = dst_now = None | ||
epsilon = sys.float_info.max | ||
i = 0 | ||
for i in range(limit): |
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.
Loop control variable 'i' not used within the loop body. If this is intended, start the name with an underscore.
5e29e6f
to
c3034ef
Compare
@@ -124,10 +125,15 @@ def set_tag(self, key, value): | |||
return self | |||
|
|||
def finish(self, finish_time=None): | |||
if (finish_time is not None and |
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.
line break after binary operator
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.
@AndreiPashkin thanks a lot for your contribution!
Just as a quick rationale why we didn't ensure start
/ end
timestamps to be monotonic when explicitly provided: these arguments have been introduced mainly for testing, so that we can override durations and test for exact values. They've not been intended to use publicly, exactly because mixing monotonic and non-monotonic time sources is problematic.
While I think your TimestampConversionUtil
is a smart way to kinda reconcile the two time sources, it does add a lot of complexity, and it's not bulletproof as far as I can tell (e.g. the system clock could jump right after you measured the delta, but before applying it to the non-monotonic timestamp).
As such, I'm a bit wary to introduce this into a major code path of the agent. However, I'd be open to it if you moved the usage of TimestampConversionUtil
to the opentracing bridge.
elasticapm/utils/time.py
Outdated
|
||
SYSTEM_TO_MONOTONIC = TimestampConversionUtil( | ||
time.time, | ||
time.monotonic, |
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.
time.monotonic
is not available on Python 2.7. To ensure Python 2.7 compatibility, timeit.default_timer
is the best option. On Python 3, it defaults to time.perf_counter
, on Python 2 to the best platform dependent time source (non-monotonic)
But if system clock is jumping then the agent is going to send skewed data in any case - so there is no bullet-proofness against that in current
Should I add another private argument for system-clock timestamp and pass it from the OT bridge along with the monotonic timestamp? |
@beniwohli |
c3034ef
to
4df630f
Compare
💚 Flaky test reportTests succeeded. Expand to view the summary
Test stats 🧪
|
e8170e1
to
3e18dd7
Compare
elasticapm/base.py
Outdated
:return: the started transaction object | ||
""" | ||
if self.config.is_recording: | ||
return self.tracer.begin_transaction(transaction_type, trace_parent=trace_parent, start=start) | ||
return self.tracer.begin_transaction(transaction_type, trace_parent=trace_parent, start=start, start_timestamp=start_timestamp) |
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.
line too long (139 > 120 characters)
@@ -102,7 +106,7 @@ def start_span( | |||
if parent_context and parent_context.span and not parent_context.span.is_transaction | |||
else None | |||
) | |||
span = transaction._begin_span(operation_name, None, parent_span_id=parent_span_id) | |||
span = transaction._begin_span(operation_name, None, parent_span_id=parent_span_id, start=start_time_monotonic, start_timestamp=start_time) |
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.
line too long (151 > 120 characters)
trace_parent = parent_context.trace_parent if parent_context else None | ||
transaction = self._agent.begin_transaction("custom", trace_parent=trace_parent) | ||
transaction = self._agent.begin_transaction("custom", trace_parent=trace_parent, start=start_time_monotonic, start_timestamp=start_time) |
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.
line too long (148 > 120 characters)
elasticapm/traces.py
Outdated
@@ -123,12 +123,15 @@ def set_failure(self): | |||
|
|||
class Transaction(BaseSpan): | |||
def __init__( | |||
self, tracer, transaction_type="custom", trace_parent=None, is_sampled=True, start=None, sample_rate=None | |||
self, tracer, transaction_type="custom", trace_parent=None, is_sampled=True, start=None, sample_rate=None, start_timestamp=None |
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.
line too long (135 > 120 characters)
0f07ae6
to
5283ce1
Compare
A simple class that makes possible to take a timestamp from one type of clock and convert it to as if it was taken from another type of clock. For example it makes possible to convert timestamps taken from the monotonic clock to representation in terms of the system clock.
OpenTracing API allows to explicitly set start and end timestamps of spans but the implementation in this project does not allow that. That patch fixes it.
5283ce1
to
c6db1a7
Compare
@basepi, @beniwohli, could you please look into it? |
@beniwohli As far as I can tell, the new For my sanity, @AndreiPashkin, can you give me the tl;dr of why that class is necessary? Are we just trying to avoid the unlikely, but possible chance that we could measure the difference between the clocks at the point of a daylight saving change, and thus convert with an hour mistake in the duration? Are there other examples of jumps in non-monotonic clocks that we're trying to detect/prevent? |
Hey @AndreiPashkin -- I'd still like to get this in. I ended up writing a similar (but a bit simpler) timestamp conversion util for some AWS lambda work I was doing. It was just merged in #1366. Can you merge from Thanks! |
Closing this due to lack of reply. |
What does this pull request do?
OpenTracing API allows to explicitly set start and end timestamps of spans but the implementation in this project does not allow that. That patch fixes it.
Closes #1126