Когда вы запускаете долгосрочные приложения, такие как веб-приложения, полезно знать некоторую статистику о них, например, количество обработанных запросов, длительности запросов или количество активных запросов. Но также некоторую более общую информацию, такую как состояние ваших внутренних коллекций, сколько раз выполняется какая-то часть кода, или проверки работоспособности, такие как доступность базы данных, или любой вид соединения с внешней системой.
Все эти виды инструментализации могут быть достигнуты с помощью нативного
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 или
веб-приложений .