本文目录导读:

我来为您提供一个完整的Java监控系统案例,涵盖JVM监控、应用性能监控和自定义指标监控。
项目结构
java-monitoring-demo/
├── pom.xml
├── src/main/java/com/example/monitor/
│ ├── MonitorApplication.java
│ ├── config/
│ │ └── MonitorConfig.java
│ ├── controller/
│ │ └── MonitorController.java
│ ├── service/
│ │ ├── JVMMonitorService.java
│ │ ├── MetricsService.java
│ │ └── AlertService.java
│ ├── model/
│ │ ├── JVMInfo.java
│ │ ├── MetricsData.java
│ │ └── AlertRule.java
│ ├── aspect/
│ │ └── PerformanceAspect.java
│ └── scheduler/
│ └── MonitorScheduler.java
Maven依赖配置 (pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>java-monitoring-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<properties>
<java.version>11</java.version>
<micrometer.version>1.9.0</micrometer.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Micrometer Metrics -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>${micrometer.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>${micrometer.version}</version>
</dependency>
<!-- Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- JSON处理 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 系统信息获取 -->
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>6.2.2</version>
</dependency>
<!-- 邮件通知 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies>
</project>
主应用类
package com.example.monitor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class MonitorApplication {
public static void main(String[] args) {
SpringApplication.run(MonitorApplication.class, args);
System.out.println("=".repeat(50));
System.out.println("监控系统启动完成!");
System.out.println("监控端点: http://localhost:8080/monitor");
System.out.println("=".repeat(50));
}
}
数据模型类
package com.example.monitor.model;
import lombok.Data;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import java.util.Map;
// JVM信息模型
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class JVMInfo {
// 内存信息
private long heapTotal;
private long heapUsed;
private long heapFree;
private double heapUsage;
private long nonHeapTotal;
private long nonHeapUsed;
// 线程信息
private int activeThreads;
private int peakThreads;
private long totalThreads;
// GC信息
private long gcCount;
private long gcTime;
// 类加载信息
private int loadedClassCount;
private long totalLoadedClassCount;
private long unloadedClassCount;
// 系统信息
private String osName;
private String osArch;
private int availableProcessors;
// JVM信息
private String jvmName;
private String jvmVersion;
private long uptime;
// CPU使用率
private double cpuUsage;
// 编译信息
private long compilationTime;
// 内存池详情
private Map<String, MemoryPoolInfo> memoryPools;
// 垃圾收集器详情
private Map<String, GCInfo> gcDetails;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class MemoryPoolInfo {
private String name;
private String type;
private long used;
private long max;
private double usage;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class GCInfo {
private String name;
private long collectionCount;
private long collectionTime;
}
@Override
public String toString() {
return String.format(
"JVM信息 [堆内存使用率: %.2f%%, 活动线程: %d, GC次数: %d, CPU使用率: %.2f%%]",
heapUsage * 100, activeThreads, gcCount, cpuUsage * 100
);
}
}
// 指标数据模型
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MetricsData {
private String name;
private String module;
private String method;
private double value;
private double average;
private double max;
private double min;
private long count;
private long timestamp;
// 自定义标签
private Map<String, String> tags;
}
// 告警规则模型
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AlertRule {
private String name;
private String metricName;
private String condition; // 比较运算符: >, <, >=, <=, ==
private double threshold;
private String alertLevel; // INFO, WARN, ERROR, CRITICAL
private long duration; // 持续时间(毫秒)
private String message;
private boolean enabled;
private long lastTriggerTime;
}
监控服务类
package com.example.monitor.service;
import com.example.monitor.model.JVMInfo;
import com.sun.management.OperatingSystemMXBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.lang.management.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Service
public class JVMMonitorService {
private final MemoryMXBean memoryMXBean;
private final ThreadMXBean threadMXBean;
private final RuntimeMXBean runtimeMXBean;
private final ClassLoadingMXBean classLoadingMXBean;
private final OperatingSystemMXBean operatingSystemMXBean;
private final List<GarbageCollectorMXBean> garbageCollectorMXBeans;
private final List<MemoryPoolMXBean> memoryPoolMXBeans;
public JVMMonitorService() {
this.memoryMXBean = ManagementFactory.getMemoryMXBean();
this.threadMXBean = ManagementFactory.getThreadMXBean();
this.runtimeMXBean = ManagementFactory.getRuntimeMXBean();
this.classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
this.operatingSystemMXBean =
ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
this.garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans();
this.memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();
}
/**
* 获取完整的JVM信息
*/
public JVMInfo getJVMInfo() {
MemoryUsage heapMemory = memoryMXBean.getHeapMemoryUsage();
MemoryUsage nonHeapMemory = memoryMXBean.getNonHeapMemoryUsage();
// 计算GC信息
long totalGcCount = 0;
long totalGcTime = 0;
Map<String, JVMInfo.GCInfo> gcDetails = new HashMap<>();
for (GarbageCollectorMXBean gc : garbageCollectorMXBeans) {
long count = gc.getCollectionCount();
long time = gc.getCollectionTime();
totalGcCount += count;
totalGcTime += time;
gcDetails.put(gc.getName(), JVMInfo.GCInfo.builder()
.name(gc.getName())
.collectionCount(count)
.collectionTime(time)
.build());
}
// 获取内存池详情
Map<String, JVMInfo.MemoryPoolInfo> memoryPools = memoryPoolMXBeans.stream()
.collect(Collectors.toMap(
MemoryPoolMXBean::getName,
pool -> {
MemoryUsage usage = pool.getUsage();
return JVMInfo.MemoryPoolInfo.builder()
.name(pool.getName())
.type(pool.getType().name())
.used(usage.getUsed())
.max(usage.getMax() >= 0 ? usage.getMax() : 0)
.usage(usage.getMax() > 0 ?
(double) usage.getUsed() / usage.getMax() : 0)
.build();
}
));
// 获取CPU使用率
double cpuUsage = operatingSystemMXBean.getSystemCpuLoad() * 100;
JVMInfo info = JVMInfo.builder()
// 内存信息
.heapTotal(heapMemory.getCommitted())
.heapUsed(heapMemory.getUsed())
.heapFree(heapMemory.getMax() - heapMemory.getUsed())
.heapUsage((double) heapMemory.getUsed() / heapMemory.getMax())
.nonHeapTotal(nonHeapMemory.getCommitted())
.nonHeapUsed(nonHeapMemory.getUsed())
// 线程信息
.activeThreads(threadMXBean.getThreadCount())
.peakThreads(threadMXBean.getPeakThreadCount())
.totalThreads(threadMXBean.getTotalStartedThreadCount())
// GC信息
.gcCount(totalGcCount)
.gcTime(totalGcTime)
// 类加载信息
.loadedClassCount(classLoadingMXBean.getLoadedClassCount())
.totalLoadedClassCount(classLoadingMXBean.getTotalLoadedClassCount())
.unloadedClassCount(classLoadingMXBean.getUnloadedClassCount())
// 系统信息
.osName(System.getProperty("os.name"))
.osArch(System.getProperty("os.arch"))
.availableProcessors(Runtime.getRuntime().availableProcessors())
// JVM信息
.jvmName(runtimeMXBean.getVmName())
.jvmVersion(runtimeMXBean.getVmVersion())
.uptime(runtimeMXBean.getUptime())
// CPU使用率
.cpuUsage(cpuUsage)
// 编译时间
.compilationTime(ManagementFactory.getCompilationMXBean().getTotalCompilationTime())
// 内存池详情
.memoryPools(memoryPools)
// GC详情
.gcDetails(gcDetails)
.build();
return info;
}
/**
* 检查内存状态
*/
public Map<String, Object> checkMemoryStatus() {
MemoryUsage heapMemory = memoryMXBean.getHeapMemoryUsage();
Map<String, Object> status = new HashMap<>();
status.put("heapUsed", heapMemory.getUsed());
status.put("heapMax", heapMemory.getMax());
status.put("heapUsage",
(double) heapMemory.getUsed() / heapMemory.getMax() * 100);
status.put("status",
(double) heapMemory.getUsed() / heapMemory.getMax() > 0.9 ? "CRITICAL" :
(double) heapMemory.getUsed() / heapMemory.getMax() > 0.7 ? "WARNING" : "NORMAL");
return status;
}
/**
* 获取线程状态
*/
public Map<String, Long> getThreadStatus() {
Map<String, Long> threadStats = new HashMap<>();
long[] threadIds = threadMXBean.getAllThreadIds();
long running = 0, blocked = 0, waiting = 0, timedWaiting = 0;
for (long threadId : threadIds) {
ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId);
if (threadInfo != null) {
switch (threadInfo.getThreadState()) {
case RUNNABLE:
running++;
break;
case BLOCKED:
blocked++;
break;
case WAITING:
waiting++;
break;
case TIMED_WAITING:
timedWaiting++;
break;
}
}
}
threadStats.put("RUNNABLE", running);
threadStats.put("BLOCKED", blocked);
threadStats.put("WAITING", waiting);
threadStats.put("TIMED_WAITING", timedWaiting);
threadStats.put("TOTAL", (long) threadIds.length);
return threadStats;
}
}
指标服务类
package com.example.monitor.service;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.Timer;
import com.example.monitor.model.MetricsData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class MetricsService {
private final MeterRegistry meterRegistry;
// 自定义计数器存储(用于统计)
private final Map<String, MetricsData> customMetrics = new ConcurrentHashMap<>();
// 方法调用统计
private final Map<String, MethodStats> methodStats = new ConcurrentHashMap<>();
@lombok.Data
@lombok.AllArgsConstructor
@lombok.NoArgsConstructor
public static class MethodStats {
private long count;
private long totalTime;
private double avgTime;
private double maxTime;
private double minTime;
}
public MetricsService(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
/**
* 记录计数器指标
*/
public void recordCounter(String name, String description) {
try {
Counter counter = Counter.builder(name)
.description(description)
.register(meterRegistry);
counter.increment();
// 更新自定义指标
updateCustomMetrics(name, "counter", 1.0);
} catch (Exception e) {
log.error("记录计数器指标失败", e);
}
}
/**
* 记录计时器指标
*/
public void recordTimer(String name, long duration, TimeUnit unit,
String description, String... tags) {
try {
Timer timer = Timer.builder(name)
.description(description)
.tags(tags)
.register(meterRegistry);
timer.record(duration, unit);
// 更新自定义指标
updateCustomMetrics(name, "timer", duration);
} catch (Exception e) {
log.error("记录计时器指标失败", e);
}
}
/**
* 记录方法调用统计
*/
public void recordMethodStats(String className, String methodName,
long duration) {
String key = className + "." + methodName;
methodStats.compute(key, (k, stats) -> {
if (stats == null) {
stats = new MethodStats();
stats.setMinTime(duration);
}
stats.setCount(stats.getCount() + 1);
stats.setTotalTime(stats.getTotalTime() + duration);
stats.setAvgTime((double) stats.getTotalTime() / stats.getCount());
stats.setMaxTime(Math.max(stats.getMaxTime(), duration));
stats.setMinTime(Math.min(stats.getMinTime(), duration));
return stats;
});
}
/**
* 获取方法调用统计
*/
public Map<String, MethodStats> getMethodStats() {
return methodStats;
}
/**
* 获取所有指标
*/
public Map<String, Object> getAllMetrics() {
Map<String, Object> metrics = new ConcurrentHashMap<>();
// 添加自定义指标
metrics.put("customMetrics", customMetrics);
// 添加方法统计
metrics.put("methodStats", methodStats);
// 添加Micrometer指标
Map<String, Object> micrometerMetrics = new ConcurrentHashMap<>();
meterRegistry.getMeters().forEach(meter -> {
micrometerMetrics.put(meter.getId().getName(),
meter.measure().toString());
});
metrics.put("micrometerMetrics", micrometerMetrics);
return metrics;
}
private void updateCustomMetrics(String name, String type, double value) {
MetricsData data = customMetrics.get(name);
if (data == null) {
data = MetricsData.builder()
.name(name)
.count(0)
.timestamp(System.currentTimeMillis())
.build();
customMetrics.put(name, data);
}
data.setCount(data.getCount() + 1);
data.setValue(value);
data.setAverage((data.getAverage() * (data.getCount() - 1) + value)
/ data.getCount());
data.setMax(Math.max(data.getMax(), value));
data.setMin(data.getMin() == 0 ? value : Math.min(data.getMin(), value));
}
}
告警服务类
package com.example.monitor.service;
import com.example.monitor.model.AlertRule;
import com.example.monitor.model.JVMInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Service
public class AlertService {
private final Map<String, AlertRule> alertRules = new ConcurrentHashMap<>();
private final Map<String, Boolean> alertStates = new ConcurrentHashMap<>();
@Value("${app.monitor.enable-mail:false}")
private boolean enableMail;
@Value("${app.monitor.default-email:}")
private String defaultEmail;
private final JVMMonitorService jvmMonitorService;
private final MetricsService metricsService;
private final JavaMailSender mailSender;
public AlertService(JVMMonitorService jvmMonitorService,
MetricsService metricsService,
JavaMailSender mailSender) {
this.jvmMonitorService = jvmMonitorService;
this.metricsService = metricsService;
this.mailSender = mailSender;
}
@PostConstruct
public void init() {
// 添加默认告警规则
addDefaultRules();
}
private void addDefaultRules() {
// 内存使用率告警
addRule(AlertRule.builder()
.name("heap-memory-usage")
.metricName("heapUsage")
.condition(">")
.threshold(0.85)
.alertLevel("WARN")
.duration(5000)
.message("堆内存使用率过高")
.enabled(true)
.build());
// CPU使用率告警
addRule(AlertRule.builder()
.name("cpu-usage")
.metricName("cpuUsage")
.condition(">")
.threshold(80)
.alertLevel("WARN")
.duration(5000)
.message("CPU使用率过高")
.enabled(true)
.build());
// GC时间告警
addRule(AlertRule.builder()
.name("gc-time")
.metricName("gcTime")
.condition(">")
.threshold(10000)
.alertLevel("WARN")
.duration(10000)
.message("GC时间过长")
.enabled(true)
.build());
}
/**
* 添加告警规则
*/
public void addRule(AlertRule rule) {
alertRules.put(rule.getName(), rule);
alertStates.put(rule.getName(), true); // true 表示可以触发
log.info("添加告警规则: {}", rule.getName());
}
/**
* 移除告警规则
*/
public void removeRule(String ruleName) {
alertRules.remove(ruleName);
alertStates.remove(ruleName);
}
/**
* 检查所有告警规则
*/
public List<String> checkAlerts() {
List<String> triggeredAlerts = new ArrayList<>();
JVMInfo jvmInfo = jvmMonitorService.getJVMInfo();
for (AlertRule rule : alertRules.values()) {
if (!rule.isEnabled()) {
continue;
}
double currentValue = getMetricValue(rule.getMetricName(), jvmInfo);
boolean shouldTrigger = compareValues(currentValue, rule.getCondition(),
rule.getThreshold());
if (shouldTrigger) {
// 检查持续时间
if (rule.getLastTriggerTime() == 0) {
rule.setLastTriggerTime(System.currentTimeMillis());
continue;
}
long duration = System.currentTimeMillis() - rule.getLastTriggerTime();
if (duration >= rule.getDuration()) {
// 检查是否可以再次触发
if (alertStates.getOrDefault(rule.getName(), true)) {
String alertMessage = String.format(
"[%s] %s - 当前值: %.2f %s %.2f",
rule.getAlertLevel(),
rule.getMessage(),
currentValue,
rule.getCondition(),
rule.getThreshold()
);
triggeredAlerts.add(alertMessage);
log.warn("触发告警: {}", alertMessage);
// 发送邮件通知
if (enableMail) {
sendEmail(alertMessage);
}
// 设置为不可再次触发,直到恢复
alertStates.put(rule.getName(), false);
}
}
} else {
// 恢复正常,重置状态
rule.setLastTriggerTime(0);
alertStates.put(rule.getName(), true);
}
}
return triggeredAlerts;
}
/**
* 获取指标值
*/
private double getMetricValue(String metricName, JVMInfo jvmInfo) {
try {
switch (metricName) {
case "heapUsage":
return jvmInfo.getHeapUsage();
case "heapUsed":
return jvmInfo.getHeapUsed();
case "heapFree":
return jvmInfo.getHeapFree();
case "cpuUsage":
return jvmInfo.getCpuUsage();
case "activeThreads":
return jvmInfo.getActiveThreads();
case "gcCount":
return jvmInfo.getGcCount();
case "gcTime":
return jvmInfo.getGcTime();
case "loadedClassCount":
return jvmInfo.getLoadedClassCount();
case "uptime":
return jvmInfo.getUptime();
default:
// 尝试从方法统计中获取
if (metricName.startsWith("method.")) {
String methodKey = metricName.substring(7);
Map<String, MetricsService.MethodStats> stats =
metricsService.getMethodStats();
MetricsService.MethodStats methodStat = stats.get(methodKey);
if (methodStat != null) {
return methodStat.getAvgTime();
}
}
return 0;
}
} catch (Exception e) {
log.error("获取指标值失败: {}", metricName, e);
return 0;
}
}
/**
* 数值比较
*/
private boolean compareValues(double currentValue, String condition,
double threshold) {
switch (condition) {
case ">":
return currentValue > threshold;
case "<":
return currentValue < threshold;
case ">=":
return currentValue >= threshold;
case "<=":
return currentValue <= threshold;
case "==":
return currentValue == threshold;
default:
return false;
}
}
/**
* 发送邮件通知
*/
private void sendEmail(String message) {
try {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo(defaultEmail);
mailMessage.setSubject("[告警通知] 系统监控告警");
mailMessage.setText(message);
mailMessage.setFrom("monitor@example.com");
mailSender.send(mailMessage);
log.info("告警邮件发送成功: {}", defaultEmail);
} catch (Exception e) {
log.error("发送告警邮件失败", e);
}
}
/**
* 获取所有告警规则
*/
public List<AlertRule> getAlertRules() {
return new ArrayList<>(alertRules.values());
}
/**
* 检查单个值
*/
public List<String> checkCustomAlert(String metricName, double value) {
List<String> triggered = new ArrayList<>();
for (AlertRule rule : alertRules.values()) {
if (!rule.isEnabled() || !rule.getMetricName().equals(metricName)) {
continue;
}
if (compareValues(value, rule.getCondition(), rule.getThreshold())) {
if (alertStates.getOrDefault(rule.getName(), true)) {
String alertMessage = String.format(
"[%s] %s - 当前值: %.2f %s %.2f",
rule.getAlertLevel(),
rule.getMessage(),
value,
rule.getCondition(),
rule.getThreshold()
);
triggered.add(alertMessage);
alertStates.put(rule.getName(), false);
}
} else {
alertStates.put(rule.getName(), true);
}
}
return triggered;
}
}
AOP性能监控
package com.example.monitor.aspect;
import com.example.monitor.service.MetricsService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
@Slf4j
public class PerformanceAspect {
private final MetricsService metricsService;
public PerformanceAspect(MetricsService metricsService) {
this.metricsService = metricsService;
}
/**
* 定义切入点:所有Service和Controller的方法
*/
@Pointcut("execution(* com.example.monitor.service.*.*(..)) || " +
"execution(* com.example.monitor.controller.*.*(..))")
public void monitorPointcut() {}
/**
* 环绕通知:监控方法执行时间和性能
*/
@Around("monitorPointcut()")
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.nanoTime();
String className = joinPoint.getTarget().getClass().getSimpleName();
String methodName = joinPoint.getSignature().getName();
Object result = null;
Throwable error = null;
try {
result = joinPoint.proceed();
return result;
} catch (Throwable e) {
error = e;
throw e;
} finally {
long duration = System.nanoTime() - startTime;
long durationMs = TimeUnit.NANOSECONDS.toMillis(duration);
// 记录方法调用统计
metricsService.recordMethodStats(className, methodName, durationMs);
// 记录到Micrometer
metricsService.recordTimer("method.execution.time", duration,
TimeUnit.NANOSECONDS, "Method execution time",
"class", className, "method", methodName);
// 记录错误率
if (error != null) {
metricsService.recordCounter("method.execution.error",
"Method execution errors");
log.warn("方法 {}.{} 执行失败,耗时: {} ms",
className, methodName, durationMs, error);
} else {
log.debug("方法 {}.{} 执行时间: {} ms",
className, methodName, durationMs);
}
// 检查性能阈值(例如超过1000ms)
if (durationMs > 1000) {
log.warn("方法 {}.{} 执行时间过长: {} ms",
className, methodName, durationMs);
// 检查告警规则
metricsService.recordCounter("method.slow.execution",
"Slow method executions");
}
}
}
/**
* 定义切入点:所有Controller方法
*/
@Pointcut("execution(* com.example.monitor.controller.*.*(..))")
public void controllerPointcut() {}
/**
* 后置通知:监控Controller响应时间
*/
@AfterReturning(pointcut = "controllerPointcut()", returning = "result")
public void afterReturning(ProceedingJoinPoint joinPoint, Object result) {
log.debug("Controller方法执行成功: {}",
joinPoint.getSignature().getName());
}
/**
* 定义切入点:所有标记@MonitorAnnotation的方法
*/
@Pointcut("@annotation(com.example.monitor.annotation.MonitorAnnotation)")
public void annotationPointcut() {}
/**
* 使用自定义注解的方法监控
*/
@Around("annotationPointcut()")
public Object aroundAnnotatedMethod(ProceedingJoinPoint joinPoint)
throws Throwable {
log.info("开始监控标注方法: {}",
joinPoint.getSignature().getName());
long start = System.currentTimeMillis();
try {
return joinPoint.proceed();
} finally {
long executionTime = System.currentTimeMillis() - start;
log.info("方法 {} 执行时间: {} ms",
joinPoint.getSignature().getName(), executionTime);
}
}
}
控制器
package com.example.monitor.controller;
import com.example.monitor.model.JVMInfo;
import com.example.monitor.model.AlertRule;
import com.example.monitor.service.JVMMonitorService;
import com.example.monitor.service.MetricsService;
import com.example.monitor.service.AlertService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/monitor")
public class MonitorController {
private final JVMMonitorService jvmMonitorService;
private final MetricsService metricsService;
private final AlertService alertService;
public MonitorController(JVMMonitorService jvmMonitorService,
MetricsService metricsService,
AlertService alertService) {
this.jvmMonitorService = jvmMonitorService;
this.metricsService = metricsService;
this.alertService = alertService;
}
/**
* 获取JVM信息
*/
@GetMapping("/jvm")
public Map<String, Object> getJVMInfo() {
JVMInfo info = jvmMonitorService.getJVMInfo();
return Map.of(
"jvmInfo", info,
"timestamp", System.currentTimeMillis(),
"status", "success"
);
}
/**
* 获取指标数据
*/
@GetMapping("/metrics")
public Map<String, Object> getAllMetrics() {
return metricsService.getAllMetrics();
}
/**
* 触发告警检查
*/
@GetMapping("/alerts/check")
public Map<String, Object> checkAlerts() {
List<String> triggeredAlerts = alertService.checkAlerts();
return Map.of(
"triggeredAlerts", triggeredAlerts,
"alertCount", triggeredAlerts.size(),
"timestamp", System.currentTimeMillis()
);
}
/**
* 添加告警规则
*/
@PostMapping("/alerts/rules")
public Map<String, Object> addAlertRule(@RequestBody AlertRule rule) {
alertService.addRule(rule);
return Map.of(
"status", "success",
"message", "告警规则添加成功"
);
}
/**
* 获取所有告警规则
*/
@GetMapping("/alerts/rules")
public List<AlertRule> getAlertRules() {
return alertService.getAlertRules();
}
/**
* 删除告警规则
*/
@DeleteMapping("/alerts/rules/{name}")
public Map<String, Object> deleteAlertRule(@PathVariable String name) {
alertService.removeRule(name);
return Map.of(
"status", "success",
"message", "告警规则删除成功"
);
}
/**
* 获取方法统计
*/
@GetMapping("/methods/stats")
public Map<String, MetricsService.MethodStats> getMethodStats() {
return metricsService.getMethodStats();
}
/**
* 获取内存状态
*/
@GetMapping("/memory")
public Map<String, Object> getMemoryStatus() {
return jvmMonitorService.checkMemoryStatus();
}
/**
* 获取线程状态
*/
@GetMapping("/threads")
public Map<String, Long> getThreadStatus() {
return jvmMonitorService.getThreadStatus();
}
}
配置类
package com.example.monitor.config;
import com.example.monitor.service.JVMMonitorService;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.jvm.*;
import io.micrometer.core.instrument.binder.system.ProcessorMetrics;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MonitorConfig {
@Bean
public MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}
@Bean
public JvmMemoryMetrics jvmMemoryMetrics() {
return new JvmMemoryMetrics();
}
@Bean
public JvmGcMetrics jvmGcMetrics() {
return new JvmGcMetrics();
}
@Bean
public JvmThreadMetrics jvmThreadMetrics() {
return new JvmThreadMetrics();
}
@Bean
public ProcessorMetrics processorMetrics() {
return new ProcessorMetrics();
}
}
Application配置文件
# application.yml
spring:
application:
name: java-monitoring-demo
# 邮件配置
mail:
host: smtp.example.com
port: 25
username: monitoring@example.com
password: your-password
properties:
mail.smtp.auth: true
mail.smtp.starttls.enable: true
# 监控配置
app:
monitor:
enable-mail: false
default-email: admin@example.com
alert-check-interval: 30
# Actuator配置
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
export:
prometheus:
enabled: true
# 日志配置
logging:
level:
com.example.monitor: INFO
com.sun.management: WARN
file:
name: logs/monitor-app.log
测试示例
package