
Java Application Monitor (JAMon) является бесплатной, высокопроизводительной и потокобезопасной библиотекой для сбора статистики о работе приложения и поиска узких мест, анализа возможностей масштабирования. Можно считать количество брошенных исключений определенного типа, количество SQL запросов, количество запросов JSP страницы. В отчете выдается число вызовов, время выполнения (общее, среднее, минимальное, максимальное, среднеквадратичное отклонение), а также сведения, относящиеся к concurrency – число одновременных вызовов метода из разных потоков. К примеру, можно получить данные о захвате и удержании какого-то ресурса.
JAMon достаточно быстро работает и может использоваться в production системах (опыт показывает, что overhead пренебрежимо мал). Отчет о вызовах выдается по умолчанию в виде HTML. Есть возможность выкладывать статистику на веб сервер.
Для работы нужно добавить зависимость:
<dependency>
<groupid>com.jamonapi</groupid>
<artifactid>jamon</artifactid>
<version>2.81</version>
</dependency> |
<dependency>
<groupid>com.jamonapi</groupid>
<artifactid>jamon</artifactid>
<version>2.81</version>
</dependency>
Мониторинг будет производиться в классе Loop (программа достаточно упрощенная, можно даже сказать надуманная, но позволяет понять принципы использования JAMon):
package ru.dk2k.mavenExample;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.jamonapi.Monitor;
import com.jamonapi.MonitorFactory;
public class Loop {
synchronized public void wait(int pause){
try {
Thread.sleep(pause);
} catch (InterruptedException e){
}
}
public static void main(String[] args) {
Loop loop = new Loop();
int randValue;
int counter = 50;
Random r = new Random();
Monitor mon = null;
String label = loop.getClass().getCanonicalName() + ".wait()";
//"ru.dk2k.mavenExample.Loop.wait()";
for (int i = 0; i < counter; i++) {
try{
mon = MonitorFactory.start(label);
randValue = r.nextInt(400) + 100;
loop.wait(randValue);
} finally {
mon.stop();
}
}
System.out.println(mon);
Thread task = new Thread(new StatsUpdater());
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(task);
executor.shutdownNow();
}
} |
package ru.dk2k.mavenExample;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.jamonapi.Monitor;
import com.jamonapi.MonitorFactory;
public class Loop {
synchronized public void wait(int pause){
try {
Thread.sleep(pause);
} catch (InterruptedException e){
}
}
public static void main(String[] args) {
Loop loop = new Loop();
int randValue;
int counter = 50;
Random r = new Random();
Monitor mon = null;
String label = loop.getClass().getCanonicalName() + ".wait()";
//"ru.dk2k.mavenExample.Loop.wait()";
for (int i = 0; i < counter; i++) {
try{
mon = MonitorFactory.start(label);
randValue = r.nextInt(400) + 100;
loop.wait(randValue);
} finally {
mon.stop();
}
}
System.out.println(mon);
Thread task = new Thread(new StatsUpdater());
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(task);
executor.shutdownNow();
}
}
Вызов:
позволит увидеть статистику в виде:
JAMon Label=ru.dk2k.mavenExample.Loop.wait(), Units=ms.:
(LastValue=327.0, Hits=50.0, Avg=305.08, Total=15254.0,
Min=105.0, Max=491.0, Active=0.0, Avg Active=1.0,
Max Active=1.0, First Access=Tue Oct 27 11:34:56 MSK 2015,
Last Access=Tue Oct 27 11:35:11 MSK 2015) |
JAMon Label=ru.dk2k.mavenExample.Loop.wait(), Units=ms.:
(LastValue=327.0, Hits=50.0, Avg=305.08, Total=15254.0,
Min=105.0, Max=491.0, Active=0.0, Avg Active=1.0,
Max Active=1.0, First Access=Tue Oct 27 11:34:56 MSK 2015,
Last Access=Tue Oct 27 11:35:11 MSK 2015)
Однако, можно получить и более наглядную форму. В следующем классе данные статистики будут сбрасываться в html файл:
package ru.dk2k.mavenExample;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import com.jamonapi.MonitorFactory;
public class StatsUpdater implements Runnable {
static File statFile = new File("/home/dk/stat.html");
public void run() {
String monReport = MonitorFactory.getReport();
BufferedWriter outBuffer = null;
try {
outBuffer = new BufferedWriter(new FileWriter(statFile));
outBuffer.write(monReport);
} catch (IOException e) {
} finally {
try
{
if(outBuffer != null) {
outBuffer.close();
}
} catch (IOException e) {
}
}
}
} |
package ru.dk2k.mavenExample;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import com.jamonapi.MonitorFactory;
public class StatsUpdater implements Runnable {
static File statFile = new File("/home/dk/stat.html");
public void run() {
String monReport = MonitorFactory.getReport();
BufferedWriter outBuffer = null;
try {
outBuffer = new BufferedWriter(new FileWriter(statFile));
outBuffer.write(monReport);
} catch (IOException e) {
} finally {
try
{
if(outBuffer != null) {
outBuffer.close();
}
} catch (IOException e) {
}
}
}
}
(поток из этого класса создается в Loop). Сброс статистики можно настроить по расписанию или нажатию кнопки в графической оболочке.

(картинка кликабельна, можно посмотреть без размытия)
В моем сброшенном файле будет только одна строка с данными о вызовах - строка с меткой ru.dk2k.mavenExample.Loop.wait(), т.к. был только один вызов вида:
mon = MonitorFactory.start(label); |
mon = MonitorFactory.start(label);
(в качестве меток рекомендуется использовать уникальные строки).
В статье затронуты только базовые аспекты, если вы хотите узнать больше, читайте документацию:
документация
[sc:social_networks ]