def test_fetch_no_analytics(self): """ Confirm fetch* methods do not have analytics sample rate metric """ with self.override_config( 'dbapi2', dict(analytics_enabled=True) ): cursor = self.cursor cursor.rowcount = 0 cursor.fetchone.return_value = '__result__' pin = Pin('pin_name', tracer=self.tracer) traced_cursor = FetchTracedCursor(cursor, pin) assert '__result__' == traced_cursor.fetchone('arg_1', kwarg1='kwarg1') span = self.tracer.writer.pop()[0] self.assertIsNone(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY)) cursor = self.cursor cursor.rowcount = 0 cursor.fetchall.return_value = '__result__' pin = Pin('pin_name', tracer=self.tracer) traced_cursor = FetchTracedCursor(cursor, pin) assert '__result__' == traced_cursor.fetchall('arg_1', kwarg1='kwarg1') span = self.tracer.writer.pop()[0] self.assertIsNone(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY)) cursor = self.cursor cursor.rowcount = 0 cursor.fetchmany.return_value = '__result__' pin = Pin('pin_name', tracer=self.tracer) traced_cursor = FetchTracedCursor(cursor, pin) assert '__result__' == traced_cursor.fetchmany('arg_1', kwarg1='kwarg1') span = self.tracer.writer.pop()[0] self.assertIsNone(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY))
def test_pin_find(self): # ensure Pin will find the first available pin # Override service obj_a = self.Obj() pin = Pin(service='service-a') pin.onto(obj_a) # Override service obj_b = self.Obj() pin = Pin(service='service-b') pin.onto(obj_b) # No Pin set obj_c = self.Obj() # We find the first pin (obj_b) pin = Pin._find(obj_c, obj_b, obj_a) assert pin is not None assert pin.service == 'service-b' # We find the first pin (obj_a) pin = Pin._find(obj_a, obj_b, obj_c) assert pin is not None assert pin.service == 'service-a' # We don't find a pin if none is there pin = Pin._find(obj_c, obj_c, obj_c) assert pin is None
def _traced_session(self): tracer = get_dummy_tracer() # pin the global Cluster to test if they will conflict Pin(service='not-%s' % self.TEST_SERVICE).onto(Cluster) self.cluster = Cluster(port=CASSANDRA_CONFIG['port']) Pin(service=self.TEST_SERVICE, tracer=tracer).onto(self.cluster) return self.cluster.connect(self.TEST_KEYSPACE), tracer
def get_tracer_and_connect(self): tracer = get_dummy_tracer() # Set a connect-level service, to check that we properly override it Pin(service='not-%s' % self.TEST_SERVICE).onto(mongoengine.connect) client = mongoengine.connect(port=MONGO_CONFIG['port']) Pin(service=self.TEST_SERVICE, tracer=tracer).onto(client) return tracer
def test_blueprint_add_url_rule(self): """ When we call ``flask.Blueprint.add_url_rule`` When the ``Blueprint`` has a ``Pin`` attached We clone the Blueprint's ``Pin`` to the view When the ``Blueprint`` does not have a ``Pin`` attached We do not attach a ``Pin`` to the func """ # When the Blueprint has a Pin attached bp = flask.Blueprint('pinned', __name__) Pin(service='flask-bp', tracer=self.tracer).onto(bp) @bp.route('/') def test_view(): pass # Assert the view func has a `Pin` attached with the Blueprint's service name pin = Pin.get_from(test_view) self.assertIsNotNone(pin) self.assertEqual(pin.service, 'flask-bp') # When the Blueprint does not have a Pin attached bp = flask.Blueprint('not-pinned', __name__) @bp.route('/') def test_view(): pass # Assert the view does not have a `Pin` attached pin = Pin.get_from(test_view) self.assertIsNone(pin)
def test_s3_put(self): s3 = boto.s3.connect_to_region('us-east-1') writer = self.tracer.writer Pin(service=self.TEST_SERVICE, tracer=self.tracer).onto(s3) s3.create_bucket('mybucket') bucket = s3.get_bucket('mybucket') k = boto.s3.key.Key(bucket) k.key = 'foo' k.set_contents_from_string('bar') spans = writer.pop() assert spans # create bucket self.assertEqual(len(spans), 3) self.assertEqual(spans[0].get_tag('aws.operation'), 'create_bucket') self.assertEqual(spans[0].get_tag(http.STATUS_CODE), '200') self.assertEqual(spans[0].service, 'test-boto-tracing.s3') self.assertEqual(spans[0].resource, 's3.put') # get bucket self.assertEqual(spans[1].get_tag('aws.operation'), 'head_bucket') self.assertEqual(spans[1].resource, 's3.head') # put object self.assertEqual(spans[2].get_tag('aws.operation'), '_send_file_internal') self.assertEqual(spans[2].resource, 's3.put')
def get_tracer_and_connect(self): tracer = TestMongoEnginePatchConnectDefault.get_tracer_and_connect( self) Pin(service=self.TEST_SERVICE, tracer=tracer).onto(mongoengine.connect) mongoengine.connect(port=MONGO_CONFIG['port']) return tracer
def test_correct_span_names(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 0 pin = Pin('pin_name', tracer=tracer) traced_cursor = TracedCursor(cursor, pin) traced_cursor.execute('arg_1', kwarg1='kwarg1') self.assert_structure(dict(name='sql.query')) self.reset() traced_cursor.executemany('arg_1', kwarg1='kwarg1') self.assert_structure(dict(name='sql.query')) self.reset() traced_cursor.callproc('arg_1', 'arg2') self.assert_structure(dict(name='sql.query')) self.reset() traced_cursor.fetchone('arg_1', kwarg1='kwarg1') self.assert_has_no_spans() traced_cursor.fetchmany('arg_1', kwarg1='kwarg1') self.assert_has_no_spans() traced_cursor.fetchall('arg_1', kwarg1='kwarg1') self.assert_has_no_spans()
def test_ec2_client(self): ec2 = boto.ec2.connect_to_region('us-west-2') writer = self.tracer.writer Pin(service=self.TEST_SERVICE, tracer=self.tracer).onto(ec2) ec2.get_all_instances() spans = writer.pop() assert spans self.assertEqual(len(spans), 1) span = spans[0] self.assertEqual(span.get_tag('aws.operation'), 'DescribeInstances') self.assertEqual(span.get_tag(http.STATUS_CODE), '200') self.assertEqual(span.get_tag(http.METHOD), 'POST') self.assertEqual(span.get_tag('aws.region'), 'us-west-2') self.assertIsNone(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY)) # Create an instance ec2.run_instances(21) spans = writer.pop() assert spans self.assertEqual(len(spans), 1) span = spans[0] self.assertEqual(span.get_tag('aws.operation'), 'RunInstances') self.assertEqual(span.get_tag(http.STATUS_CODE), '200') self.assertEqual(span.get_tag(http.METHOD), 'POST') self.assertEqual(span.get_tag('aws.region'), 'us-west-2') self.assertEqual(span.service, 'test-boto-tracing.ec2') self.assertEqual(span.resource, 'ec2.runinstances') self.assertEqual(span.name, 'ec2.command') self.assertEqual(span.span_type, 'boto')
def test_when_pin_disabled_then_no_tracing(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 0 cursor.execute.return_value = '__result__' cursor.executemany.return_value = '__result__' tracer.enabled = False pin = Pin('pin_name', tracer=tracer) traced_cursor = FetchTracedCursor(cursor, pin) assert '__result__' == traced_cursor.execute('arg_1', kwarg1='kwarg1') assert len(tracer.writer.pop()) == 0 assert '__result__' == traced_cursor.executemany('arg_1', kwarg1='kwarg1') assert len(tracer.writer.pop()) == 0 cursor.callproc.return_value = 'callproc' assert 'callproc' == traced_cursor.callproc('arg_1', 'arg_2') assert len(tracer.writer.pop()) == 0 cursor.fetchone.return_value = 'fetchone' assert 'fetchone' == traced_cursor.fetchone('arg_1', 'arg_2') assert len(tracer.writer.pop()) == 0 cursor.fetchmany.return_value = 'fetchmany' assert 'fetchmany' == traced_cursor.fetchmany('arg_1', 'arg_2') assert len(tracer.writer.pop()) == 0 cursor.fetchall.return_value = 'fetchall' assert 'fetchall' == traced_cursor.fetchall('arg_1', 'arg_2') assert len(tracer.writer.pop()) == 0
def test_correct_span_names_can_be_overridden_by_pin(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 0 pin = Pin('pin_name', app='changed', tracer=tracer) traced_cursor = FetchTracedCursor(cursor, pin) traced_cursor.execute('arg_1', kwarg1='kwarg1') self.assert_structure(dict(name='changed.query')) self.reset() traced_cursor.executemany('arg_1', kwarg1='kwarg1') self.assert_structure(dict(name='changed.query')) self.reset() traced_cursor.callproc('arg_1', 'arg2') self.assert_structure(dict(name='changed.query')) self.reset() traced_cursor.fetchone('arg_1', kwarg1='kwarg1') self.assert_structure(dict(name='changed.query.fetchone')) self.reset() traced_cursor.fetchmany('arg_1', kwarg1='kwarg1') self.assert_structure(dict(name='changed.query.fetchmany')) self.reset() traced_cursor.fetchall('arg_1', kwarg1='kwarg1') self.assert_structure(dict(name='changed.query.fetchall')) self.reset()
def test_s3_client(self): s3 = self.session.create_client('s3', region_name='us-west-2') Pin(service=self.TEST_SERVICE, tracer=self.tracer).onto(s3) s3.list_buckets() s3.list_buckets() spans = self.get_spans() assert spans span = spans[0] self.assertEqual(len(spans), 2) self.assertEqual(span.get_tag('aws.operation'), 'ListBuckets') self.assertEqual(span.get_tag(http.STATUS_CODE), '200') self.assertEqual(span.service, 'test-botocore-tracing.s3') self.assertEqual(span.resource, 's3.listbuckets') # testing for span error self.reset() try: s3.list_objects(bucket='mybucket') except Exception: spans = self.get_spans() assert spans span = spans[0] self.assertEqual(span.error, 1) self.assertEqual(span.resource, 's3.listobjects')
def test_fetchmany_wrapped_is_called_and_returned(self): cursor = self.cursor cursor.rowcount = 0 cursor.fetchmany.return_value = '__result__' pin = Pin('pin_name', tracer=self.tracer) traced_cursor = TracedCursor(cursor, pin) assert '__result__' == traced_cursor.fetchmany('arg_1', kwarg1='kwarg1') cursor.fetchmany.assert_called_once_with('arg_1', kwarg1='kwarg1')
def test_rollback_is_traced(self): connection = self.connection tracer = self.tracer connection.rollback.return_value = None pin = Pin('pin_name', tracer=tracer) traced_connection = TracedConnection(connection, pin) traced_connection.rollback() assert tracer.writer.pop()[0].name == 'mock.connection.rollback' connection.rollback.assert_called_with()
def test_execute_wrapped_is_called_and_returned(self): cursor = self.cursor cursor.rowcount = 0 cursor.execute.return_value = '__result__' pin = Pin('pin_name', tracer=self.tracer) traced_cursor = FetchTracedCursor(cursor, pin) assert '__result__' == traced_cursor.execute('__query__', 'arg_1', kwarg1='kwarg1') cursor.execute.assert_called_once_with('__query__', 'arg_1', kwarg1='kwarg1')
def patch_conn(conn): tags = {t: getattr(conn, a) for t, a in CONN_ATTR_BY_TAG.items() if getattr(conn, a, '') != ''} pin = Pin(service='mysql', app='mysql', app_type=AppTypes.db, tags=tags) # grab the metadata from the conn wrapped = TracedConnection(conn, pin=pin) pin.onto(wrapped) return wrapped
def test_pin(self): # ensure a Pin can be attached to an instance obj = self.Obj() pin = Pin(service='metrics') pin.onto(obj) got = Pin.get_from(obj) assert got.service == pin.service assert got is pin
def test_executemany_wrapped_is_called_and_returned(self): cursor = self.cursor cursor.rowcount = 0 cursor.executemany.return_value = '__result__' pin = Pin('pin_name', tracer=self.tracer) traced_cursor = TracedCursor(cursor, pin) # DEV: We always pass through the result assert '__result__' == traced_cursor.executemany('__query__', 'arg_1', kwarg1='kwarg1') cursor.executemany.assert_called_once_with('__query__', 'arg_1', kwarg1='kwarg1')
def test_patch_unpatch(self): # Test patch idempotence patch() patch() es = elasticsearch.Elasticsearch(port=ELASTICSEARCH_CONFIG['port']) Pin(service=self.TEST_SERVICE, tracer=self.tracer).onto(es.transport) # Test index creation es.indices.create(index=self.ES_INDEX, ignore=400) spans = self.get_spans() self.reset() assert spans, spans assert len(spans) == 1 # Test unpatch self.reset() unpatch() es = elasticsearch.Elasticsearch(port=ELASTICSEARCH_CONFIG['port']) # Test index creation es.indices.create(index=self.ES_INDEX, ignore=400) spans = self.get_spans() self.reset() assert not spans, spans # Test patch again self.reset() patch() es = elasticsearch.Elasticsearch(port=ELASTICSEARCH_CONFIG['port']) Pin(service=self.TEST_SERVICE, tracer=self.tracer).onto(es.transport) # Test index creation es.indices.create(index=self.ES_INDEX, ignore=400) spans = self.get_spans() self.reset() assert spans, spans assert len(spans) == 1
def test_unpatch(self): kinesis = self.session.create_client('kinesis', region_name='us-east-1') Pin(service=self.TEST_SERVICE, tracer=self.tracer).onto(kinesis) unpatch() kinesis.list_streams() spans = self.get_spans() assert not spans, spans
def _patch_server(): if getattr(constants.GRPC_PIN_MODULE_SERVER, '__opentelemetry_patch', False): return setattr(constants.GRPC_PIN_MODULE_SERVER, '__opentelemetry_patch', True) Pin(service=config.grpc_server.service_name).onto( constants.GRPC_PIN_MODULE_SERVER) _w('grpc', 'server', _server_constructor_interceptor)
def test_cant_pin_with_slots(self): # ensure a Pin can't be attached if the __slots__ is defined class Obj(object): __slots__ = ['value'] obj = Obj() obj.value = 1 Pin(service='metrics').onto(obj) got = Pin.get_from(obj) assert got is None
def setUp(self): super(CeleryBaseTestCase, self).setUp() # instrument Celery and create an app with Broker and Result backends patch() self.pin = Pin(service='celery-unittest', tracer=self.tracer) self.app = Celery('celery.test_app', broker=BROKER_URL, backend=BACKEND_URL) # override pins to use our Dummy Tracer Pin.override(self.app, tracer=self.tracer)
def test_unpatch(self): lamb = boto.awslambda.connect_to_region('us-east-2') writer = self.tracer.writer Pin(service=self.TEST_SERVICE, tracer=self.tracer).onto(lamb) unpatch() # multiple calls lamb.list_functions() spans = writer.pop() assert not spans, spans
def test_cursor_analytics_default(self): cursor = self.cursor cursor.rowcount = 0 cursor.execute.return_value = '__result__' pin = Pin('pin_name', tracer=self.tracer) traced_cursor = TracedCursor(cursor, pin) # DEV: We always pass through the result assert '__result__' == traced_cursor.execute('__query__', 'arg_1', kwarg1='kwarg1') span = self.tracer.writer.pop()[0] self.assertIsNone(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY))
def test_double_patch(self): sqs = self.session.create_client('sqs', region_name='us-east-1') Pin(service=self.TEST_SERVICE, tracer=self.tracer).onto(sqs) patch() patch() sqs.list_queues() spans = self.get_spans() assert spans self.assertEqual(len(spans), 1)
def _patch_client(): if getattr(constants.GRPC_PIN_MODULE_CLIENT, '__opentelemetry_patch', False): return setattr(constants.GRPC_PIN_MODULE_CLIENT, '__opentelemetry_patch', True) Pin(service=config.grpc.service_name).onto( constants.GRPC_PIN_MODULE_CLIENT) _w('grpc', 'insecure_channel', _client_channel_interceptor) _w('grpc', 'secure_channel', _client_channel_interceptor) _w('grpc', 'intercept_channel', intercept_channel)
def test_traced_client_analytics(self): with self.override_config( 'botocore', dict(analytics_enabled=True, analytics_sample_rate=0.5)): ec2 = self.session.create_client('ec2', region_name='us-west-2') Pin(service=self.TEST_SERVICE, tracer=self.tracer).onto(ec2) ec2.describe_instances() spans = self.get_spans() assert spans span = spans[0] self.assertEqual(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY), 0.5)
def patch_conn(conn, *args, **kwargs): tags = { t: kwargs[k] if k in kwargs else args[p] for t, (k, p) in KWPOS_BY_TAG.items() if k in kwargs or len(args) > p } tags[net.TARGET_PORT] = conn.port pin = Pin(service='mysql', app='mysql', app_type=AppTypes.db, tags=tags) # grab the metadata from the conn wrapped = TracedConnection(conn, pin=pin) pin.onto(wrapped) return wrapped
def test_connection_analytics_with_rate(self): with self.override_config( 'dbapi2', dict(analytics_enabled=True, analytics_sample_rate=0.5) ): connection = self.connection tracer = self.tracer connection.commit.return_value = None pin = Pin('pin_name', tracer=tracer) traced_connection = TracedConnection(connection, pin) traced_connection.commit() span = tracer.writer.pop()[0] self.assertIsNone(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY))