コード例 #1
0
    def get_formatted_metrics(self, metrics, enable_meta_metrics=False):
        # type: (Iterable[Metric], bool) -> List[six.binary_type]
        meta_timer = None
        if enable_meta_metrics:
            meta_timer = Timer('', resolution=TimerResolution.MICROSECONDS)

        formatted_metrics = []
        for metric in metrics:
            if metric.value is None:
                continue

            existing_tags_string = self._global_tags_string

            if isinstance(metric, Counter):
                type_label = self.METRIC_TYPE_COUNTER
            elif isinstance(metric, Gauge):
                type_label = self.METRIC_TYPE_GAUGE
                existing_tags_string = self._global_gauge_tags_string
            elif isinstance(metric, Timer):
                type_label = self._metric_type_timer
            elif isinstance(metric, Histogram):
                type_label = self._metric_type_histogram
            else:
                continue

            metric_tags_string = self._generate_tag_string(
                metric.tags, existing_tags_string)

            formatted_metrics.append(b'%s:%d|%s%s' % (self._get_binary_value(
                metric.name), metric.value, type_label, metric_tags_string))

        if not formatted_metrics:
            return []

        if meta_timer:
            meta_timer.stop()
            formatted_metrics.insert(
                0,
                b'pymetrics.meta.publish.statsd.format_metrics:%d|%s%s' % (
                    cast(int, meta_timer.value),
                    self._metric_type_timer,
                    self._global_tags_string,
                ),
            )

        return formatted_metrics
コード例 #2
0
    def get_formatted_metrics(self, metrics, enable_meta_metrics=False):
        # type: (Iterable[Metric], bool) -> List[six.binary_type]
        meta_timer = None
        if enable_meta_metrics:
            meta_timer = Timer('', resolution=TimerResolution.MICROSECONDS)

        formatted_metrics = []
        for metric in metrics:
            if metric.value is None:
                continue

            if isinstance(metric, Counter):
                type_label = self.METRIC_TYPE_COUNTER
            elif isinstance(metric, Gauge):
                type_label = self.METRIC_TYPE_GAUGE
            elif isinstance(metric, Timer):
                type_label = self._metric_type_timer
            elif isinstance(metric, Histogram):
                type_label = self._metric_type_histogram
            else:
                continue  # not possible unless a new metric type is added

            formatted_metrics.append(
                b'%s:%d|%s' % (self._get_binary_value(metric.name), metric.value, type_label)
            )

        if not formatted_metrics:
            return []

        if meta_timer:
            meta_timer.stop()
            formatted_metrics.insert(
                0,
                b'pymetrics.meta.publish.statsd.format_metrics:%d|%s' % (
                    cast(int, meta_timer.value),
                    self._metric_type_timer,
                )
            )

        return formatted_metrics
コード例 #3
0
    def get_all_metrics(self):  # type: () -> List[Metric]
        meta_timer = None
        if self._configuration and self._configuration.enable_meta_metrics is True:
            meta_timer = Timer('pymetrics.meta.recorder.get_all_metrics',
                               resolution=TimerResolution.MICROSECONDS)

        metrics = []  # type: List[Metric]
        metrics.extend(six.itervalues(self.counters))
        metrics.extend(gauge for gauges in six.itervalues(self.gauges)
                       for gauge in gauges if gauge.value is not None)
        metrics.extend(histogram
                       for histograms in six.itervalues(self.histograms)
                       for histogram in histograms
                       if histogram.value is not None)
        metrics.extend(timer for timers in six.itervalues(self.timers)
                       for timer in timers if timer.value is not None)

        if meta_timer:
            meta_timer.stop()
            metrics.insert(0, meta_timer)

        return metrics
コード例 #4
0
def test_timer():
    timer = Timer('test.timer.1', tag_4='value_4')

    assert timer.name == 'test.timer.1'
    assert timer.tags['tag_4'] == 'value_4'
    assert timer.value is None

    timer = Timer('test.timer.2', initial_value=3.75)

    assert timer.name == 'test.timer.2'
    assert not timer.tags
    assert timer.value == 4

    with freezegun.freeze_time() as frozen_time:
        timer.start()
        frozen_time.tick(_milliseconds(15))
        timer.stop()

        assert timer.value == 15

        timer.start()
        frozen_time.tick(_milliseconds(27))
        timer.stop()

        assert timer.value == 42

        with timer:
            frozen_time.tick(_milliseconds(8))
            frozen_time.tick(_microseconds(100))

        assert timer.value == 50

        def around(foo, bar):
            assert foo == 'baz'
            assert bar == 'qux'
            frozen_time.tick(_milliseconds(11))
            frozen_time.tick(_microseconds(600))
            return 'Ipsum'

        assert timer.record_over_function(around, 'baz', bar='qux') == 'Ipsum'
        assert timer.value == 62

    timer = Timer('test.timer.3', resolution=TimerResolution.MICROSECONDS)

    with freezegun.freeze_time() as frozen_time:
        timer.start()
        frozen_time.tick(_milliseconds(1))
        frozen_time.tick(_microseconds(103))
        timer.stop()

        assert timer.value == 1103

        with timer:
            frozen_time.tick(_microseconds(209))

        assert timer.value == 1312

        timer.start()
        assert timer.value is None

        frozen_time.tick(_milliseconds(2))
        timer.stop()
        assert timer.value == 3312

    assert repr(timer) == 'Timer(name="test.timer.3", value=3312)'

    # make sure no error is raised, nothing happens
    timer.stop()
    timer.stop()
    timer.stop()

    assert repr(timer) == 'Timer(name="test.timer.3", value=3312)'
コード例 #5
0
    def test_metrics(self):
        p_metrics = [
            self._counter('foo.bar'),
            self._counter('baz.qux'),
            Gauge('a.b', initial_value=4),
            Gauge('a.b', initial_value=7),
            Gauge('a.b', initial_value=5),
            Gauge('c.d', initial_value=3),
        ]  # type: List[Metric]

        timer = Timer('one.two')
        timer.stop()
        p_metrics.append(timer)

        with freezegun.freeze_time() as frozen_time:
            timer = Timer('one.two')
            frozen_time.tick(self._milliseconds(50))
            timer.stop()
            p_metrics.append(timer)

            timer = Timer('one.two')
            frozen_time.tick(self._milliseconds(30))
            timer.stop()
            p_metrics.append(timer)

            timer = Timer('three.four')
            frozen_time.tick(self._milliseconds(10))
            timer.stop()
            p_metrics.append(timer)

        p_metrics.extend([
            Histogram('h.foo', initial_value=1),
            Histogram('h.foo', initial_value=3),
            Histogram('h.foo', initial_value=2),
            Histogram('h.bar', initial_value=77),
        ])

        publisher = SqlitePublisher()
        publisher.publish(p_metrics)

        connection = SqlitePublisher.get_connection()
        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_counters WHERE metric_name = 'foo.bar';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'foo.bar'
            assert metrics[0][str('metric_value')] == 1
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_counters WHERE metric_name = 'baz.qux';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'baz.qux'
            assert metrics[0][str('metric_value')] == 1
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_gauges WHERE metric_name = 'a.b';")
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'a.b'
            assert metrics[0][str('metric_value')] == 5
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_gauges WHERE metric_name = 'c.d';")
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'c.d'
            assert metrics[0][str('metric_value')] == 3
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_timers WHERE metric_name = 'one.two';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 3
            assert metrics[0][str('metric_name')] == 'one.two'
            assert metrics[0][str('metric_value')] < 0.001
            assert metrics[1][str('metric_name')] == 'one.two'
            assert 0.05 <= metrics[1][str('metric_value')] < 0.06
            assert metrics[2][str('metric_name')] == 'one.two'
            assert 0.03 <= metrics[2][str('metric_value')] < 0.04
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_timers WHERE metric_name = 'three.four';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'three.four'
            assert 0.01 <= metrics[0][str('metric_value')] < 0.02
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_histograms WHERE metric_name = 'h.foo';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 3
            assert metrics[0][str('metric_name')] == 'h.foo'
            assert metrics[0][str('metric_value')] == 1
            assert metrics[1][str('metric_name')] == 'h.foo'
            assert metrics[1][str('metric_value')] == 3
            assert metrics[2][str('metric_name')] == 'h.foo'
            assert metrics[2][str('metric_value')] == 2
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_histograms WHERE metric_name = 'h.bar';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'h.bar'
            assert metrics[0][str('metric_value')] == 77
        finally:
            cursor.close()

        p_metrics = [
            self._counter('foo.bar'),
            Gauge('a.b', initial_value=22),
            Gauge('c.d', initial_value=11),
        ]

        with freezegun.freeze_time() as frozen_time:
            timer = Timer('three.four',
                          resolution=TimerResolution.MICROSECONDS)
            frozen_time.tick(self._milliseconds(20))
            timer.stop()
            p_metrics.append(timer)

        p_metrics.append(Histogram('h.foo', initial_value=8))

        publisher = SqlitePublisher()
        publisher.initialize_if_necessary()
        publisher.publish(p_metrics)

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_counters WHERE metric_name = 'foo.bar';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 2
            assert metrics[0][str('metric_name')] == 'foo.bar'
            assert metrics[0][str('metric_value')] == 1
            assert metrics[1][str('metric_name')] == 'foo.bar'
            assert metrics[1][str('metric_value')] == 1
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_counters WHERE metric_name = 'baz.qux';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'baz.qux'
            assert metrics[0][str('metric_value')] == 1
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_gauges WHERE metric_name = 'a.b';")
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'a.b'
            assert metrics[0][str('metric_value')] == 22
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_gauges WHERE metric_name = 'c.d';")
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'c.d'
            assert metrics[0][str('metric_value')] == 11
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_timers WHERE metric_name = 'one.two';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 3
            assert metrics[0][str('metric_name')] == 'one.two'
            assert metrics[0][str('metric_value')] < 0.001
            assert metrics[1][str('metric_name')] == 'one.two'
            assert 0.05 <= metrics[1][str('metric_value')] < 0.06
            assert metrics[2][str('metric_name')] == 'one.two'
            assert 0.03 <= metrics[2][str('metric_value')] < 0.04
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_timers WHERE metric_name = 'three.four';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 2
            assert metrics[0][str('metric_name')] == 'three.four'
            assert 0.01 <= metrics[0][str('metric_value')] < 0.02
            assert metrics[1][str('metric_name')] == 'three.four'
            assert 0.02 <= metrics[1][str('metric_value')] < 0.03
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_histograms WHERE metric_name = 'h.foo';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 4
            assert metrics[0][str('metric_name')] == 'h.foo'
            assert metrics[0][str('metric_value')] == 1
            assert metrics[1][str('metric_name')] == 'h.foo'
            assert metrics[1][str('metric_value')] == 3
            assert metrics[2][str('metric_name')] == 'h.foo'
            assert metrics[2][str('metric_value')] == 2
            assert metrics[3][str('metric_name')] == 'h.foo'
            assert metrics[3][str('metric_value')] == 8
        finally:
            cursor.close()

        cursor = connection.cursor()
        try:
            # noinspection PyTypeChecker
            cursor.execute(
                "SELECT * FROM pymetrics_histograms WHERE metric_name = 'h.bar';"
            )
            metrics = list(cursor.fetchall())

            assert len(metrics) == 1
            assert metrics[0][str('metric_name')] == 'h.bar'
            assert metrics[0][str('metric_value')] == 77
        finally:
            cursor.close()
コード例 #6
0
    def _send_chunked_payload(self, payload, number_of_metrics, error_logger=None, enable_meta_metrics=False):
        # type: (six.binary_type, int, six.text_type, bool) -> None
        meta_timer = None
        error = error_max_packet = False
        sock = None
        try:
            if enable_meta_metrics:
                meta_timer = Timer('', resolution=TimerResolution.MICROSECONDS)

            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            sock.settimeout(self.timeout)
            sock.connect((self.host, self.port))
            sock.sendall(payload)
        except Exception as e:
            error = True
            if isinstance(e, socket.error) and e.errno == errno.EMSGSIZE:
                error_max_packet = True

            if error_logger:
                extra = {'data': {
                    'payload_length': len(payload),
                    'num_metrics': number_of_metrics,
                    'enable_meta_metrics': enable_meta_metrics,
                }}
                if error_max_packet:
                    logging.getLogger(error_logger).error(
                        'Failed to send metrics to statsd because UDP packet too big',
                        extra=extra,
                    )
                else:
                    logging.getLogger(error_logger).exception(
                        'Failed to send metrics to statsd {}:{}'.format(self.host, self.port),
                        extra=extra,
                    )
        finally:
            if sock:
                # noinspection PyBroadException
                try:
                    sock.close()
                except Exception:
                    pass
            if meta_timer:
                meta_timer.stop()

        if enable_meta_metrics:
            num_bytes = len(payload)  # TODO temporary; the length of the packet that we tried to send

            payload = b'pymetrics.meta.publish.statsd.send:1|%s' % self.METRIC_TYPE_COUNTER

            payload += b'\npymetrics.meta.publish.statsd.send.num_metrics:%d|%s' % (
                number_of_metrics,
                self._metric_type_histogram
            )

            if meta_timer:
                payload += b'\npymetrics.meta.publish.statsd.send.timer:%d|%s' % (
                    cast(int, meta_timer.value),
                    self._metric_type_timer,
                )

            if error:
                if error_max_packet:
                    payload += b'\npymetrics.meta.publish.statsd.send.error.max_packet:1|%s' % self.METRIC_TYPE_COUNTER
                else:
                    payload += b'\npymetrics.meta.publish.statsd.send.error.unknown:1|%s' % self.METRIC_TYPE_COUNTER

            # TODO The following three stats are temporary, to test out potential MTU problems noted above
            if num_bytes >= MAX_IPV4_PAYLOAD_SIZE_BYTES:
                payload += b'\npymetrics.meta.publish.statsd.send.exceeds_max_packet:1|%s' % self.METRIC_TYPE_COUNTER
            if num_bytes >= MAX_GIG_E_PAYLOAD_SIZE_BYTES:
                payload += b'\npymetrics.meta.publish.statsd.send.exceeds_max_gig_e:1|%s' % self.METRIC_TYPE_COUNTER
            if num_bytes >= MAX_FAST_E_PAYLOAD_SIZE_BYTES:
                payload += b'\npymetrics.meta.publish.statsd.send.exceeds_max_fast_e:1|%s' % self.METRIC_TYPE_COUNTER

            sock = None
            # noinspection PyBroadException
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                sock.settimeout(self.timeout)
                sock.connect((self.host, self.port))
                sock.sendall(payload)
            except Exception:
                if error_logger:
                    logging.getLogger(error_logger).exception(
                        'Failed to send meta metrics to statsd {}:{}'.format(self.host, self.port),
                    )
            finally:
                if sock:
                    # noinspection PyBroadException
                    try:
                        sock.close()
                    except Exception:
                        pass