-
Notifications
You must be signed in to change notification settings - Fork 0
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
Adopt Sender.append() and flush() #1
Adopt Sender.append() and flush() #1
Conversation
@ProvoK, if you're interested in continuing with these changes, do you mind rebasing your branch to update the dependencies for successful CI runs? |
99b5bd5
to
d43a89e
Compare
@rmfitzpatrick Hello there, thanks for continuing the work! Yes I'm interested, I was a lot busy in the last period, that's why I was not working on it. I'll update my branch and review your change asap 😉 |
8f070d1
to
435b532
Compare
@rmfitzpatrick I've fetched upstream master and merged into my branch. This is all I can do till Monday, sorry! |
b795720
to
ef41bed
Compare
Codecov Report
@@ Coverage Diff @@
## send_spans_over_http #1 +/- ##
========================================================
+ Coverage 94.86% 95.23% +0.36%
========================================================
Files 26 26
Lines 1812 1824 +12
Branches 227 227
========================================================
+ Hits 1719 1737 +18
+ Misses 59 55 -4
+ Partials 34 32 -2
Continue to review full report at Codecov.
|
Signed-off-by: Ryan Fitzpatrick <rmfitzpatrick@signalfx.com>
ef41bed
to
0ac58e8
Compare
jaeger_client/reporter.py
Outdated
@@ -168,14 +160,15 @@ def _report_span_from_ioloop(self, span): | |||
|
|||
@tornado.gen.coroutine | |||
def _consume_queue(self): | |||
spans = [] | |||
spans_appended = 0 |
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.
Keeping the count of an internal state of the sender outside of it doesn't seem to me like a good idea.
It's better that the sender expose a property like spans_count
which returns the real and actual count of its spans.
With that, you can easily get rid of updating this spans_appended
variable (line 183, 187), with a more secure and less error prone behaviour.
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 idea, updated.
jaeger_client/senders.py
Outdated
|
||
raise tornado.gen.Return((num_spans, exc, error_msg)) |
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 very skilled with tornado: is there a valid reason to handle exceptions in this manner?
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 is a special exception that allows coroutines to return values in older versions of python: http://www.tornadoweb.org/en/stable/gen.html#tornado.gen.Return. It's necessary to get the exception info from the send generator.
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.
Ok, I got it. Still I'm not sure this is necessary.
The only return value used is num_spans
, which is everytime equal to sender.span_count
with the actual implementation.
This means that you can simply save a variable here (something like num_spans = self._sender.span_count
) and then use it later for reporting the number of success/error spans.
Everything else (exceptions and theirs messages) can be handled normally, I suppose.
@rmfitzpatrick
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.
Of course, makes more sense to fully adopt span_count and I've updated. However, I did retain the Sender._flush()
generated exception info so that transport-specific exception handling is possible in Sender and its subclasses, without having to maintain a complete, sender-aware try/except block in Reporter._consume_queue()
. Does that work for you, @ProvoK?
jaeger_client/senders.py
Outdated
def send(self, batch): | ||
""" | ||
Send batch of spans out via thrift transport. Any exceptions thrown |
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 docstring does not belongs to this method
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.
Good call. Updated.
def __init__(self, host, port, io_loop=None): | ||
self.host = host | ||
self.port = port | ||
def __init__(self, io_loop=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.
host
and port
are likely to be needed in every sender implementations. I would keep them in the base class
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.
In my early HTTPSender implementation I found only a url is necessary, and constructing one via host, port, and trace endpoint seems overkill (other jaeger clients use JAEGER_ENDPOINT
env var to specify the collector location).
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.
Ok, let's see if jaeger maintainers are ok with this interface
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.
Do you mean before merging into your PR branch?
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.
Nono, I mean after merging in my PR branch. The only one remaining issue is the one related to tornado.gen.Return
, I replied to you there yesterday
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.
Sorry, I missed that comment.
@ProvoK, thanks for the feedback, which I believe I've addressed as requested with the exception of #1 (comment) to match the logic of other clients. Let me know if you still request that change and I'll be happy to do so, or if you have any other notes. |
0b9edef
to
8708e1f
Compare
jaeger_client/reporter.py
Outdated
|
||
if self._sender.span_count: | ||
num_spans = self._sender.span_count | ||
exc, error_msg = yield self._sender.flush() |
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 don't get the benefit of that, honestly. What you are doing now is a try ...except Exception ...
in the Sender.flush()
, returning the exception plus a message. Which is the same as an raise AnyException("message")
In the Reporter
you just check if any kind of exc
is raised, and the use the message returned.
This is the very same of:
try:
yield self._sender.flush()
except Exception as exc:
self.metrics.reporter_failure(num_spans)
self.error_reporter.error(error_msg, exc)
else:
self.metrics.reporter_success(num_spans)
but this is the most common and standard way to deal with exceptions, in Python.
The point is to keep the code "idiomatic".
In other languages, as Go, the standard is to have the pattern you are doing: multiple returns, one for the error/ok-boolean and the other for the "real" value.
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.
Where does error_msg
come from in this excerpt? Providing error_reporter.error()
with str(exc)
and exc
loses the information provided by the initial local-agent submission failure: https://github.com/jaegertracing/jaeger-client-python/blob/master/jaeger_client/reporter.py#L201
This pattern could be repeated with all manner of clients in the future, who idiomatically catch their transport specific exceptions and provide a relevant exception message.
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 was writing in this little github editor so I lost the context
try:
yield self._sender.flush()
except Exception as exc:
self.metrics.reporter_failure(num_spans)
self.error_reporter.error("Failed to submit traces to jaeger: {}".format(exc), exc)
else:
self.metrics.reporter_success(num_spans)
You can still catch below, in the sender, the specific error and provide a relevant message, carried with the exception itself.
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.
Providing a custom message in send()
seems effective. Are you comfortable with using something like six.reraise
to add a custom value with the traceback from sys.exc_info()
?
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 would not add six as dependency just for that. And probably jaeger maitaners wouldn't 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.
It already is one via thrift.
edit: Not to speak in circles, but I'm not aware of a version agnostic way to override an exception value without making Reporter sender detail aware or less informative otherwise.
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.
Oh, didn't know it was included in thrift. Then I suppose it's allright to use it
jaeger_client/senders.py
Outdated
try: | ||
yield self.send(batch) | ||
except Exception as e: | ||
exc = e |
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.
Here you can just raise e("my message") from e
and it's done! (alongwith the previous comment modifications)
The from e
part preserve the exception stacktrace
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.
from e
is not supported in python 2.
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.
Yeah, you're right. I'm too used to python3
jaeger_client/senders.py
Outdated
@@ -81,6 +134,24 @@ def _create_local_agent_channel(self, io_loop): | |||
io_loop=io_loop | |||
) | |||
|
|||
@tornado.gen.coroutine | |||
def _flush(self, spans, process): | |||
exc = 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.
Again here, you can save a lot of lines of code
5e9d687
to
361b5f5
Compare
edit: User error with a stale test. I really appreciate your thorough feedback and believe I've addressed it all, @ProvoK. |
b8a9656
to
29ead94
Compare
Also handle exceptions normally over marshalling as future result. Signed-off-by: Ryan Fitzpatrick <rmfitzpatrick@signalfx.com>
29ead94
to
073d2ba
Compare
Thanks @rmfitzpatrick for your work, I'm going to merge this, and I'll quote in in the original PR. |
Implements the
Sender.append()
andSender.flush()
methods requested in jaegertracing#186 (review) in an attempt to get those changes sourced.Signed-off-by: Ryan Fitzpatrick rmfitzpatrick@signalfx.com