def setUp(self): self.exporter = MockDatadogSpanExporter() self.span_processor = datadog.DatadogExportSpanProcessor(self.exporter) tracer_provider = trace.TracerProvider() tracer_provider.add_span_processor(self.span_processor) self.tracer_provider = tracer_provider self.tracer = tracer_provider.get_tracer(__name__)
def test_batch_span_processor_reset_timeout(self): """Test that the scheduled timeout is reset on cycles without spans""" delay = 50 # pylint: disable=protected-access exporter = MockDatadogSpanExporter() exporter._agent_writer.write.side_effect = lambda spans: time.sleep( 0.05) span_processor = datadog.DatadogExportSpanProcessor( exporter, schedule_delay_millis=delay) tracer_provider = trace.TracerProvider() tracer_provider.add_span_processor(span_processor) tracer = tracer_provider.get_tracer(__name__) with mock.patch.object(span_processor.condition, "wait") as mock_wait: with tracer.start_span("foo"): pass # give some time for exporter to loop # since wait is mocked it should return immediately time.sleep(0.1) mock_wait_calls = list(mock_wait.mock_calls) # find the index of the call that processed the singular span for idx, wait_call in enumerate(mock_wait_calls): _, args, __ = wait_call if args[0] <= 0: after_calls = mock_wait_calls[idx + 1:] break self.assertTrue(all(args[0] >= 0.05 for _, args, __ in after_calls)) span_processor.shutdown()
def test_span_processor_accepts_parent_context(self): span_processor = mock.Mock( wraps=datadog.DatadogExportSpanProcessor(self.exporter)) tracer_provider = trace.TracerProvider() tracer_provider.add_span_processor(span_processor) tracer = tracer_provider.get_tracer(__name__) context = Context() span = tracer.start_span("foo", context=context) span_processor.on_start.assert_called_once_with(span, parent_context=context)
def test_span_processor_lossless(self): """Test that no spans are lost when sending max_trace_size spans""" span_processor = datadog.DatadogExportSpanProcessor(self.exporter, max_trace_size=128) tracer_provider = trace.TracerProvider() tracer_provider.add_span_processor(span_processor) tracer = tracer_provider.get_tracer(__name__) with tracer.start_as_current_span("root"): for _ in range(127): with tracer.start_span("foo"): pass self.assertTrue(span_processor.force_flush()) datadog_spans = get_spans(tracer, self.exporter) self.assertEqual(len(datadog_spans), 128) tracer_provider.shutdown()
def test_span_processor_dropped_spans(self): """Test that spans are lost when exceeding max_trace_size spans""" span_processor = datadog.DatadogExportSpanProcessor(self.exporter, max_trace_size=128) tracer_provider = trace.TracerProvider() tracer_provider.add_span_processor(span_processor) tracer = tracer_provider.get_tracer(__name__) with tracer.start_as_current_span("root"): for _ in range(127): with tracer.start_span("foo"): pass with self.assertLogs(level=logging.WARNING): with tracer.start_span("one-too-many"): pass self.assertTrue(span_processor.force_flush()) datadog_spans = get_spans(tracer, self.exporter) self.assertEqual(len(datadog_spans), 128) tracer_provider.shutdown()
def test_span_processor_scheduled_delay(self): """Test that spans are exported each schedule_delay_millis""" delay = 300 span_processor = datadog.DatadogExportSpanProcessor( self.exporter, schedule_delay_millis=delay) tracer_provider = trace.TracerProvider() tracer_provider.add_span_processor(span_processor) tracer = tracer_provider.get_tracer(__name__) with tracer.start_span("foo"): pass time.sleep(delay / (1e3 * 2)) datadog_spans = get_spans(tracer, self.exporter, shutdown=False) self.assertEqual(len(datadog_spans), 0) time.sleep(delay / (1e3 * 2) + 0.01) datadog_spans = get_spans(tracer, self.exporter, shutdown=False) self.assertEqual(len(datadog_spans), 1) tracer_provider.shutdown()