From 71ce915b8ff2e411e71348b4fd3f1a9297571d1a Mon Sep 17 00:00:00 2001 From: aravins Date: Fri, 5 Jun 2020 19:50:43 -0400 Subject: [PATCH 01/22] adding instrumentors to grpc autoinstrumentor --- ext/opentelemetry-ext-grpc/setup.cfg | 3 ++ .../src/opentelemetry/ext/grpc/__init__.py | 44 ++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/ext/opentelemetry-ext-grpc/setup.cfg b/ext/opentelemetry-ext-grpc/setup.cfg index a45ee3c6473..b2c7cc3203a 100644 --- a/ext/opentelemetry-ext-grpc/setup.cfg +++ b/ext/opentelemetry-ext-grpc/setup.cfg @@ -50,3 +50,6 @@ test = [options.packages.find] where = src + +opentelemetry_instrumentor = +grpc = opentelemetry.ext.grpc:GrpcInstrumentor diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 0e9b19ef51b..8f2ee896a41 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -16,9 +16,51 @@ # pylint:disable=import-self # pylint:disable=no-name-in-module # pylint:disable=relative-beyond-top-level - +import grpc from opentelemetry import trace from opentelemetry.ext.grpc.version import __version__ +from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.trace import get_tracer +from wrapt import ObjectProxy +from wrapt import wrap_function_wrapper as _wrap + +class GrpcInstrumentorServer (BaseInstrumentor): + + def _instrument(self, **kwargs): + tracer = self.get_trace(kwargs) + _wrap(grpc,'server', server_interceptor(tracer_provider = get_tracer_provider(kwargs))) + _wrap(grpc, 'secure_channel',server_interceptor(tracer_provider= get_tracer_provider(kwargs))) + + + + def _uninstrument(self, **kwargs): + _unwrap(grpc, 'server') + + + +class GrpcInstrumeentorClient (BaseInstrumentor): + + def _instrument(self, **kwargs): + tracer = self.get_trace(kwargs) + _wrap(grpc,'insecure_channel', client_interceptor(tracer_provider = get_tracer_provider(kwargs))) + _wrap(grpc, 'secure_channel',client_interceptor(tracer_provider= get_tracer_provider(kwargs))) + + + + + def _uninstrument(self, **kwargs): + + _unwrap(grpc, 'secure_channel') + _unwrap(grpc, 'insecure_channel') + +def _unwrap(obj, attr): + func = getattr(obj,attr, None) + + if func and isinstance(func, ObjectProxy) and hasattr(func,"__wrapped__"): + setattr(obj,attr,func.__wrapped__) + +def get_tracer_provider (**kwargs): + return kwargs.get("tracer_provider") def client_interceptor(tracer_provider=None): From 17741abadc9ee2e229f3ce250fd06e604cb11980 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Mon, 8 Jun 2020 15:13:13 +0000 Subject: [PATCH 02/22] adding grpc instrumentor class --- .../src/opentelemetry/ext/grpc/__init__.py | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 8f2ee896a41..1e187913a0e 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -24,43 +24,41 @@ from wrapt import ObjectProxy from wrapt import wrap_function_wrapper as _wrap -class GrpcInstrumentorServer (BaseInstrumentor): + + +class GrpcInstrumentorServer(BaseInstrumentor): def _instrument(self, **kwargs): - tracer = self.get_trace(kwargs) - _wrap(grpc,'server', server_interceptor(tracer_provider = get_tracer_provider(kwargs))) - _wrap(grpc, 'secure_channel',server_interceptor(tracer_provider= get_tracer_provider(kwargs))) + # tracer = self.get_trace(kwargs) - + _wrap(grpc, 'server', server_interceptor(tracer_provider=get_tracer_provider(**kwargs))) + _wrap(grpc, 'secure_channel', server_interceptor(tracer_provider=get_tracer_provider(**kwargs))) def _uninstrument(self, **kwargs): _unwrap(grpc, 'server') - -class GrpcInstrumeentorClient (BaseInstrumentor): +class GrpcInstrumentorClient(BaseInstrumentor): def _instrument(self, **kwargs): - tracer = self.get_trace(kwargs) - _wrap(grpc,'insecure_channel', client_interceptor(tracer_provider = get_tracer_provider(kwargs))) - _wrap(grpc, 'secure_channel',client_interceptor(tracer_provider= get_tracer_provider(kwargs))) - - - + # tracer = get_tracer_provider(kwargs) + _wrap(grpc, 'insecure_channel', client_interceptor(tracer_provider=get_tracer_provider(**kwargs))) + _wrap(grpc, 'secure_channel', client_interceptor(tracer_provider=get_tracer_provider(**kwargs))) def _uninstrument(self, **kwargs): - _unwrap(grpc, 'secure_channel') _unwrap(grpc, 'insecure_channel') + def _unwrap(obj, attr): - func = getattr(obj,attr, None) + func = getattr(obj, attr, None) + + if func and isinstance(func, ObjectProxy) and hasattr(func, "__wrapped__"): + setattr(obj, attr, func.__wrapped__) - if func and isinstance(func, ObjectProxy) and hasattr(func,"__wrapped__"): - setattr(obj,attr,func.__wrapped__) -def get_tracer_provider (**kwargs): - return kwargs.get("tracer_provider") +def get_tracer_provider(**kwargs): + return kwargs.get("tracer_provider") def client_interceptor(tracer_provider=None): From eebd8fd0da3957069a1fda24be8949f15b5c2960 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Fri, 12 Jun 2020 03:59:21 +0000 Subject: [PATCH 03/22] adding grpc integration --- .../src/opentelemetry/ext/grpc/__init__.py | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 1e187913a0e..3b8f5963aca 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -16,49 +16,70 @@ # pylint:disable=import-self # pylint:disable=no-name-in-module # pylint:disable=relative-beyond-top-level +from contextlib import contextmanager + import grpc +from concurrent import futures from opentelemetry import trace from opentelemetry.ext.grpc.version import __version__ +from opentelemetry.sdk.trace import TracerProvider from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor from opentelemetry.trace import get_tracer from wrapt import ObjectProxy from wrapt import wrap_function_wrapper as _wrap +from opentelemetry.ext.grpc.grpcext import intercept_channel, intercept_server +import pdb +from opentelemetry.sdk.trace.export import ( + ConsoleSpanExporter, + SimpleExportSpanProcessor, +) class GrpcInstrumentorServer(BaseInstrumentor): + trace.set_tracer_provider(TracerProvider()) + tracer = trace.get_tracer_provider() + server = None def _instrument(self, **kwargs): - # tracer = self.get_trace(kwargs) - - _wrap(grpc, 'server', server_interceptor(tracer_provider=get_tracer_provider(**kwargs))) - _wrap(grpc, 'secure_channel', server_interceptor(tracer_provider=get_tracer_provider(**kwargs))) + self.server = grpc.server(futures.ThreadPoolExecutor()) + self.server = intercept_server(self.server, server_interceptor()) def _uninstrument(self, **kwargs): - _unwrap(grpc, 'server') + if hasattr(self.server, 'stop'): + return self.server.stop(kwargs.get('grace')) class GrpcInstrumentorClient(BaseInstrumentor): + trace.set_tracer_provider(TracerProvider()) + tracer = trace.get_tracer_provider() + channel = None def _instrument(self, **kwargs): - # tracer = get_tracer_provider(kwargs) - _wrap(grpc, 'insecure_channel', client_interceptor(tracer_provider=get_tracer_provider(**kwargs))) - _wrap(grpc, 'secure_channel', client_interceptor(tracer_provider=get_tracer_provider(**kwargs))) + hostport = kwargs.get('hostport') + + if kwargs.get('channel_type') == 'secure': + self.channel = secure_channel_wrapper(hostport, kwargs.get("credentials")) + + else: + self.channel = insecure_channel_wrapper(hostport) def _uninstrument(self, **kwargs): - _unwrap(grpc, 'secure_channel') - _unwrap(grpc, 'insecure_channel') + if hasattr(self.channel, 'close'): + return self.channel.close() -def _unwrap(obj, attr): - func = getattr(obj, attr, None) - if func and isinstance(func, ObjectProxy) and hasattr(func, "__wrapped__"): - setattr(obj, attr, func.__wrapped__) +@contextmanager +def insecure_channel_wrapper(hostport): + with grpc.insecure_channel(hostport) as channel: + yield intercept_channel(channel, client_interceptor()) -def get_tracer_provider(**kwargs): - return kwargs.get("tracer_provider") +@contextmanager +def secure_channel_wrapper(hostport, credentials): + with grpc.secure_channel(hostport, credentials) as channel: + yield intercept_channel(channel, client_interceptor()) def client_interceptor(tracer_provider=None): From 7785468792de9ef1cdad9f2b3b37d7b03f1099fe Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Mon, 15 Jun 2020 21:19:31 +0000 Subject: [PATCH 04/22] writing tests to test grpc integration --- .../tests/test_server_interceptor.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 6c055c863c2..ef42b2299fa 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -26,6 +26,8 @@ from opentelemetry.ext.grpc.grpcext import intercept_server from opentelemetry.sdk import trace as trace_sdk from opentelemetry.test.test_base import TestBase +from opentelemetry.ext.grpc import GrpcInstrumentorServer, GrpcInstrumentorClient + class UnaryUnaryMethodHandler(grpc.RpcMethodHandler): @@ -49,6 +51,51 @@ def service(self, handler_call_details): class TestOpenTelemetryServerInterceptor(TestBase): + + def test_instrumentor(self): + # Intercept gRPC calls... + #interceptor = server_interceptor() + + def handler(request, context): + return b"" + + #server = grpc.server( + # futures.ThreadPoolExecutor(max_workers=1), + # options=(("grpc.so_reuseport", 0),), + #) + # FIXME: grpcext interceptor doesn't apply to handlers passed to server + # init, should use intercept_service API instead. + #server = intercept_server(server, interceptor) + + grpc_server_instrumentor = GrpcInstrumentorServer() + grpc_server_instrumentor.instrument() + + server = grpc_server_instrumentor.server + + server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) + + port = server.add_insecure_port("[::]:0") + grpc_client_instrumentor = GrpcInstrumentorClient() + grpc_client_instrumentor.instrument(hostport=port) + channel = grpc.insecure_channel("localhost:{:d}".format(port)) + + try: + server.start() + channel.unary_unary("")(b"") + finally: + server.stop(None) + + spans_list = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans_list), 1) + span = spans_list[0] + + self.assertEqual(span.name, "") + self.assertIs(span.kind, trace.SpanKind.SERVER) + + # Check version and name in span's instrumentation info + self.check_span_instrumentation_info(span, opentelemetry.ext.grpc) + + def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" From 3a51c6e6ec19ef073547a15cd34878f1fc5da0c5 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Tue, 16 Jun 2020 18:38:51 +0000 Subject: [PATCH 05/22] code clean up --- .../tests/test_server_interceptor.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index ef42b2299fa..318d94b49f1 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -53,20 +53,10 @@ def service(self, handler_call_details): class TestOpenTelemetryServerInterceptor(TestBase): def test_instrumentor(self): - # Intercept gRPC calls... - #interceptor = server_interceptor() def handler(request, context): return b"" - #server = grpc.server( - # futures.ThreadPoolExecutor(max_workers=1), - # options=(("grpc.so_reuseport", 0),), - #) - # FIXME: grpcext interceptor doesn't apply to handlers passed to server - # init, should use intercept_service API instead. - #server = intercept_server(server, interceptor) - grpc_server_instrumentor = GrpcInstrumentorServer() grpc_server_instrumentor.instrument() @@ -91,8 +81,6 @@ def handler(request, context): self.assertEqual(span.name, "") self.assertIs(span.kind, trace.SpanKind.SERVER) - - # Check version and name in span's instrumentation info self.check_span_instrumentation_info(span, opentelemetry.ext.grpc) From 816477986476fac54f34ff16f28fd1fff733d5af Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Wed, 17 Jun 2020 14:00:27 +0000 Subject: [PATCH 06/22] makng requested review changes --- .../src/opentelemetry/ext/grpc/__init__.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 3b8f5963aca..6c11487d628 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -24,17 +24,8 @@ from opentelemetry.ext.grpc.version import __version__ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor -from opentelemetry.trace import get_tracer -from wrapt import ObjectProxy -from wrapt import wrap_function_wrapper as _wrap from opentelemetry.ext.grpc.grpcext import intercept_channel, intercept_server -import pdb -from opentelemetry.sdk.trace.export import ( - ConsoleSpanExporter, - SimpleExportSpanProcessor, -) - class GrpcInstrumentorServer(BaseInstrumentor): trace.set_tracer_provider(TracerProvider()) @@ -65,7 +56,6 @@ def _instrument(self, **kwargs): self.channel = insecure_channel_wrapper(hostport) def _uninstrument(self, **kwargs): - if hasattr(self.channel, 'close'): return self.channel.close() From 10393ba1d26e3cf2f809485cfec51607097dd7b9 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Wed, 17 Jun 2020 19:17:06 +0000 Subject: [PATCH 07/22] fixing lint issue --- .../src/opentelemetry/ext/grpc/__init__.py | 14 ++++++++------ .../tests/test_server_interceptor.py | 9 ++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 6c11487d628..9c347a30573 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -37,8 +37,8 @@ def _instrument(self, **kwargs): self.server = intercept_server(self.server, server_interceptor()) def _uninstrument(self, **kwargs): - if hasattr(self.server, 'stop'): - return self.server.stop(kwargs.get('grace')) + if hasattr(self.server, "stop"): + return self.server.stop(kwargs.get("grace")) class GrpcInstrumentorClient(BaseInstrumentor): @@ -47,16 +47,18 @@ class GrpcInstrumentorClient(BaseInstrumentor): channel = None def _instrument(self, **kwargs): - hostport = kwargs.get('hostport') + hostport = kwargs.get("hostport") - if kwargs.get('channel_type') == 'secure': - self.channel = secure_channel_wrapper(hostport, kwargs.get("credentials")) + if kwargs.get("channel_type") == "secure": + self.channel = secure_channel_wrapper( + hostport, kwargs.get("credentials") + ) else: self.channel = insecure_channel_wrapper(hostport) def _uninstrument(self, **kwargs): - if hasattr(self.channel, 'close'): + if hasattr(self.channel, "close"): return self.channel.close() diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index d09cb010eb8..3065fa1ff29 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -26,8 +26,10 @@ from opentelemetry.ext.grpc.grpcext import intercept_server from opentelemetry.sdk import trace as trace_sdk from opentelemetry.test.test_base import TestBase -from opentelemetry.ext.grpc import GrpcInstrumentorServer, GrpcInstrumentorClient - +from opentelemetry.ext.grpc import ( + GrpcInstrumentorServer, + GrpcInstrumentorClient, +) class UnaryUnaryMethodHandler(grpc.RpcMethodHandler): @@ -51,9 +53,7 @@ def service(self, handler_call_details): class TestOpenTelemetryServerInterceptor(TestBase): - def test_instrumentor(self): - def handler(request, context): return b"" @@ -83,7 +83,6 @@ def handler(request, context): self.assertIs(span.kind, trace.SpanKind.SERVER) self.check_span_instrumentation_info(span, opentelemetry.ext.grpc) - def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" From 7a6da4a46d95824592c26e9f73ada887e40ea7df Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Wed, 17 Jun 2020 19:40:33 -0400 Subject: [PATCH 08/22] applying tox changes --- .../src/opentelemetry/ext/grpc/__init__.py | 7 ++++--- .../tests/test_server_interceptor.py | 10 +++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 9c347a30573..5069d33fce0 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -14,17 +14,18 @@ # pylint:disable=import-outside-toplevel # pylint:disable=import-self +from concurrent import futures # pylint:disable=no-name-in-module # pylint:disable=relative-beyond-top-level from contextlib import contextmanager import grpc -from concurrent import futures + from opentelemetry import trace -from opentelemetry.ext.grpc.version import __version__ -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor from opentelemetry.ext.grpc.grpcext import intercept_channel, intercept_server +from opentelemetry.ext.grpc.version import __version__ +from opentelemetry.sdk.trace import TracerProvider class GrpcInstrumentorServer(BaseInstrumentor): diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 3065fa1ff29..eeacd50eb9c 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -22,14 +22,14 @@ import opentelemetry.ext.grpc from opentelemetry import trace -from opentelemetry.ext.grpc import server_interceptor -from opentelemetry.ext.grpc.grpcext import intercept_server -from opentelemetry.sdk import trace as trace_sdk -from opentelemetry.test.test_base import TestBase from opentelemetry.ext.grpc import ( - GrpcInstrumentorServer, GrpcInstrumentorClient, + GrpcInstrumentorServer, + server_interceptor, ) +from opentelemetry.ext.grpc.grpcext import intercept_server +from opentelemetry.sdk import trace as trace_sdk +from opentelemetry.test.test_base import TestBase class UnaryUnaryMethodHandler(grpc.RpcMethodHandler): From f44eeba808200d0fa084e734fd94d0a3e0bb5c07 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Fri, 19 Jun 2020 17:13:57 +0000 Subject: [PATCH 09/22] wrapping server and chnnel calls --- .../src/opentelemetry/ext/grpc/__init__.py | 62 +++++++++---------- .../tests/test_server_interceptor.py | 11 +++- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 9c347a30573..b8f66b3ebdd 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -12,66 +12,62 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint:disable=import-outside-toplevel -# pylint:disable=import-self + + # pylint:disable=no-name-in-module # pylint:disable=relative-beyond-top-level from contextlib import contextmanager -import grpc -from concurrent import futures +from wrapt import wrap_function_wrapper as _wrap + +# pylint:disable=import-outside-toplevel +# pylint:disable=import-self from opentelemetry import trace -from opentelemetry.ext.grpc.version import __version__ -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor from opentelemetry.ext.grpc.grpcext import intercept_channel, intercept_server +from opentelemetry.ext.grpc.version import __version__ +from opentelemetry.instrumentation.utils import unwrap class GrpcInstrumentorServer(BaseInstrumentor): - trace.set_tracer_provider(TracerProvider()) - tracer = trace.get_tracer_provider() - server = None + def __init__(self): + self.server = None def _instrument(self, **kwargs): - self.server = grpc.server(futures.ThreadPoolExecutor()) - self.server = intercept_server(self.server, server_interceptor()) + _wrap("grpc", "server", self.wrapper_fn) def _uninstrument(self, **kwargs): - if hasattr(self.server, "stop"): - return self.server.stop(kwargs.get("grace")) + unwrap("grpc", "server") + + def wrapper_fn(self, original_func, instance, args, kwargs): + self.server = original_func(*args, **kwargs) + self.server = intercept_server(self.server, server_interceptor()) class GrpcInstrumentorClient(BaseInstrumentor): - trace.set_tracer_provider(TracerProvider()) - tracer = trace.get_tracer_provider() - channel = None + def __init__(self): + self.channel = None def _instrument(self, **kwargs): - hostport = kwargs.get("hostport") if kwargs.get("channel_type") == "secure": - self.channel = secure_channel_wrapper( - hostport, kwargs.get("credentials") - ) + _wrap("grpc", "secure_channel", self.wrapper_fn) else: - self.channel = insecure_channel_wrapper(hostport) + _wrap("grpc", "insecure_channel", self.wrapper_fn) def _uninstrument(self, **kwargs): - if hasattr(self.channel, "close"): - return self.channel.close() - - -@contextmanager -def insecure_channel_wrapper(hostport): - with grpc.insecure_channel(hostport) as channel: - yield intercept_channel(channel, client_interceptor()) + if kwargs.get("channel_type") == "secure": + unwrap("grpc", "secure_channel") + else: + unwrap("grpc", "insecure_channel") -@contextmanager -def secure_channel_wrapper(hostport, credentials): - with grpc.secure_channel(hostport, credentials) as channel: - yield intercept_channel(channel, client_interceptor()) + @contextmanager + def wrapper_fn(self, original_func, instance, args, kwargs): + with original_func(*args, **kwargs) as channel: + self.channel = intercept_channel(channel, client_interceptor()) + yield self.channel def client_interceptor(tracer_provider=None): diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 3065fa1ff29..9122fba9822 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -60,13 +60,18 @@ def handler(request, context): grpc_server_instrumentor = GrpcInstrumentorServer() grpc_server_instrumentor.instrument() + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=1), + options=(("grpc.so_reuseport", 0),), + ) + server = grpc_server_instrumentor.server server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) port = server.add_insecure_port("[::]:0") - grpc_client_instrumentor = GrpcInstrumentorClient() - grpc_client_instrumentor.instrument(hostport=port) + #grpc_client_instrumentor = GrpcInstrumentorClient() + #grpc_client_instrumentor.instrument(hostport=port) channel = grpc.insecure_channel("localhost:{:d}".format(port)) try: @@ -82,6 +87,8 @@ def handler(request, context): self.assertEqual(span.name, "") self.assertIs(span.kind, trace.SpanKind.SERVER) self.check_span_instrumentation_info(span, opentelemetry.ext.grpc) + grpc_server_instrumentor.uninstrument() + def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" From ff1dfb249c372d5a91e2333b5566b7e0d01ee232 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Sun, 21 Jun 2020 16:43:29 -0400 Subject: [PATCH 10/22] fixing tox issues --- .../src/opentelemetry/ext/grpc/__init__.py | 3 ++- ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index cabbe3e9a32..50aaa5eec54 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -19,7 +19,9 @@ # pylint:disable=no-name-in-module # pylint:disable=relative-beyond-top-level from contextlib import contextmanager + from wrapt import wrap_function_wrapper as _wrap + from opentelemetry import trace from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor from opentelemetry.ext.grpc.grpcext import intercept_channel, intercept_server @@ -27,7 +29,6 @@ from opentelemetry.instrumentation.utils import unwrap - class GrpcInstrumentorServer(BaseInstrumentor): def __init__(self): self.server = None diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index d6a761886ad..42dd8dd9d8c 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -70,8 +70,8 @@ def handler(request, context): server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) port = server.add_insecure_port("[::]:0") - #grpc_client_instrumentor = GrpcInstrumentorClient() - #grpc_client_instrumentor.instrument(hostport=port) + # grpc_client_instrumentor = GrpcInstrumentorClient() + # grpc_client_instrumentor.instrument(hostport=port) channel = grpc.insecure_channel("localhost:{:d}".format(port)) try: @@ -89,7 +89,6 @@ def handler(request, context): self.check_span_instrumentation_info(span, opentelemetry.ext.grpc) grpc_server_instrumentor.uninstrument() - def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" From 50c8bc05fafe31a04ab90288acd0e11c260f263b Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Tue, 23 Jun 2020 16:09:44 +0000 Subject: [PATCH 11/22] fixing lint issues --- .../src/opentelemetry/ext/grpc/__init__.py | 3 ++- ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index cabbe3e9a32..50aaa5eec54 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -19,7 +19,9 @@ # pylint:disable=no-name-in-module # pylint:disable=relative-beyond-top-level from contextlib import contextmanager + from wrapt import wrap_function_wrapper as _wrap + from opentelemetry import trace from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor from opentelemetry.ext.grpc.grpcext import intercept_channel, intercept_server @@ -27,7 +29,6 @@ from opentelemetry.instrumentation.utils import unwrap - class GrpcInstrumentorServer(BaseInstrumentor): def __init__(self): self.server = None diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index d6a761886ad..42dd8dd9d8c 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -70,8 +70,8 @@ def handler(request, context): server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) port = server.add_insecure_port("[::]:0") - #grpc_client_instrumentor = GrpcInstrumentorClient() - #grpc_client_instrumentor.instrument(hostport=port) + # grpc_client_instrumentor = GrpcInstrumentorClient() + # grpc_client_instrumentor.instrument(hostport=port) channel = grpc.insecure_channel("localhost:{:d}".format(port)) try: @@ -89,7 +89,6 @@ def handler(request, context): self.check_span_instrumentation_info(span, opentelemetry.ext.grpc) grpc_server_instrumentor.uninstrument() - def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" From 687bf8a6489b92bd3d076d82fb2d337e589f22e9 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Tue, 23 Jun 2020 12:29:43 -0400 Subject: [PATCH 12/22] fixing linter issue --- .../src/opentelemetry/ext/grpc/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 50aaa5eec54..da1f3e3f430 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -16,6 +16,7 @@ # pylint:disable=import-outside-toplevel # pylint:disable=import-self from concurrent import futures + # pylint:disable=no-name-in-module # pylint:disable=relative-beyond-top-level from contextlib import contextmanager From 750964b978432f7625f14e593107fe83c2575498 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Thu, 25 Jun 2020 09:14:31 -0400 Subject: [PATCH 13/22] making lint modifications --- .../src/opentelemetry/ext/grpc/__init__.py | 8 +++++--- .../tests/test_server_interceptor.py | 6 +----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index da1f3e3f430..ebe017306b7 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -15,10 +15,12 @@ # pylint:disable=import-outside-toplevel # pylint:disable=import-self -from concurrent import futures +from concurrent import futures # isort:skip # pylint:disable=no-name-in-module # pylint:disable=relative-beyond-top-level +# pylint:disable=import-error +# pylint:disable=no-self-use from contextlib import contextmanager from wrapt import wrap_function_wrapper as _wrap @@ -40,7 +42,7 @@ def _instrument(self, **kwargs): def _uninstrument(self, **kwargs): unwrap("grpc", "server") - def wrapper_fn(self, original_func, instance, args, kwargs): + def wrapper_fn(self, original_func, args, kwargs): self.server = original_func(*args, **kwargs) self.server = intercept_server(self.server, server_interceptor()) @@ -65,7 +67,7 @@ def _uninstrument(self, **kwargs): unwrap("grpc", "insecure_channel") @contextmanager - def wrapper_fn(self, original_func, instance, args, kwargs): + def wrapper_fn(self, original_func, args, kwargs): with original_func(*args, **kwargs) as channel: self.channel = intercept_channel(channel, client_interceptor()) yield self.channel diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 42dd8dd9d8c..e2a5d2ed3df 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -22,11 +22,7 @@ import opentelemetry.ext.grpc from opentelemetry import trace -from opentelemetry.ext.grpc import ( - GrpcInstrumentorClient, - GrpcInstrumentorServer, - server_interceptor, -) +from opentelemetry.ext.grpc import GrpcInstrumentorServer, server_interceptor from opentelemetry.ext.grpc.grpcext import intercept_server from opentelemetry.sdk import trace as trace_sdk from opentelemetry.test.test_base import TestBase From 125429bfc4c16e496026455c7f1e31459f4ee04e Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Thu, 25 Jun 2020 11:24:41 -0400 Subject: [PATCH 14/22] fixing build issue --- .../src/opentelemetry/ext/grpc/__init__.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index ebe017306b7..def5ea8c7b8 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -12,17 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. - -# pylint:disable=import-outside-toplevel -# pylint:disable=import-self -from concurrent import futures # isort:skip - # pylint:disable=no-name-in-module # pylint:disable=relative-beyond-top-level # pylint:disable=import-error # pylint:disable=no-self-use from contextlib import contextmanager +import grpc from wrapt import wrap_function_wrapper as _wrap from opentelemetry import trace @@ -31,6 +27,10 @@ from opentelemetry.ext.grpc.version import __version__ from opentelemetry.instrumentation.utils import unwrap +# pylint:disable=import-outside-toplevel +# pylint:disable=import-self +from concurrent import futures # isort:skip + class GrpcInstrumentorServer(BaseInstrumentor): def __init__(self): @@ -40,7 +40,7 @@ def _instrument(self, **kwargs): _wrap("grpc", "server", self.wrapper_fn) def _uninstrument(self, **kwargs): - unwrap("grpc", "server") + unwrap(grpc, "server") def wrapper_fn(self, original_func, args, kwargs): self.server = original_func(*args, **kwargs) @@ -61,10 +61,10 @@ def _instrument(self, **kwargs): def _uninstrument(self, **kwargs): if kwargs.get("channel_type") == "secure": - unwrap("grpc", "secure_channel") + unwrap(grpc, "secure_channel") else: - unwrap("grpc", "insecure_channel") + unwrap(grpc, "insecure_channel") @contextmanager def wrapper_fn(self, original_func, args, kwargs): From 8b0e5cf77570458eedb1bf0db465da3b07a80feb Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Fri, 17 Jul 2020 16:15:41 -0400 Subject: [PATCH 15/22] fixing issues with number of paramters --- .../src/opentelemetry/ext/grpc/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index def5ea8c7b8..576b2ee5f1f 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -22,13 +22,14 @@ from wrapt import wrap_function_wrapper as _wrap from opentelemetry import trace -from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor from opentelemetry.ext.grpc.grpcext import intercept_channel, intercept_server from opentelemetry.ext.grpc.version import __version__ +from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import unwrap # pylint:disable=import-outside-toplevel # pylint:disable=import-self +# pylint:disable=unused-argument from concurrent import futures # isort:skip @@ -42,7 +43,7 @@ def _instrument(self, **kwargs): def _uninstrument(self, **kwargs): unwrap(grpc, "server") - def wrapper_fn(self, original_func, args, kwargs): + def wrapper_fn(self, original_func, instance, args, kwargs): self.server = original_func(*args, **kwargs) self.server = intercept_server(self.server, server_interceptor()) @@ -67,7 +68,7 @@ def _uninstrument(self, **kwargs): unwrap(grpc, "insecure_channel") @contextmanager - def wrapper_fn(self, original_func, args, kwargs): + def wrapper_fn(self, original_func, instance, args, kwargs): with original_func(*args, **kwargs) as channel: self.channel = intercept_channel(channel, client_interceptor()) yield self.channel From 0b2ab9904cdbee7ddc94fd48ffab09b854aa9278 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Sat, 18 Jul 2020 17:34:14 -0400 Subject: [PATCH 16/22] fixing suggested changes --- ext/opentelemetry-ext-grpc/setup.cfg | 7 +++++-- .../src/opentelemetry/ext/grpc/__init__.py | 2 +- .../tests/test_server_interceptor.py | 1 - 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/setup.cfg b/ext/opentelemetry-ext-grpc/setup.cfg index bd7775f2a60..643f0387c42 100644 --- a/ext/opentelemetry-ext-grpc/setup.cfg +++ b/ext/opentelemetry-ext-grpc/setup.cfg @@ -52,5 +52,8 @@ test = [options.packages.find] where = src -opentelemetry_instrumentor = -grpc = opentelemetry.ext.grpc:GrpcInstrumentor +opentelemetry_instrumentor_client = + grpc = opentelemetry.ext.grpc:GrpcInstrumentorClient + +opentelemetry_instrumentor_server = + grpc = opentelemetry.ext.grpc:GrpcInstrumentorServer diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 576b2ee5f1f..d435a7bba1e 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -30,7 +30,7 @@ # pylint:disable=import-outside-toplevel # pylint:disable=import-self # pylint:disable=unused-argument -from concurrent import futures # isort:skip +# isort:skip class GrpcInstrumentorServer(BaseInstrumentor): diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index e8e1d28ae6f..3cb1d21289b 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -79,7 +79,6 @@ def handler(request, context): spans_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans_list), 1) span = spans_list[0] - self.assertEqual(span.name, "") self.assertIs(span.kind, trace.SpanKind.SERVER) self.check_span_instrumentation_info(span, opentelemetry.ext.grpc) From 02cfe04f231cd9970925552ee48ad0a43ded0e78 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Mon, 20 Jul 2020 14:20:48 -0400 Subject: [PATCH 17/22] adding changes to changelog --- ext/opentelemetry-ext-grpc/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/opentelemetry-ext-grpc/CHANGELOG.md b/ext/opentelemetry-ext-grpc/CHANGELOG.md index 3be32e05e59..4221ab53710 100644 --- a/ext/opentelemetry-ext-grpc/CHANGELOG.md +++ b/ext/opentelemetry-ext-grpc/CHANGELOG.md @@ -4,6 +4,8 @@ - Add status code to gRPC client spans ([896](https://github.com/open-telemetry/opentelemetry-python/pull/896)) +- Add gRPC client and server instrumentors + ([788](https://github.com/open-telemetry/opentelemetry-python/pull/788)) ## 0.8b0 From a31d51d5fea5ca9095dedb181f0defd5d18ba7ba Mon Sep 17 00:00:00 2001 From: Aravin <34178459+aravinsiva@users.noreply.github.com> Date: Mon, 20 Jul 2020 16:18:51 -0400 Subject: [PATCH 18/22] Update ext/opentelemetry-ext-grpc/setup.cfg Co-authored-by: alrex --- ext/opentelemetry-ext-grpc/setup.cfg | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/setup.cfg b/ext/opentelemetry-ext-grpc/setup.cfg index 643f0387c42..dd296032475 100644 --- a/ext/opentelemetry-ext-grpc/setup.cfg +++ b/ext/opentelemetry-ext-grpc/setup.cfg @@ -52,8 +52,7 @@ test = [options.packages.find] where = src -opentelemetry_instrumentor_client = - grpc = opentelemetry.ext.grpc:GrpcInstrumentorClient - -opentelemetry_instrumentor_server = - grpc = opentelemetry.ext.grpc:GrpcInstrumentorServer +[options.entry_points] +opentelemetry_instrumentor = + grpc_client = opentelemetry.ext.grpc:GrpcInstrumentorClient + grpc_server = opentelemetry.ext.grpc:GrpcInstrumentorServer From 6ceadd9e6abf699aa258cb25cb851b5e7df3f14a Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Tue, 21 Jul 2020 15:41:40 -0400 Subject: [PATCH 19/22] adding example code, removing self.server and self.channel as well as modifying test case as per Shawn suggestion --- .../src/opentelemetry/ext/grpc/__init__.py | 106 ++++++++++++++++-- .../tests/test_server_interceptor.py | 7 +- 2 files changed, 97 insertions(+), 16 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index d435a7bba1e..3a8db114036 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -16,6 +16,98 @@ # pylint:disable=relative-beyond-top-level # pylint:disable=import-error # pylint:disable=no-self-use +""" +Usage Client +----- +.. code-block:: python + + import logging + + import grpc + + from opentelemetry import trace + from opentelemetry.ext.grpc import GrpcInstrumentorClient, client_interceptor + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import ( + ConsoleSpanExporter, + SimpleExportSpanProcessor, + ) + + try: + from .gen import helloworld_pb2, helloworld_pb2_grpc + except ImportError: + from gen import helloworld_pb2, helloworld_pb2_grpc + + trace.set_tracer_provider(TracerProvider()) + trace.get_tracer_provider().add_span_processor( + SimpleExportSpanProcessor(ConsoleSpanExporter()) + ) + instrumentor = GrpcInstrumentorClient() + instrumentor.instrument() + + def run(): + with grpc.insecure_channel("localhost:50051") as channel: + + stub = helloworld_pb2_grpc.GreeterStub(channel) + response = stub.SayHello(helloworld_pb2.HelloRequest(name="YOU")) + + print("Greeter client received: " + response.message) + + + if __name__ == "__main__": + logging.basicConfig() + run() + +Usage Server +----- +.. code-block:: python + + import logging + from concurrent import futures + + import grpc + + from opentelemetry import trace + from opentelemetry.ext.grpc import GrpcInstrumentorServer, server_interceptor + from opentelemetry.ext.grpc.grpcext import intercept_server + from opentelemetry.sdk.trace import TracerProvider + from opentelemetry.sdk.trace.export import ( + ConsoleSpanExporter, + SimpleExportSpanProcessor, + ) + + try: + from .gen import helloworld_pb2, helloworld_pb2_grpc + except ImportError: + from gen import helloworld_pb2, helloworld_pb2_grpc + + trace.set_tracer_provider(TracerProvider()) + trace.get_tracer_provider().add_span_processor( + SimpleExportSpanProcessor(ConsoleSpanExporter()) + ) + grpc_server_instrumentor = GrpcInstrumentorServer() + grpc_server_instrumentor.instrument() + + + class Greeter(helloworld_pb2_grpc.GreeterServicer): + def SayHello(self, request, context): + return helloworld_pb2.HelloReply(message="Hello, %s!" % request.name) + + + def serve(): + + server = grpc.server(futures.ThreadPoolExecutor()) + + helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) + server.add_insecure_port("[::]:50051") + server.start() + server.wait_for_termination() + + + if __name__ == "__main__": + logging.basicConfig() + serve() +""" from contextlib import contextmanager import grpc @@ -34,9 +126,6 @@ class GrpcInstrumentorServer(BaseInstrumentor): - def __init__(self): - self.server = None - def _instrument(self, **kwargs): _wrap("grpc", "server", self.wrapper_fn) @@ -44,16 +133,12 @@ def _uninstrument(self, **kwargs): unwrap(grpc, "server") def wrapper_fn(self, original_func, instance, args, kwargs): - self.server = original_func(*args, **kwargs) - self.server = intercept_server(self.server, server_interceptor()) + server = original_func(*args, **kwargs) + return intercept_server(server, server_interceptor()) class GrpcInstrumentorClient(BaseInstrumentor): - def __init__(self): - self.channel = None - def _instrument(self, **kwargs): - if kwargs.get("channel_type") == "secure": _wrap("grpc", "secure_channel", self.wrapper_fn) @@ -70,8 +155,7 @@ def _uninstrument(self, **kwargs): @contextmanager def wrapper_fn(self, original_func, instance, args, kwargs): with original_func(*args, **kwargs) as channel: - self.channel = intercept_channel(channel, client_interceptor()) - yield self.channel + yield intercept_channel(channel, client_interceptor()) def client_interceptor(tracer_provider=None): diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 3cb1d21289b..72c832a61fc 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -55,14 +55,11 @@ def handler(request, context): grpc_server_instrumentor = GrpcInstrumentorServer() grpc_server_instrumentor.instrument() - server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), options=(("grpc.so_reuseport", 0),), ) - server = grpc_server_instrumentor.server - server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) port = server.add_insecure_port("[::]:0") @@ -72,14 +69,14 @@ def handler(request, context): try: server.start() - channel.unary_unary("")(b"") + channel.unary_unary("test")(b"test") finally: server.stop(None) spans_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans_list), 1) span = spans_list[0] - self.assertEqual(span.name, "") + self.assertEqual(span.name, "test") self.assertIs(span.kind, trace.SpanKind.SERVER) self.check_span_instrumentation_info(span, opentelemetry.ext.grpc) grpc_server_instrumentor.uninstrument() From e035d77dbe77148f28e248264602ea0568e8f9fe Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Tue, 21 Jul 2020 17:38:24 -0400 Subject: [PATCH 20/22] adding uninstrument test --- .../tests/test_server_interceptor.py | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 72c832a61fc..a40a19f7299 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -63,8 +63,6 @@ def handler(request, context): server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) port = server.add_insecure_port("[::]:0") - # grpc_client_instrumentor = GrpcInstrumentorClient() - # grpc_client_instrumentor.instrument(hostport=port) channel = grpc.insecure_channel("localhost:{:d}".format(port)) try: @@ -81,6 +79,35 @@ def handler(request, context): self.check_span_instrumentation_info(span, opentelemetry.ext.grpc) grpc_server_instrumentor.uninstrument() + def test_uninstrument(self): + + def handler(request, context): + return b"" + + grpc_server_instrumentor = GrpcInstrumentorServer() + grpc_server_instrumentor.instrument() + grpc_server_instrumentor.uninstrument() + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=1), + options=(("grpc.so_reuseport", 0),), + ) + + server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) + + port = server.add_insecure_port("[::]:0") + channel = grpc.insecure_channel("localhost:{:d}".format(port)) + + try: + server.start() + channel.unary_unary("test")(b"test") + finally: + server.stop(None) + + spans_list = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans_list), 0) + + + def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" From 309a6daf624e9a7075c53dec2b17a88bce317dc0 Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Tue, 21 Jul 2020 22:51:49 -0400 Subject: [PATCH 21/22] fixing lint issue --- ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index a40a19f7299..0ba57a43228 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -80,7 +80,6 @@ def handler(request, context): grpc_server_instrumentor.uninstrument() def test_uninstrument(self): - def handler(request, context): return b"" @@ -106,8 +105,6 @@ def handler(request, context): spans_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans_list), 0) - - def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" From bd45e62e1afcb369761b7ded9568de0074128c0d Mon Sep 17 00:00:00 2001 From: Aravin Sivakumar Date: Tue, 21 Jul 2020 23:17:00 -0400 Subject: [PATCH 22/22] fixing underline issue --- .../src/opentelemetry/ext/grpc/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 3a8db114036..368ae55f2e6 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -18,7 +18,7 @@ # pylint:disable=no-self-use """ Usage Client ------ +------------ .. code-block:: python import logging @@ -59,7 +59,7 @@ def run(): run() Usage Server ------ +------------ .. code-block:: python import logging