feat: Phase 2-5 监控中心全栈实现 — 指标浏览器/SNMP/站点拨测/中间件

Phase 2 指标监控:
- 修复 /metrics 路由(原指向 AlertManager → 现指向 MetricsExplorer)
- 新建 MetricsHandler (4 API): targets/list/query/names
- 新建 MetricsExplorer 前端(170行): 目标选择器+指标分类树+多指标叠加SVG图表

Phase 3 SNMP设备:
- 新建 SNMPHandler (9 API): devices CRUD/templates/stats
- SNMPMonitor 接入真实API(428行): 设备表格+添加对话框+删除

Phase 4 站点拨测:
- 新建 SiteHandler (8 API): tasks CRUD/results/stats
- SiteMonitor 接入真实API(542行): 任务表+添加对话框+拨测类型网格
- 新增 siteApi 到 api.ts

Phase 5 中间件采集:
- Agent 新增 collector/middleware.go: Redis INFO + MySQL handshake 采集
- Agent CLI 新增 -redis/-redis-auth/-mysql/-mysql-user/-mysql-pass
- MiddlewareMonitor 接入真实API(301行): 实例卡片+指标面板

基础设施:
- AutoMigrate 新增 23 张监控表
- 前后端容器构建部署验证通过
This commit is contained in:
attacker committed 2026-06-18 13:02:19 +00:00
1 parent 94dbc89b9b
commit 2e71371257
15 files changed
+2616 -137

No files matched your search

+48
View File
@@ -12,6 +12,7 @@ import (
"log"
"os"
"os/signal"
"strings"
"syscall"
"time"
@@ -32,6 +33,14 @@ func main() {
interval := flag.Int("interval", 10, "采集与上报间隔,单位:秒")
token := flag.String("token", "", "Bearer 鉴权令牌")
hostnameFlag := flag.String("hostname", "", "上报主机名,默认使用系统主机名")
// 中间件采集配置
redisFlag := flag.String("redis", "", "Redis 监控地址,逗号分隔多实例,格式 host:port")
redisAuthFlag := flag.String("redis-auth", "", "Redis 认证密码")
mysqlFlag := flag.String("mysql", "", "MySQL 监控地址,逗号分隔多实例,格式 host:port")
mysqlUserFlag := flag.String("mysql-user", "root", "MySQL 用户名")
mysqlPassFlag := flag.String("mysql-pass", "", "MySQL 密码")
flag.Parse()
// 统一日志格式:带微秒时间戳,便于排查问题
@@ -68,6 +77,20 @@ func main() {
diskIOCollector := collector.NewDiskIOCollector()
rep := reporter.New(*server, *token, logger)
// 中间件采集器(可选)
var mwCollector *collector.MiddlewareCollector
if *redisFlag != "" || *mysqlFlag != "" {
mwCfg := collector.MiddlewareConfig{
RedisAddrs: parseAddrList(*redisFlag),
RedisAuth: *redisAuthFlag,
MySQLAddrs: parseAddrList(*mysqlFlag),
MySQLUser: *mysqlUserFlag,
MySQLPass: *mysqlPassFlag,
}
mwCollector = collector.NewMiddlewareCollector(mwCfg)
logger.Printf("中间件采集已启用: redis=%d mysql=%d", len(mwCfg.RedisAddrs), len(mwCfg.MySQLAddrs))
}
// 初始化任务执行器与任务客户端(与 reporter 复用相同的 server/token/hostname)
taskExecutor := task.New(logger)
taskClient := task.NewClient(*server, *token, hostname, logger)
@@ -122,6 +145,15 @@ func main() {
report.DiskIO = dioStat
}
// 中间件采集(可选)
if mwCollector != nil {
if mwStat, err := mwCollector.Collect(); err != nil {
logger.Printf("中间件采集异常: %v", err)
} else {
report.Middleware = mwStat
}
}
if err := rep.Send(ctx, report); err != nil {
logger.Printf("上报失败: %v", err)
return
@@ -208,3 +240,19 @@ func maskToken(token string) string {
}
return token[:4] + "****"
}
// parseAddrList 解析逗号分隔的地址列表,去除空白
func parseAddrList(raw string) []string {
if raw == "" {
return nil
}
parts := strings.Split(raw, ",")
var result []string
for _, p := range parts {
p = strings.TrimSpace(p)
if p != "" {
result = append(result, p)
}
}
return result
}