优化服务监控的数据查询逻辑
This commit is contained in:
1 parent
c4575e976c
commit
76355e57c6
8 files changed
+63
-126
No files matched your search
@@ -11,43 +11,26 @@ import (
|
||||
type MonitorHandler struct {
|
||||
logger *zap.Logger
|
||||
monitorService *service.MonitorService
|
||||
agentService *service.AgentService
|
||||
}
|
||||
|
||||
func NewMonitorHandler(logger *zap.Logger, monitorService *service.MonitorService) *MonitorHandler {
|
||||
func NewMonitorHandler(logger *zap.Logger, monitorService *service.MonitorService, agentService *service.AgentService) *MonitorHandler {
|
||||
return &MonitorHandler{
|
||||
logger: logger,
|
||||
monitorService: monitorService,
|
||||
agentService: agentService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *MonitorHandler) List(c echo.Context) error {
|
||||
keyword := c.QueryParam("keyword")
|
||||
name := c.QueryParam("name")
|
||||
target := c.QueryParam("target")
|
||||
typeParam := c.QueryParam("type")
|
||||
enabled := c.QueryParam("enabled")
|
||||
|
||||
pr := orz.GetPageRequest(c, "-updated_at", "name")
|
||||
pr := orz.GetPageRequest(c, "name")
|
||||
|
||||
builder := orz.NewPageBuilder(h.monitorService.MonitorRepo).
|
||||
PageRequest(pr)
|
||||
|
||||
// 如果有 keyword,则搜索 name(也可以搜索 target)
|
||||
if keyword != "" {
|
||||
// keyword 可以匹配 name 或 target
|
||||
builder.Contains("name", keyword)
|
||||
// 如果需要同时搜索 target,可以手动构建 OR 查询
|
||||
// 这里简化处理,只搜索 name
|
||||
} else {
|
||||
// 否则使用独立的 name 和 target 搜索
|
||||
builder.Contains("name", name).
|
||||
Contains("target", target)
|
||||
}
|
||||
|
||||
// 处理类型筛选
|
||||
if typeParam != "" {
|
||||
builder.Equal("type", typeParam)
|
||||
}
|
||||
PageRequest(pr).
|
||||
Keyword([]string{"name", "target", "type"}, keyword)
|
||||
|
||||
// 处理启用状态筛选
|
||||
if enabled == "true" {
|
||||
@@ -61,6 +44,33 @@ func (h *MonitorHandler) List(c echo.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var agentIds []string
|
||||
for _, item := range page.Items {
|
||||
if len(item.AgentIds) > 0 {
|
||||
agentIds = append(agentIds, item.AgentIds...)
|
||||
}
|
||||
}
|
||||
if len(agentIds) > 0 {
|
||||
agents, err := h.agentService.AgentRepo.FindByIdIn(ctx, agentIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var agentNameMap = make(map[string]string)
|
||||
for _, agent := range agents {
|
||||
agentNameMap[agent.ID] = agent.Name
|
||||
}
|
||||
|
||||
for i, monitor := range page.Items {
|
||||
if len(monitor.AgentIds) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, agentId := range monitor.AgentIds {
|
||||
page.Items[i].AgentNames = append(page.Items[i].AgentNames, agentNameMap[agentId])
|
||||
}
|
||||
}
|
||||
}
|
||||
return orz.Ok(c, page)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ type MonitorStats struct {
|
||||
MonitorName string `gorm:"-" json:"name"` // 监控项名称(不存储在数据库,仅用于 API 返回)
|
||||
MonitorType string `json:"type"` // 监控类型
|
||||
Target string `json:"target"` // 目标地址
|
||||
ShowTargetPublic bool `gorm:"-" json:"showTargetPublic"` // 在公开页面是否显示目标地址(不存储在数据库,仅用于 API 返回)
|
||||
CurrentResponse int64 `json:"currentResponse"` // 当前响应时间(ms)
|
||||
AvgResponse24h int64 `json:"avgResponse24h"` // 24小时平均响应时间(ms)
|
||||
Uptime24h float64 `json:"uptime24h"` // 24小时在线率(百分比)
|
||||
|
||||
@@ -17,6 +17,7 @@ type MonitorTask struct {
|
||||
Visibility string `gorm:"default:public" json:"visibility"` // 可见性: public-匿名可见, private-登录可见
|
||||
Interval int `json:"interval"` // 检测频率(秒),默认 60
|
||||
AgentIds datatypes.JSONSlice[string] `json:"agentIds"` // 指定的探针 ID 列表(JSON 数组)
|
||||
AgentNames []string `gorm:"-" json:"agentNames"` // 指定的探针名称列表
|
||||
Tags datatypes.JSONSlice[string] `json:"tags"` // 指定的标签列表(JSON 数组),拥有这些标签的探针都会执行此监控
|
||||
HTTPConfig datatypes.JSONType[protocol.HTTPMonitorConfig] `json:"httpConfig"` // HTTP 监控配置
|
||||
TCPConfig datatypes.JSONType[protocol.TCPMonitorConfig] `json:"tcpConfig"` // TCP 监控配置
|
||||
|
||||
@@ -378,93 +378,6 @@ func (s *MonitorService) resolveTargetAgents(monitor models.MonitorTask, availab
|
||||
return targetAgents
|
||||
}
|
||||
|
||||
// BroadcastMonitorConfig 向所有在线探针广播监控配置
|
||||
func (s *MonitorService) BroadcastMonitorConfig(ctx context.Context) error {
|
||||
// 获取所有启用的监控任务
|
||||
var monitors []models.MonitorTask
|
||||
if err := s.MonitorRepo.GetDB(ctx).
|
||||
Where("enabled = ?", true).
|
||||
Find(&monitors).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 如果没有启用的监控任务,直接返回(不需要发送任何配置)
|
||||
if len(monitors) == 0 {
|
||||
s.logger.Debug("没有启用的监控任务,跳过配置推送")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取所有在线探针
|
||||
agents, err := s.agentRepo.FindOnlineAgents(ctx)
|
||||
if err != nil {
|
||||
s.logger.Error("获取在线探针失败", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 按探针分组构建监控配置
|
||||
agentMonitors := make(map[string][]models.MonitorTask)
|
||||
|
||||
for _, monitor := range monitors {
|
||||
// 使用统一的方法计算目标探针
|
||||
targetAgents := s.resolveTargetAgents(monitor, agents)
|
||||
|
||||
for _, agent := range targetAgents {
|
||||
agentMonitors[agent.ID] = append(agentMonitors[agent.ID], monitor)
|
||||
}
|
||||
}
|
||||
|
||||
// 向每个有监控任务的探针发送对应的监控配置
|
||||
for agentID, tasks := range agentMonitors {
|
||||
items := make([]protocol.MonitorItem, 0, len(tasks))
|
||||
for _, task := range tasks {
|
||||
item := protocol.MonitorItem{
|
||||
ID: task.ID,
|
||||
Type: task.Type,
|
||||
Target: task.Target,
|
||||
}
|
||||
|
||||
if task.Type == "http" || task.Type == "https" {
|
||||
var httpConfig protocol.HTTPMonitorConfig
|
||||
if err := task.HTTPConfig.Scan(&httpConfig); err == nil {
|
||||
item.HTTPConfig = &httpConfig
|
||||
}
|
||||
} else if task.Type == "tcp" {
|
||||
var tcpConfig protocol.TCPMonitorConfig
|
||||
if err := task.TCPConfig.Scan(&tcpConfig); err == nil {
|
||||
item.TCPConfig = &tcpConfig
|
||||
}
|
||||
} else if task.Type == "icmp" || task.Type == "ping" {
|
||||
var icmpConfig protocol.ICMPMonitorConfig
|
||||
if err := task.ICMPConfig.Scan(&icmpConfig); err == nil {
|
||||
item.ICMPConfig = &icmpConfig
|
||||
}
|
||||
}
|
||||
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
// 构建监控配置 payload
|
||||
// Interval 字段不再使用(探针收到后立即检测一次),但保留字段兼容性
|
||||
payload := protocol.MonitorConfigPayload{
|
||||
Interval: 0,
|
||||
Items: items,
|
||||
}
|
||||
|
||||
// 发送监控配置到指定探针
|
||||
if err := s.sendMonitorConfigToAgent(agentID, payload); err != nil {
|
||||
s.logger.Error("发送监控配置失败",
|
||||
zap.String("agentID", agentID),
|
||||
zap.Error(err))
|
||||
} else {
|
||||
s.logger.Debug("发送监控配置成功",
|
||||
zap.String("agentID", agentID),
|
||||
zap.Int("taskCount", len(items)))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// sendMonitorConfigToAgent 向指定探针发送监控配置(内部方法)
|
||||
func (s *MonitorService) sendMonitorConfigToAgent(agentID string, payload protocol.MonitorConfigPayload) error {
|
||||
payloadData, err := json.Marshal(payload)
|
||||
@@ -688,24 +601,38 @@ func (s *MonitorService) GetMonitorStatsByID(ctx context.Context, monitorID stri
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取探针列表
|
||||
agents, err := s.agentRepo.FindAll(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 当前监控任务的关联的探针
|
||||
targetAgents := s.resolveTargetAgents(monitor, agents)
|
||||
var targetAgentsMap = make(map[string]string)
|
||||
for _, agent := range targetAgents {
|
||||
targetAgentsMap[agent.ID] = agent.Name
|
||||
}
|
||||
|
||||
// 填充监控名称、探针名称和隐私设置
|
||||
for i := range statsList {
|
||||
statsList[i].MonitorName = monitor.Name
|
||||
statsList[i].ShowTargetPublic = monitor.ShowTargetPublic
|
||||
var filteredStatsList []models.MonitorStats
|
||||
for _, stats := range statsList {
|
||||
agentName, ok := targetAgentsMap[stats.AgentID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
stats.MonitorName = monitor.Name
|
||||
|
||||
// 根据 ShowTargetPublic 字段决定是否隐藏 Target
|
||||
if !monitor.ShowTargetPublic {
|
||||
statsList[i].Target = "***"
|
||||
stats.Target = "******"
|
||||
}
|
||||
|
||||
// 查询探针名称
|
||||
agent, err := s.agentRepo.FindById(ctx, statsList[i].AgentID)
|
||||
if err == nil {
|
||||
statsList[i].AgentName = agent.Name
|
||||
}
|
||||
stats.AgentName = agentName
|
||||
filteredStatsList = append(filteredStatsList, stats)
|
||||
}
|
||||
|
||||
return statsList, nil
|
||||
return filteredStatsList, nil
|
||||
}
|
||||
|
||||
// GetMonitorHistory 获取监控任务的历史响应时间数据
|
||||
|
||||
@@ -38,7 +38,7 @@ func InitializeApp(logger *zap.Logger, db *gorm.DB, cfg *config.AppConfig) (*App
|
||||
alertService := service.NewAlertService(logger, db, propertyService, notifier)
|
||||
alertHandler := handler.NewAlertHandler(logger, alertService)
|
||||
propertyHandler := handler.NewPropertyHandler(logger, propertyService, notifier)
|
||||
monitorHandler := handler.NewMonitorHandler(logger, monitorService)
|
||||
monitorHandler := handler.NewMonitorHandler(logger, monitorService, agentService)
|
||||
tamperHandler := handler.NewTamperHandler(logger, tamperService)
|
||||
appComponents := &AppComponents{
|
||||
AccountHandler: accountHandler,
|
||||
|
||||
@@ -259,7 +259,7 @@ const MonitorList = () => {
|
||||
{hasAgents && (
|
||||
<Space wrap size={4}>
|
||||
<span className="text-xs text-gray-500">探针:</span>
|
||||
{record.agentIds.map((id) => (
|
||||
{record.agentNames?.map((id) => (
|
||||
<Tag key={id} color="blue">{id}</Tag>
|
||||
))}
|
||||
</Space>
|
||||
@@ -267,7 +267,7 @@ const MonitorList = () => {
|
||||
{hasTags && (
|
||||
<Space wrap size={4}>
|
||||
<span className="text-xs text-gray-500">标签:</span>
|
||||
{record.tags.map((tag) => (
|
||||
{record.tags?.map((tag) => (
|
||||
<Tag key={tag} color="green">{tag}</Tag>
|
||||
))}
|
||||
</Space>
|
||||
|
||||
@@ -392,7 +392,7 @@ const MonitorDetail = () => {
|
||||
<h1 className="text-3xl font-semibold">{monitorTitle}</h1>
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-white/80">
|
||||
{firstStat.showTargetPublic ? firstStat.target : '***'}
|
||||
{firstStat.target}
|
||||
</p>
|
||||
<p className="text-xs text-white/60">公共视图 · 实时监控概览</p>
|
||||
</div>
|
||||
|
||||
@@ -253,6 +253,7 @@ export interface MonitorTask {
|
||||
tcpConfig?: MonitorTcpConfig | null;
|
||||
icmpConfig?: MonitorIcmpConfig | null;
|
||||
agentIds?: string[];
|
||||
agentNames?: string[];
|
||||
tags?: string[]; // 标签列表,拥有这些标签的探针都会执行此监控
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
@@ -312,7 +313,6 @@ export interface MonitorStats {
|
||||
name: string; // 监控项名称
|
||||
type: string;
|
||||
target: string;
|
||||
showTargetPublic: boolean; // 在公开页面是否显示目标地址
|
||||
currentResponse: number; // 当前响应时间(ms)
|
||||
avgResponse24h: number; // 24小时平均响应时间(ms)
|
||||
uptime24h: number; // 24小时在线率(百分比)
|
||||
|
||||
Reference in new issue
Block a user