Когда вы запускаете долгосрочные приложения, такие как веб-приложения, полезно знать некоторую статистику о них, например, количество обработанных запросов, длительности запросов или количество активных запросов. Но также некоторую более общую информацию, такую как состояние ваших внутренних коллекций, сколько раз выполняется какая-то часть кода, или проверки работоспособности, такие как доступность базы данных, или любой вид соединения с внешней системой.
Все эти виды инструментализации могут быть достигнуты с помощью нативного
JMX или модульного проекта, такого как
Metrics .
Метрики предоставляют эффективный способ измерить поведение ваших критических компонентов и сообщить о них различным системам, таким как
JConsole ,
System Console ,
Ganglia ,
Graphite ,
CSV , или сделать их доступными через веб-сервер.
Чтобы установить
метрики , нам нужно только добавить метрики зависимости. В этом примере мы будем использовать Maven.
<dependencies>
<dependency>
<groupId>com.yammer.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
Теперь пришло время добавить некоторые метрики в наш код. В
метриках мы можем использовать 6 типов метрик:
- Датчики : мгновенное измерение дискретного значения.
- Счетчики : значение, которое можно увеличивать и уменьшать. Может использоваться в очередях для мониторинга оставшегося количества ожидающих заданий.
- Метры : измерьте скорость событий с течением времени. Вы можете указать единицу тарифа, объем событий или тип события.
- Гистограммы : измерение статистического распределения значений в потоке данных.
- Таймеры : измеряют количество времени, необходимое для выполнения фрагмента кода, и распределение его продолжительности.
- Проверка работоспособности : как следует из его названия, она централизует проверку работоспособности внешних систем нашей службой.
Итак, давайте напишем действительно простое приложение (на самом деле это консольное приложение), которое отправляет запросы в
поисковую систему Google . Мы измерим количество петиций, количество символов, отправленных в
Google , последнее найденное слово и таймер для измерения скорости отправки запроса и получения ответа.
Основной класс, в котором
будут применяться меры , называется
MetricsApplication и отвечает за подключение к
Google и отправку введенного слова.
public class MetricsApplication {
//Counter
private final Counter numberOfSendCharacters = Metrics.newCounter(MetricsApplication.class, "Total-Number-Of-Characters");
//Meter
private final Meter sendMessages = Metrics.newMeter(MetricsApplication.class, "Sent-Messages", "Send", TimeUnit.SECONDS);
//Timer
private final Timer responseTime = Metrics.newTimer(MetricsApplication.class, "Response-Time");
private LinkedList<String> historyOfQueries = new LinkedList<String>();
{
//Gauge
Metrics.newGauge(MetricsApplication.class, "lastQuery", new Gauge<String>() {
@Override
public String value() {
return historyOfQueries.getLast();
}
});
}
public void sendQuery(String message) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
updateMetrics(message);
TimerContext timerContext = responseTime.time();
sendQueryToGoogle(message);
timerContext.stop();
}
private void sendQueryToGoogle(String message) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
WebClient webClient = new WebClient();
HtmlPage currentPage = webClient.getPage("http://www.google.com/");
//Get the query input text
HtmlInput queryInput = currentPage.getElementByName("q");
queryInput.setValueAttribute(message);
//Submit the form by pressing the submit button
HtmlSubmitInput submitBtn = currentPage.getElementByName("btnG");
currentPage = submitBtn.click();
}
private void updateMetrics(String message) {
numberOfSendCharacters.inc(message.length());
sendMessages.mark();
historyOfQueries.addLast(message);
}
}
Первое, что мы видим, это контрпример. Этот счетчик будет подсчитывать количество символов, отправленных в
Google за всю жизнь приложений (пока вы не остановите это).
Следующее свойство — это индикатор, который измеряет скорость отправки запросов с течением времени.
Затем у нас есть таймер, который оценивает
вызовы метода sendQueryToGoogle и его распределение по времени.
И, наконец,
LinkedList для хранения всех отправленных запросов. Этот экземпляр будет использоваться для возврата последнего выполненного запроса и используется в индикаторе для возврата последнего вставленного элемента.
Обратите внимание, что в каждой мере мы устанавливаем класс, который будет использоваться как папка в
jconsole . Кроме того, предусмотрена метка для использования в качестве имени внутри папки.
Давайте посмотрим на скриншот
jconsole с предыдущей конфигурацией и выполнением трех поисков:
По умолчанию все метрики видны через
JMX . Но, конечно, мы можем сообщить об измерениях на
консоль ,
http-сервер ,
Ganglia или
Graphite .
Также обратите внимание, что в этом примере мы смешиваем код бизнес-кода и метрик. Если вы планируете использовать
метрики в своем производственном коде, я предлагаю вам по возможности использовать логику метрик в AOP.
Мы изучили простой способ мониторинга наших приложений без непосредственного использования
JMX . Также имейте в виду, что
Metrics поставляется с некоторыми встроенными метриками для инструментов
HttpClient ,
JDBI ,
Jetty ,
Jersey ,
Log4j ,
Logback или
веб-приложений .