PerformanceMeasurer

Open source Java библиотека для получения информации о состоянии выполнения Java приложения.

Оглавление

  • Описание
  • Примеры использования
  • Статистика прогресса
  • Статистика прогресса по отдельному критерию
  • Статистика кодов состояния HTTP
  • Статистика производительности определенного участка кода
  • Лицензирование

Описание

Утилита с конфигурируемой частотой (по умолчанию 15 секунд) для каждого измерителя (анализируемая сущность) отображает время выполнения, производительность в секунду, прогресс и прогноз выполнения, данные по датчикам (снимаемым параметрам) данного измерителя. Каждый датчик отображает подсчитываемое значение, изменение после предыдущего отображения, процент от других датчиков данного измерителя.

Примеры использования

Статистика прогресса

Существует несколько предопределенных названий для датчиков - success, fail и error. Вы можете использовать любое название для вашего датчика. Например .success(); или .measure("success");

Вызов

// get list of merchandise
List<Merchandise> merchandiseList = getMerchandiseList();

// set possible workload
PerformanceMeasurer.get().possibleSize(merchandiseList.size());

for (Merchandise merchandise : merchandiseList) {
    try {

        // checking data
        boolean isGood = checkData(merchandise);

        if (!isGood) {
            // say measurer about user's mistake
            PerformanceMeasurer.get().fail();
        } else {
            // if ok then some work...
            // ...

            // say measurer about success
            PerformanceMeasurer.get().success();
        }

    } catch (Exception e) {
        // say measurer about serious failure
        PerformanceMeasurer.get().error();

        LOG.error(merchandise.toString() + e, e);
    }
}

Результат

c.d.import.MerchandiseImport 00:00:15 00:00:15 49%   r/s: 16;  fail: 35% 86;  success: 34% 83;  error: 31% 77;  sum: 246;
c.d.import.MerchandiseImport 00:00:29 00:00:12 70%   r/s: 11(-5);  fail: 34% 121(+35);  success: 34% 120(+37);  error: 31% 110(+33);  sum: 351(+105);
c.d.import.MerchandiseImport 00:00:44 00:00:07 86%   r/s: 9(-2);   fail: 35% 151(+30);  success: 34% 145(+25);  error: 31% 135(+25);  sum: 431(+80); 
c.d.import.MerchandiseImport 00:00:59 00:00:00 99%   r/s: 8(-1);   fail: 35% 175(+24);  success: 34% 166(+21);  error: 31% 154(+19);  sum: 495(+64); 
c.d.import.MerchandiseImport 00:01:01    .     100%  r/s: 8(0);    fail: 36% 178(+3);   success: 33% 167(+1);   error: 31% 155(+1);   sum: 500(+5);  

Статистика прогресса по отдельному критерию

В том случае, когда заранее неизвестно максимальное значение важного параметра, снимаемое датчиком, но есть отдельный побочный параметр, по которому можно отследить прогресс, то можно указать его в качестве изолируемого датчика в possibleSize(isolatedSensor, size).

Например, при подсчете числа товаров, импортируемых из магазинов, заранее известно только число магазинов. В качестве изолируемого датчика используем “магазин”.

Вызов

// get list of shops
List<Shop> shopList = getShops();

// set possible workload of shops
PerformanceMeasurer.get().possibleSize("shop", shopList.size());

for (Shop shop : shopList) {
    // get list of merchandise in shop
    List<Merchandise> merchandiseList = shop.getMerchandise();

    // say measurer about progress by isolated sensor
    PerformanceMeasurer.get().measure("shop");

    for (Merchandise merchandise : merchandiseList) {
        try {
            // checking data
            boolean isGood = checkData(merchandise);

            if (!isGood) {
                // say measurer about user's mistake
                PerformanceMeasurer.get().fail();
            } else {
                // if ok then some work...

                // say measurer about success
                PerformanceMeasurer.get().success();
            }
        } catch (Exception e) {
            // say measurer about serious failure
            PerformanceMeasurer.get().error();
            LOG.error(merchandise.toString() + e, e);
        }
    }
}

Результат

c.d.import.MerchandiseImport 00:00:03    ∞     0%    r/s: 8;  fail: 33% 10;  success: 30% 9;  error: 37% 11;  sum: 30;  shop: 0;
c.d.import.MerchandiseImport 00:00:18 00:01:14 20%   r/s: 8(0);  fail: 36% 54(+44);  success: 37% 55(+46);  error: 27% 41(+30);  sum: 150(+120);  shop: 1;
c.d.import.MerchandiseImport 00:00:33 00:00:50 40%   r/s: 8(0);  fail: 35% 95(+41);  success: 35% 96(+41);  error: 30% 81(+40);  sum: 272(+122);  shop: 2(+1);
c.d.import.MerchandiseImport 00:00:48 00:00:32 60%   r/s: 7(-1);  fail: 37% 143(+48);  success: 34% 130(+34);  error: 29% 109(+28);  sum: 382(+110);  shop: 3(+1);
c.d.import.MerchandiseImport 00:01:03 00:00:15 80%   r/s: 7(0);   fail: 36% 179(+36);  success: 33% 164(+34);  error: 31% 154(+45);  sum: 497(+115);  shop: 4(+1);
c.d.import.MerchandiseImport 00:01:18    .     100%  r/s: 6(-1);  fail: 36% 180(+1);   success: 33% 165(+1);   error: 31% 155(+1);   sum: 500(+3);    shop: 5(+1);

Статистика кодов состояния HTTP

Предположим, у нас есть поисковый робот, который обходит веб-сайты и нам необходимо вести статистику кодов состояния HTTP ответа веб-сервера - 1xx/2xx/3xx/4xx/5xx.

Вызов

if (httpStatusCode >= 100 && httpStatusCode < 200) {
    PerformanceMeasurer.get().measure("Informational");
} else if (httpStatusCode >= 200 && httpStatusCode < 300) {
    PerformanceMeasurer.get().measure("Success");
} else if (httpStatusCode >= 300 && httpStatusCode < 400) {
    PerformanceMeasurer.get().measure("Redirection");
} else if (httpStatusCode >= 400 && httpStatusCode < 500) {
    PerformanceMeasurer.get().measure("Client Error");
} else if (httpStatusCode >= 500 && httpStatusCode < 600) {
    PerformanceMeasurer.get().measure("Server Error");
}

Результат

c.d.h.HttpStatusCode 00:00:15  r/s: 15;  Redirection: 16% 38;  Server Error: 21% 51;  Client Error: 19% 45;  Informational: 18% 43;  Success: 26% 61;  sum: 238;
c.d.h.HttpStatusCode 00:00:29  r/s: 11(-4);  Redirection: 16% 54(+16);  Server Error: 23% 77(+26);  Client Error: 21% 71(+26);  Informational: 18% 61(+18);  Success: 23% 78(+17);  sum: 341(+103);
c.d.h.HttpStatusCode 00:00:44  r/s: 9(-2);   Redirection: 18% 73(+19);  Server Error: 21% 86(+9);   Client Error: 22% 90(+19);  Informational: 18% 73(+12);  Success: 23% 95(+17);  sum: 417(+76); 
c.d.h.HttpStatusCode 00:00:59  r/s: 7(-2);   Redirection: 19% 89(+16);  Server Error: 20% 95(+9);   Client Error: 22% 103(+13);  Informational: 17% 83(+10);  Success: 22% 106(+11);  sum: 476(+59); 
c.d.h.HttpStatusCode 00:01:06  r/s: 7(0);    Redirection: 19% 96(+7);   Server Error: 20% 99(+4);   Client Error: 22% 111(+8);   Informational: 17% 86(+3);   Success: 22% 108(+2);   sum: 500(+24); 

Статистика производительности определенного участка кода

Как правило, программная система состоит из множества модулей, каждый из которых может быть обработан отдельным измерителем (со своими датчиками). По-умолчанию, производительность любого модуля расчитывается за весь период выполнения всей системы.

Но иногда имеет смысл подсчитывать производительность определенного модуля (блока кода) обособленно. В этом случае нужно указать границы исполняемого кода вызовами .start() и .stop()

Пример

Возьмем уже рассмостренный пример и модифицируем его:

private boolean downloadAndSavePage(String url) {

    // borders - independent measure
    PerformanceMeasurer.get().start();
    
    
    // internal long work...
    int httpStatusCode = downloadPage(url);
    

    if (httpStatusCode >= 100 && httpStatusCode < 200) {
        PerformanceMeasurer.get().measure("Informational");
    } else if (httpStatusCode >= 200 && httpStatusCode < 300) {
        PerformanceMeasurer.get().measure("Success");
    } else if (httpStatusCode >= 300 && httpStatusCode < 400) {
        PerformanceMeasurer.get().measure("Redirection");
    } else if (httpStatusCode >= 400 && httpStatusCode < 500) {
        PerformanceMeasurer.get().measure("Client Error");
    } else if (httpStatusCode >= 500 && httpStatusCode < 600) {
        PerformanceMeasurer.get().measure("Server Error");
    }


    // borders - independent measure
    PerformanceMeasurer.get().stop();
    
    return true;
}

Результат

c.d.h.HttpStatusCode (personal) 00:00:01  r/s: 159;  Redirection: 20% 51;  Server Error: 24% 61;  Client Error: 19% 48;  Informational: 17% 42;  Success: 19% 47;  sum: 249;
c.d.h.HttpStatusCode (personal) 00:00:03  r/s: 112(-47);  Redirection: 21% 73(+22);  Server Error: 25% 88(+27);  Client Error: 18% 63(+15);  Informational: 18% 62(+20);  Success: 18% 64(+17);  sum: 350(+101);
c.d.h.HttpStatusCode (personal) 00:00:04  r/s: 92(-20);   Redirection: 20% 86(+13);  Server Error: 24% 104(+16);  Client Error: 19% 82(+19);  Informational: 19% 79(+17);  Success: 18% 75(+11);  sum: 426(+76); 
c.d.h.HttpStatusCode (personal) 00:00:06  r/s: 78(-14);   Redirection: 20% 97(+11);  Server Error: 24% 114(+10);  Client Error: 20% 98(+16);  Informational: 19% 90(+11);  Success: 18% 85(+10);  sum: 484(+58); 
c.d.h.HttpStatusCode (personal) 00:00:06  r/s: 78(0);     Redirection: 19% 97(0);    Server Error: 23% 116(+2);   Client Error: 21% 103(+5);  Informational: 19% 95(+5);   Success: 18% 89(+4);   sum: 500(+16); 
Март 2020

Локализованные версии

Лицензирование

PerformanceMeasurer лицензировано под Apache-2.0

Репозитории

Если вам понравился проект и у вас есть идеи как его улучшить — присоединяйтесь к его развитию. Буду рад коллаборации :)

GitHub

Поделиться с друзьями

Если вам понравился проект — поделитесь с друзьями. Это лучшая мотивация развивать проект.

Комментарии

Если у вас есть вопросы или комментарии — буду рад их услышать — присоединяйтесь к беседе!

Олег Полторацкий Июнь 2020
Разбираюсь с (не-)возможностью копирования кода со страницы. Подождите немного...
P.S. Код выделяется, копируется. Визуально не заметно выделение текста.


Open-source проекты

Open-source проекты и утилиты, автором которых являюсь или в которых принимаю участие.

Список проектов

Поиск по сайту