def test_execute_wrapped_is_called_and_returned(self): cursor = self.cursor cursor.rowcount = 0 pin = Pin('pin_name', tracer=self.tracer) traced_cursor = TracedCursor(cursor, pin) assert traced_cursor is traced_cursor.execute( '__query__', 'arg_1', kwarg1='kwarg1') cursor.execute.assert_called_once_with('__query__', 'arg_1', kwarg1='kwarg1')
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.pop_spans()[0] self.assertIsNone(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY))
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_default_service(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 123 pin = Pin(None, app='my_app', tracer=tracer, tags={'pin1': 'value_pin1'}) traced_cursor = TracedCursor(cursor, pin, None) def method(): pass traced_cursor._trace_method(method, 'my_name', 'my_resource', {'extra1': 'value_extra1'}) span = tracer.writer.pop()[0] # type: Span assert span.service == "db"
def test_default_service(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 123 pin = Pin(None, app="my_app", tracer=tracer, tags={"pin1": "value_pin1"}) traced_cursor = TracedCursor(cursor, pin, None) def method(): pass traced_cursor._trace_method(method, "my_name", "my_resource", {"extra1": "value_extra1"}) span = tracer.pop()[0] # type: Span assert span.service == "db"
def test_cursor_analytics_without_rate(self): with self.override_config("dbapi2", dict(analytics_enabled=True)): 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.pop_spans()[0] self.assertEqual(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY), 1.0)
def test_service_cfg_and_pin(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 123 pin = Pin("pin-svc", app='my_app', tracer=tracer, tags={'pin1': 'value_pin1'}) cfg = AttrDict(_default_service="cfg-svc") traced_cursor = TracedCursor(cursor, pin, cfg) def method(): pass traced_cursor._trace_method(method, 'my_name', 'my_resource', {'extra1': 'value_extra1'}) span = tracer.writer.pop()[0] # type: Span assert span.service == "pin-svc"
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_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 = TracedCursor(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_service_cfg_and_pin(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 123 pin = Pin("pin-svc", app="my_app", tracer=tracer, tags={"pin1": "value_pin1"}) cfg = AttrDict(_default_service="cfg-svc") traced_cursor = TracedCursor(cursor, pin, cfg) def method(): pass traced_cursor._trace_method(method, "my_name", "my_resource", {"extra1": "value_extra1"}) span = tracer.pop()[0] # type: Span assert span.service == "pin-svc"
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 = TracedCursor(cursor, pin, {}) assert "__result__" == traced_cursor.execute("arg_1", kwarg1="kwarg1") assert len(tracer.pop()) == 0 assert "__result__" == traced_cursor.executemany("arg_1", kwarg1="kwarg1") assert len(tracer.pop()) == 0 cursor.callproc.return_value = "callproc" assert "callproc" == traced_cursor.callproc("arg_1", "arg_2") assert len(tracer.pop()) == 0 cursor.fetchone.return_value = "fetchone" assert "fetchone" == traced_cursor.fetchone("arg_1", "arg_2") assert len(tracer.pop()) == 0 cursor.fetchmany.return_value = "fetchmany" assert "fetchmany" == traced_cursor.fetchmany("arg_1", "arg_2") assert len(tracer.pop()) == 0 cursor.fetchall.return_value = "fetchall" assert "fetchall" == traced_cursor.fetchall("arg_1", "arg_2") assert len(tracer.pop()) == 0
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_cursor_analytics_without_rate(self): with self.override_config('dbapi2', dict(analytics_enabled=True)): 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.assertEqual(span.get_metric(ANALYTICS_SAMPLE_RATE_KEY), 1.0)
def test_cfg_service(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 123 pin = Pin(None, tracer=tracer, tags={"pin1": "value_pin1"}) cfg = IntegrationConfig(None, "db-test", service="cfg-service") traced_cursor = TracedCursor(cursor, pin, cfg) def method(): pass traced_cursor._trace_method(method, "my_name", "my_resource", {"extra1": "value_extra1"}) span = tracer.pop()[0] # type: Span assert span.service == "cfg-service"
def test_django_traced_cursor_backward_compatibility(self): cursor = self.cursor tracer = self.tracer # Django integration used to have its own TracedCursor implementation. When we replaced such custom # implementation with the generic dbapi traced cursor, we had to make sure to add the tag 'sql.rows' that was # set by the legacy replaced implementation. cursor.rowcount = 123 pin = Pin('my_service', app='my_app', tracer=tracer, tags={'pin1': 'value_pin1'}) traced_cursor = TracedCursor(cursor, pin, {}) def method(): pass traced_cursor._trace_method(method, 'my_name', 'my_resource', {'extra1': 'value_extra1'}) span = tracer.writer.pop()[0] # type: Span # Row count assert span.get_metric('db.rowcount') == 123, 'Row count is set as a metric' assert span.get_metric('sql.rows') == 123, 'Row count is set as a tag (for legacy django cursor replacement)'
def test_span_info(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 123 pin = Pin('my_service', app='my_app', tracer=tracer, tags={'pin1': 'value_pin1'}) traced_cursor = TracedCursor(cursor, pin) def method(): pass traced_cursor._trace_method(method, 'my_name', 'my_resource', {'extra1': 'value_extra1'}) span = tracer.writer.pop()[0] # type: Span assert span.meta['pin1'] == 'value_pin1', 'Pin tags are preserved' assert span.meta['extra1'] == 'value_extra1', 'Extra tags are merged into pin tags' assert span.name == 'my_name', 'Span name is respected' assert span.service == 'my_service', 'Service from pin' assert span.resource == 'my_resource', 'Resource is respected' assert span.span_type == 'sql', 'Span has the correct span type' # Row count assert span.get_metric('db.rowcount') == 123, 'Row count is set as a metric' assert span.get_metric('sql.rows') == 123, 'Row count is set as a tag (for legacy django cursor replacement)'
def test_span_info(self): cursor = self.cursor tracer = self.tracer cursor.rowcount = 123 pin = Pin("my_service", app="my_app", tracer=tracer, tags={"pin1": "value_pin1"}) traced_cursor = TracedCursor(cursor, pin, {}) def method(): pass traced_cursor._trace_method(method, "my_name", "my_resource", {"extra1": "value_extra1"}) span = tracer.pop()[0] # type: Span # Only measure if the name passed matches the default name (e.g. `sql.query` and not `sql.query.fetchall`) assert_is_not_measured(span) assert span.meta["pin1"] == "value_pin1", "Pin tags are preserved" assert span.meta["extra1"] == "value_extra1", "Extra tags are merged into pin tags" assert span.name == "my_name", "Span name is respected" assert span.service == "my_service", "Service from pin" assert span.resource == "my_resource", "Resource is respected" assert span.span_type == "sql", "Span has the correct span type" # Row count assert span.get_metric("db.rowcount") == 123, "Row count is set as a metric" assert span.get_metric("sql.rows") == 123, "Row count is set as a tag (for legacy django cursor replacement)"
def test_django_traced_cursor_backward_compatibility(self): cursor = self.cursor tracer = self.tracer # Django integration used to have its own TracedCursor implementation. When we replaced such custom # implementation with the generic dbapi traced cursor, we had to make sure to add the tag 'sql.rows' that was # set by the legacy replaced implementation. cursor.rowcount = 123 pin = Pin("my_service", tracer=tracer, tags={"pin1": "value_pin1"}) cfg = IntegrationConfig(None, "db-test") traced_cursor = TracedCursor(cursor, pin, cfg) def method(): pass traced_cursor._trace_method(method, "my_name", "my_resource", {"extra1": "value_extra1"}) span = tracer.pop()[0] # type: Span # Row count assert span.get_metric( "db.rowcount") == 123, "Row count is set as a metric" assert span.get_metric( "sql.rows" ) == 123, "Row count is set as a tag (for legacy django cursor replacement)"
def test_callproc_can_handle_arbitrary_args(self): cursor = self.cursor tracer = self.tracer pin = Pin("pin_name", tracer=tracer) cursor.callproc.return_value = "gme --> moon" traced_cursor = TracedCursor(cursor, pin, {}) traced_cursor.callproc("proc_name", "arg_1") spans = self.tracer.writer.pop() assert len(spans) == 1 self.reset() traced_cursor.callproc("proc_name", "arg_1", "arg_2") spans = self.tracer.writer.pop() assert len(spans) == 1 self.reset() traced_cursor.callproc("proc_name", "arg_1", "arg_2", {"arg_key": "arg_value"}) spans = self.tracer.writer.pop() assert len(spans) == 1 self.reset()
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')) assert_is_measured(self.get_root_span()) self.reset() traced_cursor.executemany('arg_1', kwarg1='kwarg1') self.assert_structure(dict(name='sql.query')) assert_is_measured(self.get_root_span()) self.reset() traced_cursor.callproc('arg_1', 'arg2') self.assert_structure(dict(name='sql.query')) assert_is_measured(self.get_root_span()) 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_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")) assert_is_measured(self.get_root_span()) self.reset() traced_cursor.executemany("arg_1", kwarg1="kwarg1") self.assert_structure(dict(name="sql.query")) assert_is_measured(self.get_root_span()) self.reset() traced_cursor.callproc("arg_1", "arg2") self.assert_structure(dict(name="sql.query")) assert_is_measured(self.get_root_span()) 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 cursor(self): return TracedCursor(Cursor(), pin, {})
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 = TracedCursor(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_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()