feat: add scheduler log display
This commit is contained in:
@@ -60,6 +60,8 @@ const (
|
||||
KeyPushLogMaxCount = "push_log_max_count"
|
||||
KeyLoginLogDays = "login_log_days"
|
||||
KeyLoginLogMaxCount = "login_log_max_count"
|
||||
KeySchedulerLogDays = "scheduler_log_days"
|
||||
KeySchedulerLogMaxCount = "scheduler_log_max_count"
|
||||
|
||||
// Scheduler Settings Key 常量
|
||||
KeyWorkerCount = "worker_count"
|
||||
@@ -104,6 +106,7 @@ const (
|
||||
|
||||
// 其他事件类型
|
||||
EventSystemNotice = "system_notice"
|
||||
EventSchedulerLog = "scheduler_log"
|
||||
EventNotifySent = "notify_sent"
|
||||
EventAppLogAdded = "app_log_added"
|
||||
|
||||
@@ -153,6 +156,7 @@ const (
|
||||
LogCategorySystemNotice = "system_notice"
|
||||
LogCategoryPushLog = "push_log"
|
||||
LogCategoryLoginLog = "login_log"
|
||||
LogCategorySchedulerLog = "scheduler_log"
|
||||
|
||||
// AppLog 级别
|
||||
LogLevelInfo = "info"
|
||||
|
||||
@@ -155,6 +155,8 @@ func (sc *SettingsController) GetSiteSettings(c *gin.Context) {
|
||||
settings["push_log_max_count"] = sc.settingsService.Get(constant.SectionSystem, constant.KeyPushLogMaxCount)
|
||||
settings["login_log_days"] = sc.settingsService.Get(constant.SectionSystem, constant.KeyLoginLogDays)
|
||||
settings["login_log_max_count"] = sc.settingsService.Get(constant.SectionSystem, constant.KeyLoginLogMaxCount)
|
||||
settings["scheduler_log_days"] = sc.settingsService.Get(constant.SectionSystem, constant.KeySchedulerLogDays)
|
||||
settings["scheduler_log_max_count"] = sc.settingsService.Get(constant.SectionSystem, constant.KeySchedulerLogMaxCount)
|
||||
|
||||
utils.Success(c, settings)
|
||||
}
|
||||
@@ -188,6 +190,8 @@ func (sc *SettingsController) UpdateSiteSettings(c *gin.Context) {
|
||||
PushLogMaxCount string `json:"push_log_max_count"`
|
||||
LoginLogDays string `json:"login_log_days"`
|
||||
LoginLogMaxCount string `json:"login_log_max_count"`
|
||||
SchedulerLogDays string `json:"scheduler_log_days"`
|
||||
SchedulerLogMaxCount string `json:"scheduler_log_max_count"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -228,6 +232,8 @@ func (sc *SettingsController) UpdateSiteSettings(c *gin.Context) {
|
||||
sc.settingsService.Set(constant.SectionSystem, constant.KeyPushLogMaxCount, req.PushLogMaxCount)
|
||||
sc.settingsService.Set(constant.SectionSystem, constant.KeyLoginLogDays, req.LoginLogDays)
|
||||
sc.settingsService.Set(constant.SectionSystem, constant.KeyLoginLogMaxCount, req.LoginLogMaxCount)
|
||||
sc.settingsService.Set(constant.SectionSystem, constant.KeySchedulerLogDays, req.SchedulerLogDays)
|
||||
sc.settingsService.Set(constant.SectionSystem, constant.KeySchedulerLogMaxCount, req.SchedulerLogMaxCount)
|
||||
|
||||
utils.SuccessMsg(c, "保存成功")
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ func startAppLogCleanup(appLogSvc *services.AppLogService) {
|
||||
// 初始化时执行一次清理
|
||||
appLogSvc.CleanUp()
|
||||
|
||||
// 每天凌晨或者定期清理
|
||||
ticker := time.NewTicker(24 * time.Hour)
|
||||
// 定期清理(每隔1小时执行一次巡检)
|
||||
ticker := time.NewTicker(1 * time.Hour)
|
||||
for range ticker.C {
|
||||
appLogSvc.CleanUp()
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/engigu/baihu-panel/internal/constant"
|
||||
"github.com/engigu/baihu-panel/internal/database"
|
||||
@@ -133,6 +134,10 @@ func (s *AppLogService) GetRetentionConfigs() map[string]LogRetentionConfig {
|
||||
Days: utils.ToInt(s.settingsService.Get(constant.SectionSystem, constant.KeyLoginLogDays), 30),
|
||||
MaxCount: utils.ToInt(s.settingsService.Get(constant.SectionSystem, constant.KeyLoginLogMaxCount), 1000),
|
||||
},
|
||||
constant.LogCategorySchedulerLog: {
|
||||
Days: utils.ToInt(s.settingsService.Get(constant.SectionSystem, constant.KeySchedulerLogDays), 30),
|
||||
MaxCount: utils.ToInt(s.settingsService.Get(constant.SectionSystem, constant.KeySchedulerLogMaxCount), 10000),
|
||||
},
|
||||
constant.LogCategoryDefault: {
|
||||
Days: 30,
|
||||
MaxCount: 10000,
|
||||
@@ -141,9 +146,25 @@ func (s *AppLogService) GetRetentionConfigs() map[string]LogRetentionConfig {
|
||||
return configs
|
||||
}
|
||||
|
||||
func (s *AppLogService) AddSchedulerLog(title, content, level string) error {
|
||||
if level == "" {
|
||||
level = constant.LogLevelInfo
|
||||
}
|
||||
return s.Add(&models.AppLog{
|
||||
Category: constant.LogCategorySchedulerLog,
|
||||
Title: title,
|
||||
Content: models.BigText(content),
|
||||
Level: level,
|
||||
Status: constant.LogStatusRead,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AppLogService) CleanUp() {
|
||||
configs := s.GetRetentionConfigs()
|
||||
categories := []string{constant.LogCategorySystemNotice, constant.LogCategoryPushLog, constant.LogCategoryLoginLog}
|
||||
categories := []string{constant.LogCategorySystemNotice, constant.LogCategoryPushLog, constant.LogCategoryLoginLog, constant.LogCategorySchedulerLog}
|
||||
|
||||
var totalDeleted int64
|
||||
var summaryBuilder strings.Builder
|
||||
|
||||
for _, cat := range categories {
|
||||
cfg, ok := configs[cat]
|
||||
@@ -151,11 +172,16 @@ func (s *AppLogService) CleanUp() {
|
||||
cfg = configs[constant.LogCategoryDefault]
|
||||
}
|
||||
|
||||
var daysDeleted int64
|
||||
if cfg.Days > 0 {
|
||||
deadline := time.Now().AddDate(0, 0, -cfg.Days)
|
||||
database.DB.Where("category = ? AND created_at < ?", cat, deadline).Delete(&models.AppLog{})
|
||||
res := database.DB.Where("category = ? AND created_at < ?", cat, deadline).Delete(&models.AppLog{})
|
||||
if res.Error == nil {
|
||||
daysDeleted = res.RowsAffected
|
||||
}
|
||||
}
|
||||
|
||||
var countDeleted int64
|
||||
if cfg.MaxCount > 0 {
|
||||
var total int64
|
||||
database.DB.Model(&models.AppLog{}).Where("category = ?", cat).Count(&total)
|
||||
@@ -164,12 +190,34 @@ func (s *AppLogService) CleanUp() {
|
||||
var ids []string
|
||||
database.DB.Model(&models.AppLog{}).Where("category = ?", cat).Order("created_at asc").Limit(int(deleteCount)).Pluck("id", &ids)
|
||||
if len(ids) > 0 {
|
||||
database.DB.Where("id IN ?", ids).Delete(&models.AppLog{})
|
||||
res := database.DB.Where("id IN ?", ids).Delete(&models.AppLog{})
|
||||
if res.Error == nil {
|
||||
countDeleted = res.RowsAffected
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catTotal := daysDeleted + countDeleted
|
||||
if catTotal > 0 {
|
||||
totalDeleted += catTotal
|
||||
summaryBuilder.WriteString(fmt.Sprintf("分类 [%s]: 过期清理 %d 条,溢出限制清理 %d 条;\n", cat, daysDeleted, countDeleted))
|
||||
}
|
||||
}
|
||||
|
||||
if totalDeleted > 0 {
|
||||
logger.Infof("[AppLog] 周期巡检完成清理,共删除 %d 条陈旧日志", totalDeleted)
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventSystemNotice,
|
||||
Payload: map[string]interface{}{
|
||||
"title": "系统日志定时容量收敛",
|
||||
"content": fmt.Sprintf("后台巡检已自动执行日志容量清理,共计清除陈旧或溢出记录 %d 条。\n详情明细:\n%s", totalDeleted, summaryBuilder.String()),
|
||||
"level": constant.LogLevelInfo,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
logger.Debugf("[AppLog] 完成应用日志清理策略,未检测到需要剔除的陈旧记录")
|
||||
}
|
||||
logger.Debugf("[AppLog] 完成应用日志清理策略")
|
||||
}
|
||||
|
||||
func (s *AppLogService) SubscribeEvents(bus *eventbus.EventBus) {
|
||||
@@ -281,4 +329,16 @@ func (s *AppLogService) SubscribeEvents(bus *eventbus.EventBus) {
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
// 4. [订阅] 调度日志写入
|
||||
bus.Subscribe(constant.EventSchedulerLog, func(e eventbus.Event) {
|
||||
payload, ok := e.Payload.(map[string]interface{})
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
title, _ := payload["title"].(string)
|
||||
content, _ := payload["content"].(string)
|
||||
level, _ := payload["level"].(string)
|
||||
s.AddSchedulerLog(title, content, level)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -77,6 +77,8 @@ func (s *SettingsService) InitSettings() error {
|
||||
constant.KeyPushLogMaxCount: "5000",
|
||||
constant.KeyLoginLogDays: "30",
|
||||
constant.KeyLoginLogMaxCount: "1000",
|
||||
constant.KeySchedulerLogDays: "30",
|
||||
constant.KeySchedulerLogMaxCount: "10000",
|
||||
}
|
||||
|
||||
for k, v := range defaultRetention {
|
||||
|
||||
@@ -112,6 +112,11 @@ func (m *SystemWSManager) SubscribeEvents(bus *eventbus.EventBus) {
|
||||
bus.Subscribe(constant.EventSystemNotice, func(e eventbus.Event) {
|
||||
m.Broadcast("notice", e.Payload)
|
||||
})
|
||||
|
||||
// 应用日志新增事件(驱动运行日志下属4大标签页实时流式刷新列表)
|
||||
bus.Subscribe(constant.EventAppLogAdded, func(e eventbus.Event) {
|
||||
m.Broadcast(e.Type, e.Payload)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *ClientConnection) Close() {
|
||||
|
||||
@@ -112,6 +112,15 @@ func (es *ExecutorService) initScheduler() {
|
||||
es.scheduler.Start()
|
||||
|
||||
logger.Infof("[Executor] 调度器已启动: workers=%d, queue=%d, rate=%dms", workerCount, queueSize, rateInterval)
|
||||
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventSchedulerLog,
|
||||
Payload: map[string]interface{}{
|
||||
"title": "调度器启动",
|
||||
"content": fmt.Sprintf("主服务任务调度引擎已成功拉起运行。\n配置 Worker 数量: %d\n等待队列容量: %d\n速率限制间隔: %dms", workerCount, queueSize, rateInterval),
|
||||
"level": constant.LogLevelInfo,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// ServerSchedulerHandler 实现 executor.SchedulerEventHandler
|
||||
@@ -128,6 +137,15 @@ func (h *ServerSchedulerHandler) OnTaskScheduled(req *executor.ExecutionRequest)
|
||||
"status": constant.TaskStatusQueued,
|
||||
},
|
||||
})
|
||||
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventSchedulerLog,
|
||||
Payload: map[string]interface{}{
|
||||
"title": "触发任务",
|
||||
"content": fmt.Sprintf("任务 [%s] (#%s) 调度类型: %s\n已成功推入后台调度排队队列等待执行。", req.Name, req.TaskID, req.Type),
|
||||
"level": constant.LogLevelInfo,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,6 +592,15 @@ func (es *ExecutorService) loadCronTasks() {
|
||||
}
|
||||
}
|
||||
logger.Infof("[Executor] 启动调度已加载 %d 个定时任务", count)
|
||||
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventSchedulerLog,
|
||||
Payload: map[string]interface{}{
|
||||
"title": "加载定时任务",
|
||||
"content": fmt.Sprintf("后台调度引擎成功解析并载入本地活跃定时计划任务: %d 个。", count),
|
||||
"level": constant.LogLevelInfo,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Reload 重新加载配置并重建调度器
|
||||
@@ -588,6 +615,15 @@ func (es *ExecutorService) Reload() {
|
||||
if es.cronManager != nil {
|
||||
es.cronManager.SetScheduler(es.scheduler)
|
||||
}
|
||||
|
||||
eventbus.DefaultBus.Publish(eventbus.Event{
|
||||
Type: constant.EventSchedulerLog,
|
||||
Payload: map[string]interface{}{
|
||||
"title": "调度器重载",
|
||||
"content": "主服务任务调度引擎配置及执行队列实例已全量重载完毕。",
|
||||
"level": constant.LogLevelInfo,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// CreateExecutionRequest 统一处理任务到执行请求的转换逻辑(包含指令拼装、脱敏等)
|
||||
|
||||
Reference in New Issue
Block a user