Метрики — сервисные метрики

задняя часть

Введение

MetricsВ качестве библиотеки измерений для мониторинга показателей она предоставляет множество модулей для предоставления вспомогательной статистики для сторонних библиотек или приложений. Метрики предоставляют датчик, счетчик, измеритель, гистограмму, таймер и другие классы инструментов измерения, а также функции проверки работоспособности.

Конфигурация Maven

metrics-core — это основная библиотека метрик, которая определяет различные метрики и на которую нужно ссылаться в pom.xml.

<dependencies>
    <dependency>
        <groupId>io.dropwizard.metrics</groupId>
        <artifactId>metrics-core</artifactId>
        <version>3.1.0</version>
    </dependency>
</dependencies>

MetricRegistry

Класс MetricRegistry — это основной контейнер, внутри которого используется ConcurrentHashMap для поддержки всех элементов метрик мониторинга. Основной код регистрации индикатора:

    public <T extends Metric> T register(String name, T metric) throws IllegalArgumentException {
        if (metric instanceof MetricSet) {
            registerAll(name, (MetricSet) metric);
        } else {
            final Metric existing = metrics.putIfAbsent(name, metric);
            if (existing == null) {
                onMetricAdded(name, metric);
            } else {
                throw new IllegalArgumentException("A metric named " + name + " already exists");
            }
        }
        return metric;
    }

Каждый элемент метрики должен иметь уникальное имя, и класс MetricRegistry предоставляет способ создания имени. В дополнение к созданию имен на основе имен классов также поддерживаются пользовательские имена. Его суть заключается в конкатенации строк.

    public static String name(String name, String... names) {
        final StringBuilder builder = new StringBuilder();
        append(builder, name);
        if (names != null) {
            for (String s : names) {
                append(builder, s);
            }
        }
        return builder.toString();
    }

    public static String name(Class<?> klass, String... names) {
        return name(klass.getName(), names);
    }

    private static void append(StringBuilder builder, String part) {
        if (part != null && !part.isEmpty()) {
            if (builder.length() > 0) {
                builder.append('.');
            }
            builder.append(part);
        }
    }

Отображение данных метрик

Метрики предоставляют интерфейс Reporter для отображения информации внутреннего индикатора данных. Ядро метрик в основном реализует ConsoleReporter, CsvReporter, Slf4jReporter, JmxReporter. В этом примере ConsoleReporter используется для отображения внутренних показателей.

Для использованияFalconКомпании с системами мониторинга могут внедрить собственный Reporter, обратившись к ConsoleReporter, чтобы метрики можно было легко интегрировать в систему мониторинга компании.

Метрики

Gauge

Датчик в основном записывает мгновенное значение индикатора, например текущее обслуживаниеJvmиспользование и т.д.;

public class JvmGaugeTest {

    public static void main(String[] args) throws Exception {
        MetricRegistry registry = new MetricRegistry();

        ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build();
        reporter.start(1, TimeUnit.SECONDS);

        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
        registry.register("jvm.total.used",
                new Gauge<Long>() {

                    @Override
                    public Long getValue() {
                        return memoryMXBean.getHeapMemoryUsage().getUsed()
                                + memoryMXBean.getNonHeapMemoryUsage().getUsed();
                    }
                });

        while (true) {
            Thread.sleep(1000);
        }
    }
}

Результат выполнения кода следующий:

-- Gauges ----------------------------------------------------------------------
jvm.total.used
             value = 16314496

Counter

Счетчик — счетчик, который можно увеличивать и уменьшать для поддержания накопленных показателей.

public class CounterTest {

    private static Queue<String> queue = new LinkedBlockingQueue<String>();
    private static Counter pendingJobs;
    private static Random random = new Random();

    public static void addJob(String job) {
        pendingJobs.inc();
        queue.offer(job);
    }

    public static String takeJob() {
        pendingJobs.dec();
        return queue.poll();
    }

    public static void main(String[] args) throws InterruptedException {
        MetricRegistry registry = new MetricRegistry();

        ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build();
        reporter.start(1, TimeUnit.SECONDS);

        pendingJobs = registry.counter("pending.jobs.size");
        for (int num = 1; ; num++) {
            Thread.sleep(100);
            if (random.nextDouble() > 0.8) {
                takeJob();
            } else {
                addJob("Job-" + num);
            }
        }
    }
}

Результат выполнения кода следующий:

-- Counters --------------------------------------------------------------------
pending.jobs.size
             count = 19

Meter

Счетчик измеряет частоту событий и подсчитывает частоту последних 1 минуты, 5 минут и 15 минут.

public class MeterTest {

    private static Random random = new Random();

    public static void request(Meter meter, int times) {
        for (int i = 0; i < times; i++) {
            meter.mark();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MetricRegistry registry = new MetricRegistry();

        ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build();
        reporter.start(1, TimeUnit.SECONDS);

        Meter meterTps = registry.meter("request.tps");
        while (true) {
            request(meterTps, random.nextInt(10));
            Thread.sleep(1000);
        }
    }

}

Результат выполнения кода следующий:

-- Meters ----------------------------------------------------------------------
request.tps
             count = 115
         mean rate = 5.00 events/second
     1-minute rate = 7.04 events/second
     5-minute rate = 7.63 events/second
    15-minute rate = 7.74 events/second

Счетчик разработан с привязкой к системе UNIX по средней нагрузке средней нагрузки, которая используетEMAАлгоритм экспоненциального скользящего среднего. Чем новее данные, тем более влиятельными они являются.

Histogram

Гистограмма распределения статистических данных, статистический минимум, максимум, среднее значение, медиана, 75-е, 90-е, 95-е, 99-е, 99,9-е и другие данные.

public class HistogramTest {

    private static Random random = new Random();

    public static void main(String[] args) throws Exception {
        MetricRegistry registry = new MetricRegistry();

        ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build();
        reporter.start(1, TimeUnit.SECONDS);

        Histogram histogram = new Histogram(new UniformReservoir());
        registry.register("request.histogram", histogram);

        while (true) {
            Thread.sleep(1000);
            histogram.update(random.nextInt(100));
        }
    }

}

Результат выполнения кода следующий:

-- Histograms ------------------------------------------------------------------
request.histogram
             count = 18
               min = 10
               max = 98
              mean = 53.28
            stddev = 29.48
            median = 44.50
              75% <= 83.50
              95% <= 98.00
              98% <= 98.00
              99% <= 98.00
            99.9% <= 98.00
выборка данных

Гистограмме необходимо распределение статистических данных, а ее внутренние данные должны быть отобраны для сохранения информации о данных. Встроенная выборка данных имеет следующие реализации:

  • ExponentiallyDecayingReservoir: на основе алгоритма выборки экспоненциального уровня разница между временем обновления и временем начала преобразуется в значение веса.Чем больше вес, тем выше вероятность сохранения данных.
  • UniformReservoir: случайная выборка, по мере увеличения количества обновлений вероятность выборки данных уменьшается.
  • SlidingWindowReservoir: выборка из скользящего окна, всегда сохраняющая самую свежую статистику.
  • SlidingTimeWindowReservoir: выборка скользящего временного окна, всегда сохраняющая статистику за самый последний период времени.

Меры предосторожности

Если вы используете ExponentiallyDecayingReservoir и SlidingTimeWindowReservoir, вам нужно обратить внимание на емкость, а нижний слой не ограничивает емкость. Если служебный трафик большой, он может занимать много памяти.

Timer

Таймер представляет собой комбинацию гистограммы и измерителя, гистограмма подсчитывает распределение, требующее времени, а измеритель подсчитывает число запросов в секунду;

public class TimerTest {

    public static Random random = new Random();

    private static void request() throws InterruptedException {
        Thread.sleep(random.nextInt(1000));
    }

    public static void main(String[] args) throws Exception {
        MetricRegistry registry = new MetricRegistry();

        ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build();
        reporter.start(1, TimeUnit.SECONDS);

        Timer timer = registry.timer("request.latency");
        Timer.Context ctx;
        while (true) {
            ctx = timer.time();
            request();
            ctx.stop();
        }
    }
}

Результат выполнения кода следующий:

-- Timers ----------------------------------------------------------------------
request.latency
             count = 22
         mean rate = 2.00 calls/second
     1-minute rate = 1.98 calls/second
     5-minute rate = 2.00 calls/second
    15-minute rate = 2.00 calls/second
               min = 148.93 milliseconds
               max = 865.65 milliseconds
              mean = 491.89 milliseconds
            stddev = 219.59 milliseconds
            median = 465.60 milliseconds
              75% <= 671.65 milliseconds
              95% <= 850.28 milliseconds
              98% <= 865.65 milliseconds
              99% <= 865.65 milliseconds
            99.9% <= 865.65 milliseconds

Сводка опыта

Guage используется, когда нам нужно сообщать о мгновенных показателях обслуживания, таких как использование JVM. Гистограмма используется, когда нам нужно статистическое распределение данных, например распределение времени отклика интерфейса. Meter используется, когда нам нужно подсчитать частоту, например, частоту запроса интерфейса. Объект Timer используется, когда нам нужно подсчитать как частоту, так и распределение, например частоту запросов и время, затрачиваемое на интерфейс.

Релевантная информация

Metrics Core