Java监控案例

wen java案例 1

本文目录导读:

Java监控案例

  1. 项目结构
  2. Maven依赖配置 (pom.xml)
  3. 主应用类
  4. 数据模型类
  5. 监控服务类
  6. 指标服务类
  7. 告警服务类
  8. AOP性能监控
  9. 控制器
  10. 配置类
  11. Application配置文件
  12. 测试示例

我来为您提供一个完整的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

抱歉,评论功能暂时关闭!