Repository: census-instrumentation/opencensus-python
Pull request #152 (2018-04-10 19:53:29)

Update gRPC span names to match spec


Patch:
diff --git a/opencensus/trace/ext/grpc/client_interceptor.py b/opencensus/trace/ext/grpc/client_interceptor.py
index 82c25c3..c96d130 100644
--- a/opencensus/trace/ext/grpc/client_interceptor.py
+++ b/opencensus/trace/ext/grpc/client_interceptor.py
@@ -29,6 +29,7 @@ ATTRIBUTE_ERROR_NAME = 'ERROR_NAME'
 ATTRIBUTE_ERROR_MESSAGE = 'ERROR_MESSAGE'
 GRPC_HOST_PORT = 'GRPC_HOST_PORT'
 GRPC_METHOD = 'GRPC_METHOD'
+SENT_PREFIX = 'Sent'
 
 TIMEOUT = 3
 
@@ -57,9 +58,10 @@ class OpenCensusClientInterceptor(grpc.UnaryUnaryClientInterceptor,
         self.host_port = host_port
         self._propagator = binary_format.BinaryFormatPropagator()
 
-    def _start_client_span(self, method, grpc_type):
+    def _start_client_span(self, client_call_details):
         span = self._tracer.start_span(
-            name='[gRPC_client][{}]{}'.format(grpc_type, str(method)))
+            name=_get_span_name(client_call_details)
+        )
 
         # Add the component grpc to span attribute
         self._tracer.add_attribute_to_current_span(
@@ -76,7 +78,7 @@ class OpenCensusClientInterceptor(grpc.UnaryUnaryClientInterceptor,
         # Add the method to span attribute
         self._tracer.add_attribute_to_current_span(
             attribute_key=attributes_helper.GRPC_ATTRIBUTES.get(GRPC_METHOD),
-            attribute_value=str(method))
+            attribute_value=str(client_call_details.method))
 
         return span
 
@@ -91,9 +93,7 @@ class OpenCensusClientInterceptor(grpc.UnaryUnaryClientInterceptor,
             metadata = client_call_details.metadata
 
         # Start a span
-        current_span = self._start_client_span(
-            client_call_details.method,
-            grpc_type)
+        current_span = self._start_client_span(client_call_details)
 
         span_context = self._tracer.span_context
         header = self._propagator.to_header(span_context)
@@ -211,3 +211,9 @@ class OpenCensusClientInterceptor(grpc.UnaryUnaryClientInterceptor,
         self._end_span_between_context(current_span)
 
         return response_it
+
+
+def _get_span_name(client_call_details):
+    """Generates a span name based off of the gRPC client call details"""
+    method_name = client_call_details.method[1:].replace('/', '.')
+    return '{}.{}'.format(SENT_PREFIX, method_name)
diff --git a/opencensus/trace/ext/grpc/server_interceptor.py b/opencensus/trace/ext/grpc/server_interceptor.py
index ee72fc6..275dcc7 100644
--- a/opencensus/trace/ext/grpc/server_interceptor.py
+++ b/opencensus/trace/ext/grpc/server_interceptor.py
@@ -29,6 +29,7 @@ from opencensus.trace.propagation import binary_format
 ATTRIBUTE_COMPONENT = 'COMPONENT'
 ATTRIBUTE_ERROR_NAME = 'ERROR_NAME'
 ATTRIBUTE_ERROR_MESSAGE = 'ERROR_MESSAGE'
+RECV_PREFIX = 'Recv'
 
 RpcRequestInfo = collections.namedtuple(
     'RPCRequestInfo', ('request', 'context')
@@ -113,7 +114,7 @@ class OpenCensusServerInterceptor(grpc.ServerInterceptor):
                                       sampler=self.sampler,
                                       exporter=self.exporter)
 
-        span = tracer.start_span(name='grpc_server')
+        span = tracer.start_span(name=_get_span_name(rpc_request_info))
         tracer.add_attribute_to_current_span(
             attribute_key=attributes_helper.COMMON_ATTRIBUTES.get(
                 ATTRIBUTE_COMPONENT),
@@ -151,3 +152,12 @@ class OpenCensusServerInterceptor(grpc.ServerInterceptor):
 
     def intercept_service(self, continuation, handler_call_details):
         return self.intercept_handler(continuation, handler_call_details)
+
+
+def _get_span_name(rpc_request_info):
+    """Generates a span name based off of the gRPC server rpc_request_info"""
+    method_name = rpc_request_info.context._rpc_event.call_details.method[1:]
+    if isinstance(method_name, bytes):
+        method_name = method_name.decode('utf-8')
+    method_name = method_name.replace('/', '.')
+    return '{}.{}'.format(RECV_PREFIX, method_name)


Test patch:
diff --git a/tests/unit/trace/ext/grpc/test_client_interceptor.py b/tests/unit/trace/ext/grpc/test_client_interceptor.py
index b469667..127492f 100644
--- a/tests/unit/trace/ext/grpc/test_client_interceptor.py
+++ b/tests/unit/trace/ext/grpc/test_client_interceptor.py
@@ -55,7 +55,9 @@ class TestOpenCensusClientInterceptor(unittest.TestCase):
         tracer = mock.Mock()
         interceptor = client_interceptor.OpenCensusClientInterceptor(
             tracer=tracer, host_port='test')
-        interceptor._start_client_span('test_method', 'unary_unary')
+        mock_client_call_details = mock.Mock()
+        mock_client_call_details.method = '/hello'
+        interceptor._start_client_span(mock_client_call_details)
 
         self.assertTrue(tracer.start_span.called)
         self.assertTrue(tracer.add_attribute_to_current_span.called)
@@ -86,6 +88,7 @@ class TestOpenCensusClientInterceptor(unittest.TestCase):
         interceptor._propagator = mock_propagator
         mock_client_call_details = mock.Mock()
         mock_client_call_details.metadata = None
+        mock_client_call_details.method = '/hello'
 
         client_call_details, request_iterator, current_span = interceptor._intercept_call(
             mock_client_call_details,
@@ -108,6 +111,7 @@ class TestOpenCensusClientInterceptor(unittest.TestCase):
         interceptor._propagator = mock_propagator
         mock_client_call_details = mock.Mock()
         mock_client_call_details.metadata = [('test_key', 'test_value'),]
+        mock_client_call_details.method = '/hello'
 
         client_call_details, request_iterator, current_span = interceptor._intercept_call(
             mock_client_call_details,
@@ -130,6 +134,7 @@ class TestOpenCensusClientInterceptor(unittest.TestCase):
         interceptor._propagator = mock_propagator
         mock_client_call_details = mock.Mock()
         mock_client_call_details.metadata = (('test_key', 'test_value'),)
+        mock_client_call_details.method = '/hello'
 
         client_call_details, request_iterator, current_span = interceptor._intercept_call(
             mock_client_call_details,
diff --git a/tests/unit/trace/ext/grpc/test_server_interceptor.py b/tests/unit/trace/ext/grpc/test_server_interceptor.py
index aaf35eb..1565def 100644
--- a/tests/unit/trace/ext/grpc/test_server_interceptor.py
+++ b/tests/unit/trace/ext/grpc/test_server_interceptor.py
@@ -44,6 +44,7 @@ class TestOpenCensusServerInterceptor(unittest.TestCase):
             MockTracer)
         mock_context = mock.Mock()
         mock_context.invocation_metadata = mock.Mock(return_value=None)
+        mock_context._rpc_event.call_details.method = 'hello'
         interceptor = server_interceptor.OpenCensusServerInterceptor(
             None, None)
 
@@ -68,6 +69,7 @@ class TestOpenCensusServerInterceptor(unittest.TestCase):
         mock_context.invocation_metadata = mock.Mock(
             return_value=(('test_key', b'test_value'),)
         )
+        mock_context._rpc_event.call_details.method = 'hello'
         interceptor = server_interceptor.OpenCensusServerInterceptor(
             None, None)
 
@@ -100,6 +102,7 @@ class TestOpenCensusServerInterceptor(unittest.TestCase):
             None, None)
         mock_context = mock.Mock()
         mock_context.invocation_metadata = mock.Mock(return_value=None)
+        mock_context._rpc_event.call_details.method = 'hello'
         mock_continuation = mock.Mock()
         mock_continuation.unary_unary = mock.Mock(side_effect=Exception('Test'))
         with patch: