AE86 3 gadi atpakaļ
vecāks
revīzija
303259c05c
17 mainītis faili ar 516 papildinājumiem un 293 dzēšanām
  1. 32 5
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MonitorServiceImpl.java
  2. 17 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/AbstractMetricDetailFormatter.java
  3. 9 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/MetricDetailFormatter.java
  4. 16 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/CpuMetricDetailFormatter.java
  5. 25 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/DiskMetricDetailFormatter.java
  6. 16 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/DoubleRoundMetricDetailFormatter.java
  7. 20 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/GCMetricDetailFormatter.java
  8. 19 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/MemoryMetricDetailFormatter.java
  9. 15 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/ValueMetricDetailFormatter.java
  10. 9 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/vo/MetricResponseVo.java
  11. 48 0
      dbsyncer-monitor/src/main/java/org/dbsyncer/monitor/enums/DiskMetricEnum.java
  12. 9 20
      dbsyncer-monitor/src/main/java/org/dbsyncer/monitor/enums/MetricEnum.java
  13. 2 3
      dbsyncer-web/src/main/java/org/dbsyncer/web/config/TaskPoolConfig.java
  14. 52 19
      dbsyncer-web/src/main/java/org/dbsyncer/web/controller/monitor/MonitorController.java
  15. 94 73
      dbsyncer-web/src/main/resources/public/monitor/monitor.html
  16. 2 9
      dbsyncer-web/src/main/resources/static/js/common.js
  17. 131 164
      dbsyncer-web/src/main/resources/static/js/monitor/index.js

+ 32 - 5
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MonitorServiceImpl.java

@@ -3,6 +3,8 @@ package org.dbsyncer.biz.impl;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.math.NumberUtils;
 import org.dbsyncer.biz.MonitorService;
+import org.dbsyncer.biz.metric.MetricDetailFormatter;
+import org.dbsyncer.biz.metric.impl.*;
 import org.dbsyncer.biz.vo.DataVo;
 import org.dbsyncer.biz.vo.LogVo;
 import org.dbsyncer.biz.vo.MetaVo;
@@ -12,7 +14,9 @@ import org.dbsyncer.common.util.CollectionUtils;
 import org.dbsyncer.common.util.JsonUtil;
 import org.dbsyncer.manager.Manager;
 import org.dbsyncer.monitor.Monitor;
+import org.dbsyncer.monitor.enums.DiskMetricEnum;
 import org.dbsyncer.monitor.enums.MetricEnum;
+import org.dbsyncer.monitor.enums.ThreadPoolMetricEnum;
 import org.dbsyncer.monitor.model.MetricResponse;
 import org.dbsyncer.parser.enums.ModelEnum;
 import org.dbsyncer.parser.model.Mapping;
@@ -27,10 +31,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.Assert;
 
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
+import javax.annotation.PostConstruct;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -49,6 +51,27 @@ public class MonitorServiceImpl implements MonitorService {
     @Autowired
     private Manager manager;
 
+    private Map<String, MetricDetailFormatter> metricDetailFormatterMap = new LinkedHashMap<>();
+
+    @PostConstruct
+    private void init() {
+        metricDetailFormatterMap.putIfAbsent(ThreadPoolMetricEnum.TASK_SUBMITTED.getCode(), new ValueMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(ThreadPoolMetricEnum.QUEUE_UP.getCode(), new ValueMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(ThreadPoolMetricEnum.ACTIVE.getCode(), new ValueMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(ThreadPoolMetricEnum.COMPLETED.getCode(), new ValueMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(ThreadPoolMetricEnum.REMAINING_CAPACITY.getCode(), new ValueMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(MetricEnum.THREADS_LIVE.getCode(), new DoubleRoundMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(MetricEnum.THREADS_PEAK.getCode(), new DoubleRoundMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(MetricEnum.MEMORY_USED.getCode(), new MemoryMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(MetricEnum.MEMORY_COMMITTED.getCode(), new MemoryMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(MetricEnum.MEMORY_MAX.getCode(), new MemoryMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(MetricEnum.CPU_USAGE.getCode(), new CpuMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(MetricEnum.GC_PAUSE.getCode(), new GCMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(DiskMetricEnum.THRESHOLD.getCode(), new DiskMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(DiskMetricEnum.FREE.getCode(), new DiskMetricDetailFormatter());
+        metricDetailFormatterMap.putIfAbsent(DiskMetricEnum.TOTAL.getCode(), new DiskMetricDetailFormatter());
+    }
+
     @Override
     public List<MetaVo> getMetaAll() {
         List<MetaVo> list = manager.getMetaAll()
@@ -149,10 +172,14 @@ public class MonitorServiceImpl implements MonitorService {
         // 系统指标
         metricList.addAll(metrics);
 
-        // TODO 转换显示
+        // 转换显示
         return metricList.stream().map(metric -> {
             MetricResponseVo vo = new MetricResponseVo();
             BeanUtils.copyProperties(metric, vo);
+            MetricDetailFormatter detailFormatter = metricDetailFormatterMap.get(vo.getCode());
+            if(null != detailFormatter){
+                detailFormatter.format(vo);
+            }
             return vo;
         }).collect(Collectors.toList());
     }

+ 17 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/AbstractMetricDetailFormatter.java

@@ -0,0 +1,17 @@
+package org.dbsyncer.biz.metric;
+
+import org.dbsyncer.biz.vo.MetricResponseVo;
+import org.dbsyncer.common.util.CollectionUtils;
+
+public abstract class AbstractMetricDetailFormatter implements MetricDetailFormatter{
+
+    protected abstract void apply(MetricResponseVo vo);
+
+    @Override
+    public void format(MetricResponseVo vo) {
+        if(CollectionUtils.isEmpty(vo.getMeasurements())){
+            return;
+        }
+        apply(vo);
+    }
+}

+ 9 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/MetricDetailFormatter.java

@@ -0,0 +1,9 @@
+package org.dbsyncer.biz.metric;
+
+import org.dbsyncer.biz.vo.MetricResponseVo;
+
+public interface MetricDetailFormatter {
+
+    void format(MetricResponseVo vo);
+
+}

+ 16 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/CpuMetricDetailFormatter.java

@@ -0,0 +1,16 @@
+package org.dbsyncer.biz.metric.impl;
+
+import org.dbsyncer.biz.metric.AbstractMetricDetailFormatter;
+import org.dbsyncer.biz.vo.MetricResponseVo;
+import org.dbsyncer.monitor.model.Sample;
+
+public final class CpuMetricDetailFormatter extends AbstractMetricDetailFormatter {
+
+    @Override
+    public void apply(MetricResponseVo vo) {
+        Sample sample = vo.getMeasurements().get(0);
+        Double value = (Double) sample.getValue();
+        vo.setDetail(String.format("%.2f", (value * 100)) + "%");
+    }
+
+}

+ 25 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/DiskMetricDetailFormatter.java

@@ -0,0 +1,25 @@
+package org.dbsyncer.biz.metric.impl;
+
+import org.dbsyncer.biz.metric.AbstractMetricDetailFormatter;
+import org.dbsyncer.biz.vo.MetricResponseVo;
+import org.dbsyncer.monitor.model.Sample;
+
+import java.math.BigDecimal;
+
+public class DiskMetricDetailFormatter extends AbstractMetricDetailFormatter {
+
+    @Override
+    public void apply(MetricResponseVo vo) {
+        Sample sample = vo.getMeasurements().get(0);
+        BigDecimal decimal = new BigDecimal(String.valueOf(sample.getValue()));
+        BigDecimal bt = divide(decimal,0);
+        BigDecimal mb = divide(bt,0);
+        BigDecimal gb = divide(mb,2);
+        vo.setDetail(gb + "GB");
+    }
+
+    private BigDecimal divide(BigDecimal d1, int scale) {
+        return d1.divide(new BigDecimal("1024"), scale, BigDecimal.ROUND_HALF_UP);
+    }
+
+}

+ 16 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/DoubleRoundMetricDetailFormatter.java

@@ -0,0 +1,16 @@
+package org.dbsyncer.biz.metric.impl;
+
+import org.dbsyncer.biz.metric.AbstractMetricDetailFormatter;
+import org.dbsyncer.biz.vo.MetricResponseVo;
+import org.dbsyncer.monitor.model.Sample;
+
+public final class DoubleRoundMetricDetailFormatter extends AbstractMetricDetailFormatter {
+
+    @Override
+    public void apply(MetricResponseVo vo) {
+        Sample sample = vo.getMeasurements().get(0);
+        long round = Math.round((Double) sample.getValue());
+        vo.setDetail(String.valueOf(round));
+    }
+
+}

+ 20 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/GCMetricDetailFormatter.java

@@ -0,0 +1,20 @@
+package org.dbsyncer.biz.metric.impl;
+
+import org.dbsyncer.biz.metric.AbstractMetricDetailFormatter;
+import org.dbsyncer.biz.vo.MetricResponseVo;
+import org.dbsyncer.monitor.model.Sample;
+
+import java.util.List;
+
+public final class GCMetricDetailFormatter extends AbstractMetricDetailFormatter {
+
+    @Override
+    public void apply(MetricResponseVo vo) {
+        List<Sample> list = vo.getMeasurements();
+        long count = Math.round((Double) list.get(0).getValue());
+        String total = String.format("%.2f", ((Double) list.get(1).getValue()));
+        long max = Math.round((Double) list.get(2).getValue());
+        vo.setDetail(String.format("%s次,耗时:%s秒,最长:%s秒", count, total, max));
+    }
+
+}

+ 19 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/MemoryMetricDetailFormatter.java

@@ -0,0 +1,19 @@
+package org.dbsyncer.biz.metric.impl;
+
+import org.dbsyncer.biz.metric.AbstractMetricDetailFormatter;
+import org.dbsyncer.biz.vo.MetricResponseVo;
+import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.monitor.model.Sample;
+
+import java.text.DecimalFormat;
+
+public class MemoryMetricDetailFormatter extends AbstractMetricDetailFormatter {
+
+    @Override
+    public void apply(MetricResponseVo vo) {
+        Sample sample = vo.getMeasurements().get(0);
+        Double value = (Double) sample.getValue();
+        vo.setDetail(String.format("%.2fMB", (value / 1024 / 1024)));
+    }
+
+}

+ 15 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/ValueMetricDetailFormatter.java

@@ -0,0 +1,15 @@
+package org.dbsyncer.biz.metric.impl;
+
+import org.dbsyncer.biz.metric.AbstractMetricDetailFormatter;
+import org.dbsyncer.biz.vo.MetricResponseVo;
+import org.dbsyncer.monitor.model.Sample;
+
+public final class ValueMetricDetailFormatter extends AbstractMetricDetailFormatter {
+
+    @Override
+    public void apply(MetricResponseVo vo) {
+        Sample sample = vo.getMeasurements().get(0);
+        vo.setDetail(String.valueOf(sample.getValue()));
+    }
+
+}

+ 9 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/vo/MetricResponseVo.java

@@ -4,4 +4,13 @@ import org.dbsyncer.monitor.model.MetricResponse;
 
 public class MetricResponseVo extends MetricResponse {
 
+    private String detail;
+
+    public String getDetail() {
+        return detail;
+    }
+
+    public void setDetail(String detail) {
+        this.detail = detail;
+    }
 }

+ 48 - 0
dbsyncer-monitor/src/main/java/org/dbsyncer/monitor/enums/DiskMetricEnum.java

@@ -0,0 +1,48 @@
+package org.dbsyncer.monitor.enums;
+
+/**
+ * 硬盘指标
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2021/07/23 0:19
+ */
+public enum DiskMetricEnum {
+
+    /**
+     * 已用
+     */
+    THRESHOLD("disk.space.threshold", "硬盘", "已用"),
+
+    /**
+     * 空闲
+     */
+    FREE("disk.space.free", "硬盘", "空闲"),
+    
+    /**
+     * 总共
+     */
+    TOTAL("disk.space.total", "硬盘", "总共"),;
+
+    private String code;
+    private String group;
+    private String metricName;
+
+    DiskMetricEnum(String code, String group, String metricName) {
+        this.code = code;
+        this.group = group;
+        this.metricName = metricName;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getGroup() {
+        return group;
+    }
+
+    public String getMetricName() {
+        return metricName;
+    }
+}

+ 9 - 20
dbsyncer-monitor/src/main/java/org/dbsyncer/monitor/enums/MetricEnum.java

@@ -16,42 +16,41 @@ public enum MetricEnum {
     /**
      * 线程活跃数
      */
-    THREADS_LIVE("jvm.threads.live", "线程", "活跃数"),
+    THREADS_LIVE("jvm.threads.live", "应用线程", "活跃数"),
 
     /**
      * 线程峰值
      */
-    THREADS_PEAK("jvm.threads.peak", "线程", "峰值数"),
+    THREADS_PEAK("jvm.threads.peak", "应用线程", "峰值数"),
 
     /**
      * 内存已用
      */
-    MEMORY_USED("jvm.memory.used", "内存", "已用", "字节"),
+    MEMORY_USED("jvm.memory.used", "内存", "已用"),
 
     /**
      * 内存空闲
      */
-    MEMORY_COMMITTED("jvm.memory.committed", "内存", "空闲", "字节"),
+    MEMORY_COMMITTED("jvm.memory.committed", "内存", "空闲"),
 
     /**
      * 内存总共
      */
-    MEMORY_MAX("jvm.memory.max", "内存", "总共", "字节"),
+    MEMORY_MAX("jvm.memory.max", "内存", "总共"),
 
     /**
-     * CPU已用
+     * GC
      */
-    CPU_USAGE("system.cpu.usage", "CPU", "已用", "%"),
+    GC_PAUSE("jvm.gc.pause", "GC", "已用"),
 
     /**
-     * GC
+     * CPU已用
      */
-    GC_PAUSE("jvm.gc.pause", "GC", "已用", "秒");
+    CPU_USAGE("system.cpu.usage", "CPU", "已用");
 
     private String code;
     private String group;
     private String metricName;
-    private String baseUnit;
 
     MetricEnum(String code, String group, String metricName) {
         this.code = code;
@@ -59,13 +58,6 @@ public enum MetricEnum {
         this.metricName = metricName;
     }
 
-    MetricEnum(String code, String group, String metricName, String baseUnit) {
-        this.code = code;
-        this.group = group;
-        this.metricName = metricName;
-        this.baseUnit = baseUnit;
-    }
-
     public static MetricEnum getMetric(String code) throws ConnectorException {
         for (MetricEnum e : MetricEnum.values()) {
             if (StringUtils.equals(code, e.getCode())) {
@@ -87,7 +79,4 @@ public enum MetricEnum {
         return metricName;
     }
 
-    public String getBaseUnit() {
-        return baseUnit;
-    }
 }

+ 2 - 3
dbsyncer-web/src/main/java/org/dbsyncer/web/config/TaskPoolConfig.java

@@ -27,8 +27,8 @@ public class TaskPoolConfig {
         //最大线程数128:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
         //maxPoolSize 当系统负载大道最大值时,核心线程数已无法按时处理完所有任务,这是就需要增加线程.每秒200个任务需要20个线程,那么当每秒1000个任务时,则需要(1000-queueCapacity)*(20/200),即60个线程,可将maxPoolSize设置为60;
         executor.setMaxPoolSize(128);
-        //缓冲队列360:用来缓冲执行任务的队列
-        executor.setQueueCapacity(360);
+        //缓冲队列1000:用来缓冲执行任务的队列
+        executor.setQueueCapacity(1000);
         //允许线程的空闲时间30秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
         executor.setKeepAliveSeconds(30);
         //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
@@ -60,5 +60,4 @@ public class TaskPoolConfig {
         return taskScheduler;
     }
 
-
 }

+ 52 - 19
dbsyncer-web/src/main/java/org/dbsyncer/web/controller/monitor/MonitorController.java

@@ -3,21 +3,28 @@ package org.dbsyncer.web.controller.monitor;
 import org.dbsyncer.biz.MonitorService;
 import org.dbsyncer.biz.vo.RestResult;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.monitor.enums.DiskMetricEnum;
 import org.dbsyncer.monitor.enums.MetricEnum;
+import org.dbsyncer.monitor.enums.StatisticEnum;
 import org.dbsyncer.monitor.model.MetricResponse;
 import org.dbsyncer.monitor.model.Sample;
 import org.dbsyncer.web.controller.BaseController;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthEndpoint;
 import org.springframework.boot.actuate.metrics.MetricsEndpoint;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.ModelMap;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -33,29 +40,33 @@ public class MonitorController extends BaseController {
     @Autowired
     private MetricsEndpoint metricsEndpoint;
 
+    @Autowired
+    private HealthEndpoint healthEndpoint;
+
     @ResponseBody
     @RequestMapping("/get")
     public RestResult get() {
         try {
+            List<MetricResponse> list = new ArrayList<>();
+            // 系统指标
             List<MetricEnum> metricEnumList = monitorService.getMetricEnumAll();
-            if (CollectionUtils.isEmpty(metricEnumList)) {
-                return RestResult.restSuccess(Collections.EMPTY_LIST);
+            if (!CollectionUtils.isEmpty(metricEnumList)) {
+                metricEnumList.forEach(m -> {
+                    MetricsEndpoint.MetricResponse metric = metricsEndpoint.metric(m.getCode(), null);
+                    MetricResponse metricResponse = new MetricResponse();
+                    MetricEnum metricEnum = MetricEnum.getMetric(metric.getName());
+                    metricResponse.setCode(metricEnum.getCode());
+                    metricResponse.setGroup(metricEnum.getGroup());
+                    metricResponse.setMetricName(metricEnum.getMetricName());
+                    if (!CollectionUtils.isEmpty(metric.getMeasurements())) {
+                        List<Sample> measurements = new ArrayList<>();
+                        metric.getMeasurements().forEach(s -> measurements.add(new Sample(s.getStatistic().getTagValueRepresentation(), s.getValue())));
+                        metricResponse.setMeasurements(measurements);
+                    }
+                    list.add(metricResponse);
+                });
             }
-            List<MetricResponse> list = new ArrayList<>();
-            metricEnumList.forEach(m -> {
-                MetricsEndpoint.MetricResponse metric = metricsEndpoint.metric(m.getCode(), null);
-                MetricResponse metricResponse = new MetricResponse();
-                MetricEnum metricEnum = MetricEnum.getMetric(metric.getName());
-                metricResponse.setCode(metricEnum.getCode());
-                metricResponse.setGroup(metricEnum.getGroup());
-                metricResponse.setMetricName(metricEnum.getMetricName());
-                if (!CollectionUtils.isEmpty(metric.getMeasurements())) {
-                    List<Sample> measurements = new ArrayList<>();
-                    metric.getMeasurements().forEach(s -> measurements.add(new Sample(s.getStatistic().getTagValueRepresentation(), s.getValue())));
-                    metricResponse.setMeasurements(measurements);
-                }
-                list.add(metricResponse);
-            });
+            list.addAll(getDiskHealth());
             return RestResult.restSuccess(monitorService.queryMetric(list));
         } catch (Exception e) {
             logger.error(e.getLocalizedMessage(), e.getClass());
@@ -63,6 +74,28 @@ public class MonitorController extends BaseController {
         }
     }
 
+    /**
+     * 硬盘状态
+     *
+     * @return
+     */
+    private List<MetricResponse> getDiskHealth() {
+        List<MetricResponse> list = new ArrayList<>();
+        Health health = healthEndpoint.health();
+        Map<String, Object> details = health.getDetails();
+        Health diskSpace = (Health) details.get("diskSpace");
+        Map<String, Object> diskSpaceDetails = diskSpace.getDetails();
+        list.add(createDiskMetricResponse(DiskMetricEnum.THRESHOLD, diskSpaceDetails.get("threshold")));
+        list.add(createDiskMetricResponse(DiskMetricEnum.FREE, diskSpaceDetails.get("free")));
+        list.add(createDiskMetricResponse(DiskMetricEnum.TOTAL, diskSpaceDetails.get("total")));
+        return list;
+    }
+
+    private MetricResponse createDiskMetricResponse(DiskMetricEnum metricEnum, Object value) {
+        return new MetricResponse(metricEnum.getCode(), metricEnum.getGroup(), metricEnum.getMetricName(),
+                Arrays.asList(new Sample(StatisticEnum.COUNT.getTagValueRepresentation(), value)));
+    }
+
     @RequestMapping("")
     public String index(HttpServletRequest request, ModelMap model) {
         Map<String, String> params = getParams(request);

+ 94 - 73
dbsyncer-web/src/main/resources/public/monitor/monitor.html

@@ -68,90 +68,111 @@
 
             </div>
 
-            <!-- 性能指标 -->
+            <!-- 应用性能 -->
             <div class="col-md-12">
-                <div class="col-md-6">
-                    <table class="table table-hover">
-                        <caption>系统性能</caption>
-                        <thead>
-                        <tr>
-                            <th style="width:10%;">类型</th>
-                            <th style="width:10%;">状态</th>
-                            <th style="width:80%;">指标</th>
-                        </tr>
-                        </thead>
-                        <tbody id="systemList"></tbody>
-                    </table>
-                </div>
+                <div class="panel-group">
+                    <div class="panel panel-success">
+                        <div class="panel-heading">
+                            <h4 class="panel-title">
+                                <u data-toggle="collapse" class="dbsyncer_pointer" href="#systemMetrics">应用性能</u>
+                            </h4>
+                        </div>
+                        <div id="systemMetrics" class="panel-body panel-collapse collapse in">
+                            <div class="col-md-6">
+                                <div class="row">
+                                    <div class="col-md-6">
+                                        <div id="totalChart" style="height: 260px; max-width: 260px; margin: 0px auto;"></div>
+                                    </div>
 
-                <div class="col-md-3">
-                    <div id="cpuChart" style="height: 260px; max-width: 260px; margin: 0px auto;"></div>
-                </div>
+                                    <div class="col-md-6">
+                                        <div id="eventChart" style="height: 260px; max-width: 260px; margin: 0px auto;"></div>
+                                    </div>
+                                </div>
+                                <div class="row">
+                                    <div class="col-md-6">
+                                        <div id="queueChart" style="height: 260px; max-width: 260px; margin: 0px auto;"></div>
+                                    </div>
 
-                <div class="col-md-3">
-                    <div id="memChart" style="height: 260px; max-width: 260px; margin: 0px auto;"></div>
-                </div>
-            </div>
+                                    <div class="col-md-6"></div>
+                                </div>
+                            </div>
 
-            <!-- 系统指标 -->
-            <div class="col-md-12">
-                <div class="col-md-6">
-                    <table class="table table-hover">
-                        <caption>系统指标</caption>
-                        <thead>
-                        <tr>
-                            <th style="width:3%;"></th>
-                            <th style="width:27%;">分组</th>
-                            <th style="width:60%;">名称</th>
-                            <th style="width:10%;">值</th>
-                        </tr>
-                        </thead>
-                        <tr th:each="m,s : ${metrics}">
-                            <td th:text="${s.index}+1"></td>
-                            <td th:text="${m?.group}"></td>
-                            <td th:text="${m?.metricName}"></td>
-                            <td th:text="${m?.measurements?.get(0)?.value}"></td><!-- value-->
-                        </tr>
-                    </table>
+                            <div class="col-md-6">
+                                <div class="row">
+                                    <div class="col-md-12">
+                                        <table class="table table-hover">
+                                            <thead>
+                                            <tr>
+                                                <th style="width:3%;"></th>
+                                                <th style="width:30%;">名称</th>
+                                                <th style="width:42%;">详细</th>
+                                                <th style="width:25%;">类型</th>
+                                            </tr>
+                                            </thead>
+                                            <tr th:each="m,s : ${metrics}">
+                                                <td th:text="${s.index}+1"></td>
+                                                <td th:text="${'['+ m?.group + '] ' + m?.metricName}"></td>
+                                                <td th:text="${m?.detail}"></td>
+                                                <td th:text="${m?.code}"></td>
+                                            </tr>
+                                        </table>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+
+                    </div>
                 </div>
             </div>
 
             <!-- 日志 -->
             <div class="col-md-12">
-                <div class="form-group">
-                    <div class="col-sm-4">
-                        <input id="searchLogKeyword" class="form-control" type="text" maxlength="32" placeholder="请输入内容关键字(最多32个字)." />
-                    </div>
-                    <div class="col-md-1">
-                        <button id="queryLogBtn" type="button" class="btn btn-primary">查询日志</button>
-                    </div>
-                    <div class="col-md-4"></div>
-                    <div class="col-md-3 text-right">
-                        <button th:id="${metaId}" type="button" class="btn btn-default clearLogBtn">清空日志</button>
-                    </div>
-                </div>
+                <div class="panel-group">
+                    <div class="panel panel-default">
+                        <div class="panel-heading">
+                            <h4 class="panel-title">
+                                <u data-toggle="collapse" class="dbsyncer_pointer" href="#queryLogPanel">查询日志</u>
+                            </h4>
+                        </div>
+                        <div id="queryLogPanel" class="panel-body panel-collapse collapse">
+                            <div class="form-group">
+                                <div class="col-sm-4">
+                                    <input id="searchLogKeyword" class="form-control" type="text" maxlength="32" placeholder="请输入内容关键字(最多32个字)." />
+                                </div>
+                                <div class="col-md-1">
+                                    <button id="queryLogBtn" type="button" class="btn btn-primary">查询日志</button>
+                                </div>
+                                <div class="col-md-4"></div>
+                                <div class="col-md-3 text-right">
+                                    <button th:id="${metaId}" type="button" class="btn btn-default clearLogBtn">清空日志</button>
+                                </div>
+                            </div>
 
-                <table class="table table-hover">
-                    <thead>
-                    <tr>
-                        <th style="width:3%;"></th>
-                        <th style="width:70%;">内容</th>
-                        <th style="width:27%;">时间</th>
-                    </tr>
-                    </thead>
-                    <tbody id="logList">
-                    <tr th:each="l,s : ${pagingLog?.data}">
-                        <td th:text="${s.index}+1"></td>
-                        <td th:text="${l?.json}"></td>
-                        <td th:text="${#dates.format(l?.createTime, 'yyyy-MM-dd HH:mm:ss')}"></td>
-                    </tr>
-                    </tbody>
-                </table>
+                            <table class="table table-hover">
+                                <thead>
+                                <tr>
+                                    <th style="width:3%;"></th>
+                                    <th style="width:70%;">内容</th>
+                                    <th style="width:27%;">时间</th>
+                                </tr>
+                                </thead>
+                                <tbody id="logList">
+                                <tr th:each="l,s : ${pagingLog?.data}">
+                                    <td th:text="${s.index}+1"></td>
+                                    <td th:text="${l?.json}"></td>
+                                    <td th:text="${#dates.format(l?.createTime, 'yyyy-MM-dd HH:mm:ss')}"></td>
+                                </tr>
+                                </tbody>
+                            </table>
+
+                            <div class="form-group">
+                                <div class="col-md-5">共计: <span id="logTotal">[[${pagingLog?.total}]]</span>条</div>
+                                <div class="col-md-7">
+                                    <a href="javascript:void(0);" id="queryLogMore" num="1">显示更多<i class="fa fa-angle-double-down" aria-hidden="true"></i></a>
+                                </div>
+                            </div>
+                        </div>
 
-                <div class="form-group">
-                    <div class="col-md-5">共计: <span id="logTotal">[[${pagingLog?.total}]]</span>条</div>
-                    <div class="col-md-7">
-                        <a href="javascript:void(0);" id="queryLogMore" num="1">显示更多<i class="fa fa-angle-double-down" aria-hidden="true"></i></a>
                     </div>
                 </div>
             </div>

+ 2 - 9
dbsyncer-web/src/main/resources/static/js/common.js

@@ -78,10 +78,8 @@ function doPoster(url, params, action) {
 }
 
 // 全局Ajax get
-function doGetter(url, params, action, loading) {
-    if(loading == undefined || loading == true){
-        $.loadingT(true);
-    }
+function doGetter(url, params, action) {
+    $.loadingT(true);
     $.get($basePath + url, params, function (data) {
         $.loadingT(false);
         action(data);
@@ -89,9 +87,4 @@ function doGetter(url, params, action, loading) {
         $.loadingT(false);
         bootGrowl("访问异常,请刷新或重试.", "danger");
     });
-}
-
-// 全局Ajax get, 不显示加载动画
-function doGetWithoutLoading(url, params, action) {
-    doGetter(url, params, action, false);
 }

+ 131 - 164
dbsyncer-web/src/main/resources/static/js/monitor/index.js

@@ -211,176 +211,143 @@ function showLog($logList, arr, append){
     return html;
 }
 
-// 查看系统指标
-function showSystemInfo(){
-    doGetWithoutLoading("/app/health",{}, function (data) {
-        var details = data.details;
-        var html = showPoint("硬盘", details.diskSpace);
-
-        doGetWithoutLoading("/app/metrics/jvm.threads.live",{}, function (data) {
-            html += showSystemItem("线程活跃", data.measurements[0].value);
-            doGetWithoutLoading("/app/metrics/jvm.threads.peak",{}, function (data) {
-                html += showSystemItem("线程峰值", data.measurements[0].value);
-                doGetWithoutLoading("/app/metrics/jvm.gc.pause",{}, function (data) {
-                    var count =  data.measurements[0].value;
-                    var time =  data.measurements[1].value;
-                    time = time.toFixed(2);
-                    var text = count+"次";
-                    text += ",耗时:"+time + "秒";
-                    html += showSystemItem("GC", text);
-                    $("#systemList").html(html);
-                });
-            });
-        });
-    });
-
+function random(min, max) {
+    return Math.floor(Math.random() * (max - min)) + min;
 }
 
-// CPU
-function showCpu(){
-    doGetWithoutLoading("/app/metrics/system.cpu.usage",{}, function (data) {
-        var value = data.measurements[0].value * 100;
-        value = value.toFixed(2);
-        var option={
-            title:{
-                text:"CPU",
-                x:'center',
-                y: 'top'
-            },
-            tooltip : {
-                formatter: "{a}: {c}%",
-                position: 'top'
-            },
-            series: [
-                {
-                    name: "已用",
-                    animation: true,
-                    type: 'gauge',
-                    min: 0,
-                    max: 100,
-                    splitNumber: 4,
-                    axisLine: {            // 坐标轴线
-                        lineStyle: {       // 属性lineStyle控制线条样式
-                            color: [[0.1, '#d9534f'], [0.3, '#f0ad4e'],[0.8, '#5bc0de'],[1, '#5cb85c']],
-                            width: 10
-                        }
-                    },
-                    axisTick: {            // 坐标轴小标记
-                        length: 15,        // 属性length控制线长
-                        lineStyle: {       // 属性lineStyle控制线条样式
-                            color: 'auto'
-                        }
-                    },
-                    splitLine: {           // 分隔线
-                        length: 20,         // 属性length控制线长
-                        lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式
-                            color: 'auto'
-                        }
-                    },
-                    detail: {formatter:'{value}%', fontSize:12, offsetCenter:[0,'65%']},
-                    data: [{value: value, name: ''}]
-                }
-            ]
-        };
-        echarts.init(document.getElementById('cpuChart')).setOption(option);
-
-    });
+// 堆积数据
+function showQueueChart(){
+    var value = random(1,1000);
+    var option={
+        title:{
+            text:"堆积数据",
+            x:'center',
+            y: 'top'
+        },
+        tooltip : {
+            formatter: "{a}: {c}",
+            position: 'top'
+        },
+        series: [
+            {
+                name: "待处理",
+                animation: true,
+                type: 'gauge',
+                min: 0,
+                max: 1000,
+                splitNumber: 5,
+                axisLine: {            // 坐标轴线
+                    lineStyle: {       // 属性lineStyle控制线条样式
+                        color: [[0.1, '#d9534f'], [0.3, '#f0ad4e'],[0.8, '#5bc0de'],[1, '#5cb85c']],
+                        width: 10
+                    }
+                },
+                axisTick: {            // 坐标轴小标记
+                    length: 15,        // 属性length控制线长
+                    lineStyle: {       // 属性lineStyle控制线条样式
+                        color: 'auto'
+                    }
+                },
+                splitLine: {           // 分隔线
+                    length: 20,         // 属性length控制线长
+                    lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式
+                        color: 'auto'
+                    }
+                },
+                detail: {fontSize:12, offsetCenter:[0,'65%']},
+                data: [{value: value, name: ''}]
+            }
+        ]
+    };
+    echarts.init(document.getElementById('queueChart')).setOption(option);
 }
 
-// 内存
-function showMem(){
-    doGetWithoutLoading("/app/metrics/jvm.memory.max",{}, function (data) {
-        var max = data.measurements[0].value;
-        max = (max / 1024 / 1024 / 1024).toFixed(2);
-        doGetWithoutLoading("/app/metrics/jvm.memory.used",{}, function (data) {
-            var used = data.measurements[0].value;
-            used = (used / 1024 / 1024 / 1024).toFixed(2);
-            doGetWithoutLoading("/app/metrics/jvm.memory.committed",{}, function (data) {
-                var committed = data.measurements[0].value;
-                committed = (committed / 1024 / 1024 / 1024).toFixed(2);
+// 事件分类
+function showEventChart(){
+    var del = 2;
+    var upd = 10;
+    var ins = 3;
 
-                var option = {
-                    title : {
+    var option = {
+        title : {
+            show:true,
+            text: '事件分类',
+            x:'center',
+            y: 'top'
+        },
+        tooltip : {
+            trigger: 'item',
+            formatter: "{b} : {c}"
+        },
+        series : [
+            {
+                type:'pie',
+                color: function(params) {
+                    // build a color map as your need.
+                    var colorList = [
+                        '#60C0DD','#F0805A','#89DFAA'
+                    ];
+                    return colorList[params.dataIndex]
+                },
+                label:{
+                    normal:{
                         show:true,
-                        text: '内存'+ max +'GB',
-                        x:'center',
-                        y: 'top'
-                    },
-                    tooltip : {
-                        trigger: 'item',
-                        formatter: "{b} : {c} GB"
-                    },
-                    series : [
-                        {
-                            name:'内存',
-                            type:'pie',
-                            color: function(params) {
-                                // build a color map as your need.
-                                var colorList = [
-                                    '#60C0DD','#F0805A','#89DFAA'
-                                ];
-                                return colorList[params.dataIndex]
-                            },
-                            label:{
-                                normal:{
-                                    show:true,
-                                    position:'inner',
-                                    formatter:'{d}%'
-                                }
-                            },
-                            data:[
-                                {value:max,name:'总共'},
-                                {value:used,name:'已用'},
-                                {value:committed,name:'空闲'}
-                            ]
-                        }
-                    ]
-                };
-                echarts.init(document.getElementById('memChart')).setOption(option);
-
-            });
-        });
-    });
-
+                        position:'inner',
+                        formatter:'{d}%'
+                    }
+                },
+                data:[
+                    {value:upd, name:'更新'},
+                    {value:del, name:'删除'},
+                    {value:ins, name:'插入'}
+                ]
+            }
+        ]
+    };
+    echarts.init(document.getElementById('eventChart')).setOption(option);
 }
 
-function showPoint(title, point){
-    var status = point.status;
-    var d = point.details;
-    var total = (d.total / 1024 / 1024 / 1024).toFixed(2);
-    var threshold = (d.threshold / 1024 / 1024 / 1024).toFixed(2);
-    var free = (d.free / 1024 / 1024 / 1024).toFixed(2);
-
-    // UP/DOWN success/danger
-    var statusColor = status == 'UP' ? 'success' : 'danger';
-
-    // more than 63%/78% waring/danger
-    var precent = (threshold / total).toFixed(2);
-    var barColor = precent >= 63 ? 'waring' : 'success';
-    barColor = precent >= 78 ? 'danger' : barColor;
+// 统计成功失败
+function showTotalChart(){
+    var success = 10;
+    var fail = 5;
 
-    var html = "";
-    html += "<tr>";
-    html += "   <td>" + title + "</td>";
-    html += "   <td><span class='label label-" + statusColor + "'>" + status + "</span></td>";
-    html += "   <td>";
-    html += "       <div class='progress' title='总共" + total + "GB,已用" + threshold + "GB,空闲" + free + "GB'>";
-    html += "           <div class='progress-bar progress-bar-" + barColor + " progress-bar-striped active' style='width: " + precent + "%'>" + threshold + "GB</div>";
-    html += "           <div class='progress-bar' style='width: " + (100 - precent) + "%'>" + free + "GB</div>";
-    html += "       </div>";
-    html += "   </td>";
-    html += "</tr>";
-    return html;
-}
-
-function showSystemItem(title, value){
-    var html = "";
-    html += "<tr>";
-    html += "   <td>" + title + "</td>";
-    html += "   <td><span class='label label-success'>UP</span></td>";
-    html += "   <td>"+value+"</td>";
-    html += "</tr>";
-    return html;
+    var option = {
+        title : {
+            show:true,
+            text: '已完成数据',
+            x:'center',
+            y: 'top'
+        },
+        tooltip : {
+            trigger: 'item',
+            formatter: "{b} : {c}"
+        },
+        series : [
+            {
+                type:'pie',
+                color: function(params) {
+                    // build a color map as your need.
+                    var colorList = [
+                        '#60C0DD','#F0805A'
+                    ];
+                    return colorList[params.dataIndex]
+                },
+                label:{
+                    normal:{
+                        show:true,
+                        position:'inner',
+                        formatter:'{d}%'
+                    }
+                },
+                data:[
+                    {value:success, name:'成功'},
+                    {value:fail, name:'失败'}
+                ]
+            }
+        ]
+    };
+    echarts.init(document.getElementById('totalChart')).setOption(option);
 }
 
 $(function () {
@@ -409,9 +376,9 @@ $(function () {
     bindClearEvent($(".clearDataBtn"), "确认清空数据?", "清空数据成功!", "/monitor/clearData");
     bindClearEvent($(".clearLogBtn"), "确认清空日志?", "清空日志成功!", "/monitor/clearLog");
 
-    showCpu();
-    showMem();
-    showSystemInfo();
+    showTotalChart();
+    showEventChart();
+    showQueueChart();
 
     // 绑定回车事件
     $("#searchDataKeyword").keydown(function (e) {