def test_span_lifetime(self): """Check that the span is active for the duration of the call.""" interceptor = server_interceptor() # To capture the current span at the time the handler is called active_span_in_handler = None def handler(request, context): nonlocal active_span_in_handler active_span_in_handler = trace.get_current_span() return b"" server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler), )) port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) active_span_before_call = trace.get_current_span() try: server.start() channel.unary_unary("TestServicer/handler")(b"") finally: server.stop(None) active_span_after_call = trace.get_current_span() self.assertEqual(active_span_before_call, trace.INVALID_SPAN) self.assertEqual(active_span_after_call, trace.INVALID_SPAN) self.assertIsInstance(active_span_in_handler, trace_sdk.Span) self.assertIsNone(active_span_in_handler.parent)
def test_sequential_server_spans(self): """Check that sequential RPCs get separate server spans.""" interceptor = server_interceptor() # Capture the currently active span in each thread active_spans_in_handler = [] def handler(request, context): active_spans_in_handler.append(trace.get_current_span()) return b"" with futures.ThreadPoolExecutor(max_workers=1) as executor: server = grpc.server( executor, options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) 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("TestServicer/handler")(b"") channel.unary_unary("TestServicer/handler")(b"") finally: server.stop(None) self.assertEqual(len(active_spans_in_handler), 2) # pylint:disable=unbalanced-tuple-unpacking span1, span2 = active_spans_in_handler # Spans should belong to separate traces self.assertNotEqual(span1.context.span_id, span2.context.span_id) self.assertNotEqual(span1.context.trace_id, span2.context.trace_id) for span in (span1, span2): # each should be a root span self.assertIsNone(span2.parent) # check attributes self.assert_span_has_attributes( span, { SpanAttributes.NET_PEER_IP: "[::1]", SpanAttributes.NET_PEER_NAME: "localhost", SpanAttributes.RPC_METHOD: "handler", SpanAttributes.RPC_SERVICE: "TestServicer", SpanAttributes.RPC_SYSTEM: "grpc", SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[0], }, )
def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) server = intercept_server(server, server_interceptor()) route_guide_pb2_grpc.add_RouteGuideServicer_to_server( RouteGuideServicer(), server) server.add_insecure_port("[::]:50051") server.start() server.wait_for_termination()
def serve(): server = grpc.server(futures.ThreadPoolExecutor()) server = intercept_server(server, server_interceptor()) helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) server.add_insecure_port("[::]:50051") server.start() server.wait_for_termination()
def serve(): trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter())) propagators.set_global_textmap(B3Format()) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), interceptors=[server_interceptor()]) add_ImageServiceServicer_to_server(ImageServer(), server) server.add_insecure_port("[::]:50051") server.start() server.wait_for_termination()
def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" # Intercept gRPC calls... interceptor = server_interceptor() # No-op RPC handler def handler(request, context): return b"" server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler), )) port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) rpc_call = "TestServicer/handler" try: server.start() channel.unary_unary(rpc_call)(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, rpc_call) self.assertIs(span.kind, trace.SpanKind.SERVER) # Check version and name in span's instrumentation info self.check_span_instrumentation_info( span, opentelemetry.instrumentation.grpc) # Check attributes self.assert_span_has_attributes( span, { "net.peer.ip": "[::1]", "net.peer.name": "localhost", "rpc.method": "handler", "rpc.service": "TestServicer", "rpc.system": "grpc", "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], }, )
def test_create_span_streaming(self): """Check that the interceptor wraps calls with spans server-side, on a streaming call.""" # Intercept gRPC calls... interceptor = server_interceptor() # setup the server server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) add_GRPCTestServerServicer_to_server(Servicer(), server) port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) # setup the RPC rpc_call = "/GRPCTestServer/ServerStreamingMethod" request = Request(client_id=1, request_data="test") msg = request.SerializeToString() try: server.start() list(channel.unary_stream(rpc_call)(msg)) 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, rpc_call) self.assertIs(span.kind, trace.SpanKind.SERVER) # Check version and name in span's instrumentation info self.check_span_instrumentation_info( span, opentelemetry.instrumentation.grpc) # Check attributes self.assert_span_has_attributes( span, { SpanAttributes.NET_PEER_IP: "[::1]", SpanAttributes.NET_PEER_NAME: "localhost", SpanAttributes.RPC_METHOD: "ServerStreamingMethod", SpanAttributes.RPC_SERVICE: "GRPCTestServer", SpanAttributes.RPC_SYSTEM: "grpc", SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[0], }, )
def test_concurrent_server_spans(self): """Check that concurrent RPC calls don't interfere with each other. This is the same check as test_sequential_server_spans except that the RPCs are concurrent. Two handlers are invoked at the same time on two separate threads. Each one should see a different active span and context. """ interceptor = server_interceptor() # Capture the currently active span in each thread active_spans_in_handler = [] latch = get_latch(2) def handler(request, context): latch() active_spans_in_handler.append(trace.get_current_span()) return b"" server = grpc.server( futures.ThreadPoolExecutor(max_workers=2), options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler), )) port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) try: server.start() # Interleave calls so spans are active on each thread at the same # time with futures.ThreadPoolExecutor(max_workers=2) as tpe: f1 = tpe.submit(channel.unary_unary(""), b"") f2 = tpe.submit(channel.unary_unary(""), b"") futures.wait((f1, f2)) finally: server.stop(None) self.assertEqual(len(active_spans_in_handler), 2) # pylint:disable=unbalanced-tuple-unpacking span1, span2 = active_spans_in_handler # Spans should belong to separate traces, and each should be a root # span self.assertNotEqual(span1.context.span_id, span2.context.span_id) self.assertNotEqual(span1.context.trace_id, span2.context.trace_id) self.assertIsNone(span1.parent) self.assertIsNone(span1.parent)
def __init__(self, name='otel-grpc-test', listen='localhost:50051'): self._name = name interceptors = [] self._enable_otel() interceptors.append(server_interceptor(self.tracer)) # here's the gRPC server self.server = grpc.server( futures.ThreadPoolExecutor(max_workers = 10), interceptors = interceptors) self.server.add_insecure_port(listen) log.info("Listening on %s", listen)
def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" # Intercept gRPC calls... interceptor = server_interceptor() server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) add_GRPCTestServerServicer_to_server(Servicer(), server) port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) rpc_call = "/GRPCTestServer/SimpleMethod" request = Request(client_id=1, request_data="test") msg = request.SerializeToString() try: server.start() channel.unary_unary(rpc_call)(msg) 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, rpc_call) self.assertIs(span.kind, trace.SpanKind.SERVER) # Check version and name in span's instrumentation info self.check_span_instrumentation_info( span, opentelemetry.instrumentation.grpc) # Check attributes self.assert_span_has_attributes( span, { "net.peer.ip": "[::1]", "net.peer.name": "localhost", "rpc.method": "SimpleMethod", "rpc.service": "GRPCTestServer", "rpc.system": "grpc", "rpc.grpc.status_code": grpc.StatusCode.OK.value[0], }, )
def serve(): trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter()) ) propagators.set_global_textmap(B3Format()) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), interceptors=[server_interceptor()]) add_ProductInfoServicer_to_server(ProductInfoServer(), server) server.add_insecure_port("[::]:50050") server.start() proxy = MyProxy(ProductInfoServer) try: proxy.start() server.wait_for_termination() except KeyboardInterrupt: print("terminating") proxy.stop() print("Goodbye")
def test_sequential_server_spans(self): """Check that sequential RPCs get separate server spans.""" interceptor = server_interceptor() # Capture the currently active span in each thread active_spans_in_handler = [] def handler(request, context): active_spans_in_handler.append(trace.get_current_span()) return b"" server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) 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("")(b"") channel.unary_unary("")(b"") finally: server.stop(None) self.assertEqual(len(active_spans_in_handler), 2) # pylint:disable=unbalanced-tuple-unpacking span1, span2 = active_spans_in_handler # Spans should belong to separate traces, and each should be a root # span self.assertNotEqual(span1.context.span_id, span2.context.span_id) self.assertNotEqual(span1.context.trace_id, span2.context.trace_id) self.assertIsNone(span1.parent) self.assertIsNone(span1.parent)
def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" # Intercept gRPC calls... interceptor = server_interceptor() # No-op RPC handler 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) 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("")(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.instrumentation.grpc)
def start(dummy_mode): # Create gRPC server channel to receive requests from checkout (client). interceptor = server_interceptor(trace.get_tracer_provider()) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), interceptors=(interceptor, )) service = None if dummy_mode: service = DummyEmailService() else: raise Exception("non-dummy mode not implemented yet") demo_pb2_grpc.add_EmailServiceServicer_to_server(service, server) health_pb2_grpc.add_HealthServicer_to_server(service, server) port = os.environ.get("PORT", "8080") logger.info("listening on port: " + port) server.add_insecure_port("[::]:" + port) server.start() try: while True: time.sleep(3600) except KeyboardInterrupt: server.stop(0)
def test_concurrent_server_spans(self): """Check that concurrent RPC calls don't interfere with each other. This is the same check as test_sequential_server_spans except that the RPCs are concurrent. Two handlers are invoked at the same time on two separate threads. Each one should see a different active span and context. """ interceptor = server_interceptor() # Capture the currently active span in each thread active_spans_in_handler = [] latch = get_latch(2) def handler(request, context): latch() active_spans_in_handler.append(trace.get_current_span()) return b"" with futures.ThreadPoolExecutor(max_workers=2) as executor: server = grpc.server( executor, options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler), )) port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) try: server.start() # Interleave calls so spans are active on each thread at the same # time with futures.ThreadPoolExecutor(max_workers=2) as tpe: f1 = tpe.submit( channel.unary_unary("TestServicer/handler"), b"") f2 = tpe.submit( channel.unary_unary("TestServicer/handler"), b"") futures.wait((f1, f2)) finally: server.stop(None) self.assertEqual(len(active_spans_in_handler), 2) # pylint:disable=unbalanced-tuple-unpacking span1, span2 = active_spans_in_handler # Spans should belong to separate traces self.assertNotEqual(span1.context.span_id, span2.context.span_id) self.assertNotEqual(span1.context.trace_id, span2.context.trace_id) for span in (span1, span2): # each should be a root span self.assertIsNone(span2.parent) # check attributes self.assert_span_has_attributes( span, { SpanAttributes.NET_PEER_IP: "[::1]", SpanAttributes.NET_PEER_NAME: "localhost", SpanAttributes.RPC_METHOD: "handler", SpanAttributes.RPC_SERVICE: "TestServicer", SpanAttributes.RPC_SYSTEM: "grpc", SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[0], }, )
def test_abort(self): """Check that we can catch an abort properly""" # Intercept gRPC calls... interceptor = server_interceptor() # our detailed failure message failure_message = "This is a test failure" # aborting RPC handler def handler(request, context): context.abort(grpc.StatusCode.FAILED_PRECONDITION, failure_message) server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler), )) port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) rpc_call = "TestServicer/handler" server.start() # unfortunately, these are just bare exceptions in grpc... with self.assertRaises(Exception): channel.unary_unary(rpc_call)(b"") 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, rpc_call) self.assertIs(span.kind, trace.SpanKind.SERVER) # Check version and name in span's instrumentation info self.check_span_instrumentation_info( span, opentelemetry.instrumentation.grpc) # make sure this span errored, with the right status and detail self.assertEqual(span.status.status_code, StatusCode.ERROR) self.assertEqual( span.status.description, "{}:{}".format(grpc.StatusCode.FAILED_PRECONDITION, failure_message), ) # Check attributes self.assert_span_has_attributes( span, { SpanAttributes.NET_PEER_IP: "[::1]", SpanAttributes.NET_PEER_NAME: "localhost", SpanAttributes.RPC_METHOD: "handler", SpanAttributes.RPC_SERVICE: "TestServicer", SpanAttributes.RPC_SYSTEM: "grpc", SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.FAILED_PRECONDITION.value[0], }, )
def test_create_two_spans_streaming(self): """Verify that the interceptor captures sub spans in a streaming call, within the given trace""" class TwoSpanServicer(GRPCTestServerServicer): # pylint:disable=C0103 def ServerStreamingMethod(self, request, context): # create another span tracer = trace.get_tracer(__name__) with tracer.start_as_current_span("child") as child: child.add_event("child event") for data in ("one", "two", "three"): yield Response( server_id=request.client_id, response_data=data, ) # Intercept gRPC calls... interceptor = server_interceptor() # setup the server server = grpc.server( futures.ThreadPoolExecutor(max_workers=1), options=(("grpc.so_reuseport", 0), ), interceptors=[interceptor], ) add_GRPCTestServerServicer_to_server(TwoSpanServicer(), server) port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) # setup the RPC rpc_call = "/GRPCTestServer/ServerStreamingMethod" request = Request(client_id=1, request_data="test") msg = request.SerializeToString() try: server.start() list(channel.unary_stream(rpc_call)(msg)) finally: server.stop(None) spans_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans_list), 2) child_span = spans_list[0] parent_span = spans_list[1] self.assertEqual(parent_span.name, rpc_call) self.assertIs(parent_span.kind, trace.SpanKind.SERVER) # Check version and name in span's instrumentation info self.check_span_instrumentation_info( parent_span, opentelemetry.instrumentation.grpc) # Check attributes self.assert_span_has_attributes( parent_span, { SpanAttributes.NET_PEER_IP: "[::1]", SpanAttributes.NET_PEER_NAME: "localhost", SpanAttributes.RPC_METHOD: "ServerStreamingMethod", SpanAttributes.RPC_SERVICE: "GRPCTestServer", SpanAttributes.RPC_SYSTEM: "grpc", SpanAttributes.RPC_GRPC_STATUS_CODE: grpc.StatusCode.OK.value[0], }, ) # Check the child span self.assertEqual(child_span.name, "child") self.assertEqual(parent_span.context.trace_id, child_span.context.trace_id)
catalog_addr = os.environ.get('PRODUCT_CATALOG_SERVICE_ADDR', '') if catalog_addr == "": raise Exception( 'PRODUCT_CATALOG_SERVICE_ADDR environment variable not set') logger.info("product catalog address: " + catalog_addr) # Create the gRPC client channel to ProductCatalog (server). channel = grpc.insecure_channel(catalog_addr) # OpenTelemetry client interceptor passes trace contexts to the server. channel = intercept_channel( channel, client_interceptor(trace.get_tracer_provider())) product_catalog_stub = demo_pb2_grpc.ProductCatalogServiceStub(channel) # Create the gRPC server for accepting ListRecommendations Requests from frontend (client). interceptor = server_interceptor(trace.get_tracer_provider()) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), interceptors=(interceptor,)) # Add RecommendationService class to gRPC server. service = RecommendationService() demo_pb2_grpc.add_RecommendationServiceServicer_to_server(service, server) health_pb2_grpc.add_HealthServicer_to_server(service, server) # start server logger.info("listening on port: " + port) server.add_insecure_port('[::]:'+port) server.start() # keep alive try: