def test_trace_pubsub_error(self): pubsub = self.client.pubsub() with patch.object(pubsub, 'parse_response', side_effect=ValueError) as parse_response: parse_response.__name__ = 'parse_response' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_pubsub(pubsub) call_exc = None try: pubsub.get_message() except ValueError as exc: call_exc = exc self.assertEqual(parse_response.call_count, 1) self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'SUB') self.assertEqual( span.tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': '', 'span.kind': 'client', 'error': True, }) self.assertEqual(len(span.logs), 1) self.assertEqual(span.logs[0].key_values.get('event', None), 'error') self.assertTrue( isinstance(span.logs[0].key_values.get('error.object', None), ValueError))
def test_trace_pubsub_start_span_cb(self): def start_span_cb(span): span.set_operation_name('Test') pubsub = self.client.pubsub() return_value = [ # Simulate a real message 'pmessage', 'pattern1', 'channel1', 'hello', ] with patch.object(pubsub, 'parse_response', return_value=return_value) as parse_response: parse_response.__name__ = 'parse_response' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False, start_span_cb=start_span_cb) redis_opentracing.trace_pubsub(pubsub) res = pubsub.get_message() spans = self.tracer.finished_spans() self.assertEqual(len(spans), 1) self.assertEqual(spans[0].operation_name, 'Test')
def test_trace_pubsub_error(self): pubsub = self.client.pubsub() with patch.object(pubsub, 'parse_response', side_effect=ValueError) as parse_response: parse_response.__name__ = 'parse_response' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False, prefix='Test') redis_opentracing.trace_pubsub(pubsub) call_exc = None try: pubsub.get_message() except ValueError as exc: call_exc = exc self.assertEqual(parse_response.call_count, 1) self.assertEqual(len(self.tracer.spans), 1) self.assertEqual(self.tracer.spans[0].operation_name, 'Test/SUB') self.assertEqual(self.tracer.spans[0].is_finished, True) self.assertEqual( self.tracer.spans[0].tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': '', 'span.kind': 'client', 'error': 'true', 'error.object': call_exc, })
def test_trace_pubsub_execute_command(self): pubsub = self.client.pubsub() with patch.object(pubsub, 'execute_command', return_value='hello') as execute_command: execute_command.__name__ = 'parse_response' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False, prefix='Test') redis_opentracing.trace_pubsub(pubsub) res = pubsub.execute_command('GET', 'foo') self.assertEqual(res, 'hello') self.assertEqual(execute_command.call_count, 1) self.assertEqual(len(self.tracer.spans), 1) self.assertEqual(self.tracer.spans[0].operation_name, 'Test/GET') self.assertEqual(self.tracer.spans[0].is_finished, True) self.assertEqual( self.tracer.spans[0].tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'GET foo', 'span.kind': 'client', })
def test_trace_pipeline_error(self): pipe = self.client.pipeline() with patch.object(pipe, 'execute', side_effect=ValueError) as execute: execute.__name__ = 'execute' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False, prefix='Test') redis_opentracing.trace_pipeline(pipe) pipe.lpush('my:keys', 1, 3) pipe.lpush('my:keys', 5, 7) call_exc = None try: pipe.execute() except ValueError as exc: call_exc = exc self.assertEqual(execute.call_count, 1) self.assertEqual(len(self.tracer.spans), 1) self.assertEqual(self.tracer.spans[0].operation_name, 'Test/MULTI') self.assertEqual(self.tracer.spans[0].is_finished, True) self.assertEqual( self.tracer.spans[0].tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'LPUSH my:keys 1 3;LPUSH my:keys 5 7', 'span.kind': 'client', 'error': 'true', 'error.object': call_exc, })
def serve(): config = Config( config={ "sampler": { "type": "const", "param": 1 }, "logging": True }, service_name="chat-server", ) tracer = config.initialize_tracer() tracer_interceptor = open_tracing_server_interceptor(tracer, log_payloads=True) redis_opentracing.init_tracing(tracer_interceptor) redis_client = Redis() kafka_producer = KafkaProducer( bootstrap_servers="127.0.0.1:9092", value_serializer=lambda v: json.dumps(v).encode("utf-8"), ) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) server = intercept_server(server, tracer_interceptor) chat_pb2_grpc.add_ChatServicer_to_server( ChatServicer(tracer, redis_client, kafka_producer), server) server.add_insecure_port("[::]:50051") server.start() try: while True: time.sleep(_ONE_DAY_IN_SECONDS) except KeyboardInterrupt: server.stop(0)
def test_trace_client_error(self): with patch.object(self.client, 'execute_command', side_effect=ValueError) as exc_command: exc_command.__name__ = 'execute_command' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False, prefix='Test') redis_opentracing.trace_client(self.client) call_exc = None try: self.client.get('my.key') except ValueError as exc: call_exc = exc self.assertEqual(exc_command.call_count, 1) self.assertTrue(True, exc_command.call_args == (('my.key', ), )) self.assertEqual(len(self.tracer.spans), 1) self.assertEqual(self.tracer.spans[0].operation_name, 'Test/GET') self.assertEqual(self.tracer.spans[0].is_finished, True) self.assertEqual( self.tracer.spans[0].tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'GET my.key', 'span.kind': 'client', 'error': 'true', 'error.object': call_exc, })
def test_init_subtracer(self): tracer = MockTracer() tracer._tracer = object() redis_opentracing.init_tracing(tracer) self.assertEqual(tracer._tracer, tracing._g_tracer) self.assertEqual(tracer._tracer, tracing._get_tracer()) self.assertEqual(True, tracing._g_trace_all_classes)
def test_trace_pubsub(self): pubsub = self.client.pubsub() return_value = [ # Simulate a real message 'pmessage', 'pattern1', 'channel1', 'hello', ] with patch.object(pubsub, 'parse_response', return_value=return_value) as parse_response: parse_response.__name__ = 'parse_response' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_pubsub(pubsub) res = pubsub.get_message() self.assertEqual(res, { 'type': 'pmessage', 'pattern': 'pattern1', 'channel': 'channel1', 'data': 'hello', }) self.assertEqual(parse_response.call_count, 1) self.assertEqual(len(self.tracer.finished_spans()), 1) self.assertEqual(self.tracer.finished_spans()[0].operation_name, 'SUB') self.assertEqual(self.tracer.finished_spans()[0].tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': '', 'span.kind': 'client', })
def test_trace_pipeline_error(self): pipe = self.client.pipeline() with patch.object(pipe, 'execute', side_effect=ValueError) as execute: execute.__name__ = 'execute' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_pipeline(pipe) pipe.lpush('my:keys', 1, 3) pipe.lpush('my:keys', 5, 7) call_exc = None try: pipe.execute() except ValueError as exc: call_exc = exc self.assertEqual(execute.call_count, 1) self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'MULTI') self.assertEqual( span.tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'LPUSH my:keys 1 3;LPUSH my:keys 5 7', 'span.kind': 'client', 'error': True, }) self.assertEqual(len(span.logs), 1) self.assertEqual(span.logs[0].key_values.get('event', None), 'error') self.assertTrue( isinstance(span.logs[0].key_values.get('error.object', None), ValueError))
def test_trace_client_error(self): with patch.object(self.client, 'execute_command', side_effect=ValueError) as exc_command: exc_command.__name__ = 'execute_command' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_client(self.client) call_exc = None try: self.client.get('my.key') except ValueError as exc: call_exc = exc self.assertEqual(exc_command.call_count, 1) self.assertTrue(True, exc_command.call_args == (('my.key',),)) self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'GET') self.assertEqual(span.tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'GET my.key', 'span.kind': 'client', 'error': True, }) self.assertEqual(len(span.logs), 1) self.assertEqual(span.logs[0].key_values.get('event', None), 'error') self.assertTrue(isinstance( span.logs[0].key_values.get('error.object', None), ValueError ))
def test_trace_nothing(self): with patch.object(self.client, 'execute_command') as exc_command: exc_command.__name__ = 'execute_command' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) self.client.get('my.key') self.assertEqual(exc_command.call_count, 1) self.assertEqual(len(self.tracer.finished_spans()), 0)
def test_trace_pipeline_empty(self): pipe = self.client.pipeline() with patch.object(pipe, 'execute') as execute: execute.__name__ = 'execute' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) # No commands at all. redis_opentracing.trace_pipeline(pipe) pipe.execute() self.assertEqual(execute.call_count, 1) self.assertEqual(len(self.tracer.finished_spans()), 0)
def test_trace_all_pubsub(self): redis_opentracing.init_tracing(self.tracer) pubsub = self.client.pubsub() pubsub.subscribe('test') # Subscribing can cause more than a SUBSCRIBE call. self.assertTrue(len(self.tracer.finished_spans()) >= 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'SUBSCRIBE') self.assertEqual(span.tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'SUBSCRIBE test', 'span.kind': 'client', })
def test_trace_all_pipeline(self): redis_opentracing.init_tracing(self.tracer) pipe = self.client.pipeline() pipe.lpush('my:keys', 1, 3) pipe.rpush('my:keys', 5, 7) pipe.execute() self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'MULTI') self.assertEqual(span.tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'LPUSH my:keys 1 3;RPUSH my:keys 5 7', 'span.kind': 'client', })
def test_trace_client_start_span_cb(self): def start_span_cb(span): span.set_operation_name('Test') with patch.object(self.client, 'execute_command', return_value='1') as exc_command: exc_command.__name__ = 'execute_command' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False, start_span_cb=start_span_cb) redis_opentracing.trace_client(self.client) res = self.client.get('my.key') span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'Test')
def test_trace_all_client_with_unicode(self): with patch('redis.StrictRedis.execute_command') as execute_command: execute_command.__name__ = 'execute_command' redis_opentracing.init_tracing(self.tracer) self.client.get(u'my.k\xc3y') self.assertEqual(execute_command.call_count, 1) self.assertTrue(True, execute_command.call_args == ((u'my.k\xc3y',),)) self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'GET') self.assertEqual(span.tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': u'GET my.k\xc3y', 'span.kind': 'client', })
def test_trace_all_pipeline(self): redis_opentracing.init_tracing(self.tracer, prefix='Test') pipe = self.client.pipeline() pipe.lpush('my:keys', 1, 3) pipe.rpush('my:keys', 5, 7) pipe.execute() self.assertEqual(len(self.tracer.spans), 1) self.assertEqual(self.tracer.spans[0].operation_name, 'Test/MULTI') self.assertEqual(self.tracer.spans[0].is_finished, True) self.assertEqual( self.tracer.spans[0].tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'LPUSH my:keys 1 3;RPUSH my:keys 5 7', 'span.kind': 'client', })
def test_trace_client_start_span_cb_exc(self): def start_span_cb(span): raise RuntimeError('This should not happen') with patch.object(self.client, 'execute_command', return_value='1') as exc_command: exc_command.__name__ = 'execute_command' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False, start_span_cb=start_span_cb) redis_opentracing.trace_client(self.client) res = self.client.get('my.key') span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'GET') self.assertFalse(span.tags.get('error', False))
def listen(): config = Config( config={ "sampler": { "type": "const", "param": 1 }, "logging": True }, service_name="storage", ) tracer = config.initialize_tracer() redis_opentracing.init_tracing(tracer) redis_client = Redis() kafka_consumer = KafkaConsumer( "message-created", bootstrap_servers="127.0.0.1:9092", value_deserializer=lambda v: json.loads(v, encoding="utf-8"), ) for message in kafka_consumer: headers = dict( (key, value.decode('utf-8')) for key, value in message.headers) span_context = tracer.extract(opentracing.Format.TEXT_MAP, headers) with tracer.start_span("Storing Message", child_of=span_context) as scope: with tracer.start_span("Fetching Messages", child_of=scope): messages = redis_client.get("messages") if not messages: messages = "[]" with tracer.start_span("Parsing Messages", child_of=scope): messages = json.loads(messages) messages.append(message.value) with tracer.start_span("Serializing Messages", child_of=scope): messages = json.dumps(messages) with tracer.start_span("Saving Messages", child_of=scope): redis_client.set("messages", messages)
def test_trace_pipeline_start_span_cb(self): def start_span_cb(span): span.set_operation_name('Test') pipe = self.client.pipeline() with patch.object(pipe, 'execute') as execute: execute.__name__ = 'execute' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False, start_span_cb=start_span_cb) redis_opentracing.trace_pipeline(pipe) pipe.lpush('my:keys', 1, 3) pipe.execute() spans = self.tracer.finished_spans() self.assertEqual(len(spans), 1) self.assertEqual(spans[0].operation_name, 'Test')
def test_trace_all_client(self): with patch('redis.StrictRedis.execute_command') as execute_command: execute_command.__name__ = 'execute_command' redis_opentracing.init_tracing(self.tracer, prefix='Test') self.client.get('my.key') self.assertEqual(execute_command.call_count, 1) self.assertTrue(True, execute_command.call_args == (('my.key', ), )) self.assertEqual(len(self.tracer.spans), 1) self.assertEqual(self.tracer.spans[0].operation_name, 'Test/GET') self.assertEqual(self.tracer.spans[0].is_finished, True) self.assertEqual( self.tracer.spans[0].tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'GET my.key', 'span.kind': 'client', })
def test_trace_pipeline_immediate(self): pipe = self.client.pipeline() with patch.object(pipe, 'immediate_execute_command') as iexecute: iexecute.__name__ = 'immediate_execute_command' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_pipeline(pipe) pipe.immediate_execute_command('WATCH', 'my:key') self.assertEqual(iexecute.call_count, 1) self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'WATCH') self.assertEqual( span.tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'WATCH my:key', 'span.kind': 'client', })
def test_trace_client_pubsub(self): redis_opentracing.init_tracing(self.tracer, trace_all_classes=False, prefix='Test') redis_opentracing.trace_client(self.client) pubsub = self.client.pubsub() pubsub.subscribe('test') # Subscribing can cause more than a SUBSCRIBE call. self.assertTrue(len(self.tracer.spans) >= 1) self.assertEqual(self.tracer.spans[0].operation_name, 'Test/SUBSCRIBE') self.assertEqual(self.tracer.spans[0].is_finished, True) self.assertEqual( self.tracer.spans[0].tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'SUBSCRIBE test', 'span.kind': 'client', })
def test_trace_pipeline_error(self): pipe = self.client.pipeline() with patch.object(pipe, 'execute', side_effect=ValueError) as execute: execute.__name__ = 'execute' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_pipeline(pipe) pipe.lpush('my:keys', 1, 3) pipe.lpush('my:keys', 5, 7) call_exc = None try: pipe.execute() except ValueError as exc: call_exc = exc self.assertEqual(execute.call_count, 1) self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'MULTI') tags = { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'LPUSH my:keys 1 3;LPUSH my:keys 5 7', 'span.kind': 'client', 'error': True, } for k, v in tags.items(): assert k in span.tags assert span.tags[k] == v self.assertEqual(span.tags['error'], True) self.assertEqual(span.tags['sfx.error.message'], '') self.assertEqual(span.tags['sfx.error.kind'], 'ValueError') self.assertEqual(span.tags['sfx.error.object'], '<class \'ValueError\'>') assert len(span.tags['sfx.error.stack']) > 50
def test_trace_client_error(self): with patch.object(self.client, 'execute_command', side_effect=ValueError('error msg')) as exc_command: exc_command.__name__ = 'execute_command' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_client(self.client) call_exc = None try: self.client.get('my.key') except ValueError as exc: call_exc = exc self.assertEqual(exc_command.call_count, 1) self.assertTrue(True, exc_command.call_args == (('my.key', ), )) self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'GET') tags = { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'GET my.key', 'span.kind': 'client', 'error': True, } for k, v in tags.items(): assert k in span.tags assert span.tags[k] == v self.assertEqual(span.tags['error'], True) self.assertEqual(span.tags['sfx.error.message'], 'error msg') self.assertEqual(span.tags['sfx.error.kind'], 'ValueError') self.assertEqual(span.tags['sfx.error.object'], '<class \'ValueError\'>') assert len(span.tags['sfx.error.stack']) > 50
def test_trace_pubsub_error(self): pubsub = self.client.pubsub() with patch.object(pubsub, 'parse_response', side_effect=ValueError) as parse_response: parse_response.__name__ = 'parse_response' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_pubsub(pubsub) call_exc = None try: pubsub.get_message() except ValueError as exc: call_exc = exc self.assertEqual(parse_response.call_count, 1) self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'SUB') tags = { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': '', 'span.kind': 'client', 'error': True, } for k, v in tags.items(): assert k in span.tags assert span.tags[k] == v self.assertEqual(span.tags['error'], True) self.assertEqual(span.tags['sfx.error.message'], '') self.assertEqual(span.tags['sfx.error.kind'], 'ValueError') self.assertEqual(span.tags['sfx.error.object'], '<class \'ValueError\'>') assert len(span.tags['sfx.error.stack']) > 50
def test_trace_pipeline(self): pipe = self.client.pipeline() with patch.object(pipe, 'execute') as execute: execute.__name__ = 'execute' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_pipeline(pipe) pipe.lpush('my:keys', 1, 3) pipe.lpush('my:keys', 5, 7) pipe.execute() self.assertEqual(execute.call_count, 1) self.assertEqual(len(self.tracer.finished_spans()), 1) self.assertEqual(self.tracer.finished_spans()[0].operation_name, 'MULTI') self.assertEqual( self.tracer.finished_spans()[0].tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'LPUSH my:keys 1 3;LPUSH my:keys 5 7', 'span.kind': 'client', })
def test_trace_client(self): with patch.object(self.client, 'execute_command', return_value='1') as exc_command: exc_command.__name__ = 'execute_command' redis_opentracing.init_tracing(self.tracer, trace_all_classes=False) redis_opentracing.trace_client(self.client) res = self.client.get('my.key') self.assertEqual(res, '1') self.assertEqual(exc_command.call_count, 1) self.assertTrue(True, exc_command.call_args == (('my.key', ), )) self.assertEqual(len(self.tracer.finished_spans()), 1) span = self.tracer.finished_spans()[0] self.assertEqual(span.operation_name, 'GET') self.assertEqual( span.tags, { 'component': 'redis-py', 'db.type': 'redis', 'db.statement': 'GET my.key', 'span.kind': 'client', })
import datetime import redis import redis_opentracing # Your OpenTracing-compatible tracer here. tracer = None if __name__ == '__main__': client = redis.StrictRedis() redis_opentracing.init_tracing(tracer, trace_all_classes=False, prefix='Explicit') # Not traced. client.set('last_access', datetime.datetime.now()) # Everthing from this point on client gets traced. redis_opentracing.trace_client(client) # Traced. client.set('last_update', datetime.datetime.now()) # Traced as a MULTI command with # LPUSH fruits lemon watermelon pipe = client.pipeline() pipe.lpush('fruits', 'lemon', 'watermelon') print(pipe.execute())