def __init__(self, transport_handler, queue_capacity=100, batch_size=10, flush_interval=DEFAULT_FLUSH_INTERVAL, io_loop=None, error_reporter=None, metrics_factory=None, **kwargs): """ :param transport_handler: Callback function that takes a message parameter and handles logging it :param queue_capacity: how many spans we can hold in memory before starting to drop spans :param batch_size: how many spans we can submit at once to Collector :param flush_interval: how often the auto-flush is called (in seconds) :param io_loop: which IOLoop to use. :param error_reporter: :param metrics_factory: an instance of MetricsFactory class, or None. :param kwargs: 'logger' :return: """ from threading import Lock self.transport_handler = transport_handler self.queue_capacity = queue_capacity self.batch_size = batch_size self.metrics_factory = metrics_factory or \ LegacyMetricsFactory(Metrics()) self.metrics = ReporterMetrics(self.metrics_factory) self.error_reporter = error_reporter or ErrorReporter(Metrics()) self.logger = kwargs.get('logger', default_logger) if queue_capacity < batch_size: raise ValueError('Queue capacity cannot be less than batch size') self.io_loop = io_loop if self.io_loop is None: self.logger.error('Zipkin Reporter has no IOLoop') elif not six.callable(self.transport_handler): self.logger.error('Zipkin Reporter has no transport handler') else: self.queue = tornado.queues.Queue(maxsize=queue_capacity) self.stop = object() self.stopped = False self.stop_lock = Lock() self.flush_interval = flush_interval or None self.io_loop.spawn_callback(self._consume_queue)
def test_legacy_metrics_factory_noop(): mf = LegacyMetricsFactory(Metrics()) counter = mf.create_counter(name='foo', tags={'a': 'counter'}) counter(1) gauge = mf.create_gauge(name='bar', tags={'a': 'gauge'}) gauge(2) timing = mf.create_timer(name='rawr', tags={'a': 'timer'}) timing(3)
def test_legacy_metrics_factory(): cm = mock.MagicMock() tm = mock.MagicMock() gm = mock.MagicMock() mf = LegacyMetricsFactory(Metrics(count=cm, timing=tm, gauge=gm)) counter = mf.create_counter(name='foo', tags={'k': 'v', 'a': 'counter'}) counter(1) assert cm.call_args == (('foo.a_counter.k_v', 1), ) gauge = mf.create_gauge(name='bar', tags={'k': 'v', 'a': 'gauge'}) gauge(2) assert gm.call_args == (('bar.a_gauge.k_v', 2), ) timing = mf.create_timer(name='rawr', tags={'k': 'v', 'a': 'timer'}) timing(3) assert tm.call_args == (('rawr.a_timer.k_v', 0.003), ) mf = LegacyMetricsFactory(Metrics(timing=tm)) timing = mf.create_timer(name='wow') timing(4) assert tm.call_args == (('wow', 0.004),), \ 'building a timer with no tags should work'
def test_submit_failure(self): reporter, sender = self._new_reporter(batch_size=1) reporter.error_reporter = ErrorReporter(metrics=Metrics(), logger=logging.getLogger()) reporter_failure_key = 'jaeger:reporter_spans.result_err' assert reporter_failure_key not in reporter.metrics_factory.counters # simulate exception in send reporter._send = mock.MagicMock(side_effect=ValueError()) reporter.report_span(self._new_span('1')) yield self._wait_for( lambda: reporter_failure_key in reporter.metrics_factory.counters) assert 1 == reporter.metrics_factory.counters.get(reporter_failure_key) # silly test, for code coverage only yield reporter._submit([])
def test_gauge_func_called(self): m = mock.MagicMock() metrics = Metrics(gauge=m) metrics.gauge('foo', 1) assert m.call_args == (('foo', 1), )
def test_count_func_called(self): m = mock.MagicMock() metrics = Metrics(count=m) metrics.count('foo', 1) assert m.called_with('foo', 1)
def test_metrics_timing_func_noops_if_given_uncallable_timing_found(): metrics = Metrics(timing=123) metrics.timing('foo', 1)
def __init__(self): super(FakeMetricsFactory, self).__init__(Metrics(count=self._incr_count)) self.counters = {}
def test_metrics_gauge_func_noops_if_given_uncallable_gauge_found(): metrics = Metrics(gauge=123) metrics.gauge('foo', 1)
def test_metrics_timing_func_noops_if_given_uncallable_timing_found(): metrics = Metrics(timing=123) metrics.timing('foo', 1)
def test_metrics_count_func_noops_if_given_uncallable_count_found(): metrics = Metrics(count=123) metrics.count('foo', 1)
def test_metrics_gauge_func_called(): m = mock.MagicMock() metrics = Metrics(gauge=m) metrics.gauge('foo', 1) assert m.call_args == (('foo', 1),)
def test_metrics_timing_func_called(): m = mock.MagicMock() metrics = Metrics(timing=m) metrics.timing('foo', 1) assert m.call_args == (('foo', 1),)
def test_metrics_count_func_called(): m = mock.MagicMock() metrics = Metrics(count=m) metrics.count('foo', 1) assert m.call_args == (('foo', 1),)
def test_count_func_noops_if_given_uncallable_count_found(self): metrics = Metrics(count=123) metrics.count('foo', 1)
def test_gauge_func_noops_if_given_uncallable_gauge_found(self): metrics = Metrics(gauge=123) metrics.gauge('foo', 1)
def test_metrics_count_func_called(): m = mock.MagicMock() metrics = Metrics(count=m) metrics.count('foo', 1) assert m.call_args == (('foo', 1), )
def test_metrics_timing_func_called(): m = mock.MagicMock() metrics = Metrics(timing=m) metrics.timing('foo', 1) assert m.call_args == (('foo', 1), )
def test_count_func_called(self): m = mock.MagicMock() metrics = Metrics(count=m) metrics.count('foo', 1) assert m.called_with('foo', 1)