Skip to content
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 support for Python. #32

Merged
merged 46 commits into from
Nov 5, 2017
Merged

Add support for Python. #32

merged 46 commits into from
Nov 5, 2017

Conversation

rnburn
Copy link
Contributor

@rnburn rnburn commented May 9, 2017

This PR adds interceptors to support OpenTracing with Python. Unfortunately, gRPC doesn't provide any direct support for Python interceptors so the PR includes a submodule (grpcext) that implements interceptors on top of gRPC's Channel and Server APIs.

Ryan Burn and others added 30 commits March 9, 2017 00:03
@tedsuo
Copy link
Collaborator

tedsuo commented May 10, 2017

So glad to see Python support coming in. 👍

Copy link
Contributor

@bhs bhs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the insane delay – did not know this was here. :-/

python/README.md Outdated

```python
tracer = # some OpenTracing Tracer instance
interceptor = open_tracing_client_interceptor(tracer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is there this helper function instead of just initializing an OpenTracingClientInterceptor directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was to be consistent with the rest of gRPC where the __init__.py file only exposes interface classes and uses functions to construct concrete classes. (See for example the server function that does the same thing.)

Not entirely sure, but I would guess the reasons for this are to keep the documentation in a single location and to have a convention that allows easily supporting additional constructor functions if needed.

python/README.md Outdated

```python
tracer = # some OpenTracing Tracer instance
interceptor = open_tracing_server_interceptor(tracer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same)


### Server-side usage example

```python
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's include import statements in these two examples

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added import statements.


## Usage
```
python integration_server.py --access_token `lightstep-access-token` &
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be better to support Jaeger's (OSS) library here... it can run in a single local docker image.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Will switch the examples to use Jaeger.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the examples use Jaeger now.


## Usage
```
python store_server.py --access_token `lightstep-access-token` &
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same comment about Jaeger)

import argparse

import grpc
from jaeger_client import Config
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't some sort of dependency need to be added to setup.py or similar for this to work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a requirements.txt file in the example directory that includes jaeger-client as an dependency.

# updates the span accordingly.
def _check_error_code(span, servicer_context):
if servicer_context.code != grpc.StatusCode.OK:
span.set_tag('error', True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed to use the constants in opentracing.ext.tags available in opentracing-1.2.2, but tags.ERROR was added for opentracing-1.2.3 which hasn't been released yet.

"""Creates a service-side interceptor that can be use with gRPC to add
OpenTracing information.

Args:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing a comment for traced_attributes

def open_tracing_client_interceptor(tracer,
active_span_source=None,
log_payloads=False,
traced_attributes=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no comment provided for this param

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tracer_attributes is documented now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thinking more deeply about this, IMO it might be better to express this functionality as a SpanDecorator function that gives the caller the flexibility to modify the RPC Span in any way (and provides RPC context information like headers, method type/name, deadline, etc in the decorator function arguments somehow).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I'll make that change. It was mostly done this way just to match the Java version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the traced_attributes options and added a span_decorator that can be used instead.

@wkiser
Copy link

wkiser commented Jun 19, 2017

How would you suggest integrating this with https://github.com/uber-common/opentracing-python-instrumentation?

Right now I am doing something like this (to get redis and sqlalchemy in the trace):

from opentracing_instrumentation.request_context import RequestContextManager
...
class CommandLine(command_line_pb2.CommandLineServicer):
    def Echo(self, request, context):
        with RequestContextManager(span=context.get_active_span()):
            _check_redis_cache()
            _make_db_query()
            return command_line_pb2.CommandResponse(text=request.text)

But I feel like there is a better solution.

@rnburn
Copy link
Contributor Author

rnburn commented Jun 19, 2017

@wkiser There is a PR being worked on to add active span management to the Python OpenTracing API. Once that's in place, I'd expect the code to be updated to make use of it and in-process propagation between different frameworks would hopefully be more seamless. But I'm not sure what could be improved until that's done.

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again.

@evanj
Copy link

evanj commented Aug 11, 2017

Thanks for this! I totally stole the server interceptor and used it for an unrelated reason. Well, it is actually slightly related: I just want to log start/end of requests for debugging purposes. This is an extremely lightweight version of tracing :) worked like a charm. Looking forward to something like this landing in grpc proper.

@lapointexavier
Copy link

@rnburn out of curiosity, is there a timeline for when that PR would get merged (are there dependencies / blockers)?

@tedsuo
Copy link
Collaborator

tedsuo commented Sep 22, 2017

@lapointexavier we were hoping that grpc would add python interceptors so that we wouldn't have to mutate the grpc objects. Given that that is in limbo, we should probably merge this.

@lapointexavier
Copy link

@rnburn @tedsuo My apologies, just wondering if this is still something that would get merged eventually? I'm working off a hand generated wheel, but it'd be nice to make it official, if it's in the plans.

@rnburn
Copy link
Contributor Author

rnburn commented Nov 3, 2017

I think @bhs is the only one with write access to merge this -- were there any other concerns?

@wkiser
Copy link

wkiser commented Nov 4, 2017

I think people might be waiting on the PR for interceptors in gRPC to get merged.

That being said, I wouldn't mind this getting merged in the meantime since I am also running off of a hand generated wheel.

@rnburn
Copy link
Contributor Author

rnburn commented Nov 4, 2017

I don't see any reason not to ship what we have and add support for gRPC's own interceptor's in a later version.

Even if that PR were to move today (which it won't), it would take a while for those changes to roll out to the various gRPC packages that most people are using, so having a version of this that can work with older version of gRPC makes a lot of sense to me.

Copy link
Contributor

@bhs bhs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging seems like a definite improvement over non-merging. :) Looking forward to a core GRPC API that makes interceptors cleaner in python, though. Thanks!

@bhs bhs merged commit 01f8541 into grpc-ecosystem:master Nov 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants