本文目录导读:

我来为您提供一个完整的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
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播