feat: 监控采集间隔支持设置

This commit is contained in:
耗子
2026-02-27 00:11:07 +08:00
parent 4ff7ce18cd
commit d8515f9883
8 changed files with 47 additions and 11 deletions
+1
View File
@@ -15,6 +15,7 @@ const (
SettingKeyChannel SettingKey = "channel"
SettingKeyMonitor SettingKey = "monitor"
SettingKeyMonitorDays SettingKey = "monitor_days"
SettingKeyMonitorInterval SettingKey = "monitor_interval"
SettingKeyBackupPath SettingKey = "backup_path"
SettingKeyWebsitePath SettingKey = "website_path"
SettingKeyProjectPath SettingKey = "project_path"
+8
View File
@@ -31,10 +31,15 @@ func (r monitorRepo) GetSetting() (*request.MonitorSetting, error) {
if err != nil {
return nil, err
}
monitorInterval, err := r.setting.GetInt(biz.SettingKeyMonitorInterval, 1)
if err != nil {
return nil, err
}
setting := new(request.MonitorSetting)
setting.Enabled = cast.ToBool(monitor)
setting.Days = cast.ToUint(monitorDays)
setting.Interval = uint(monitorInterval)
return setting, nil
}
@@ -46,6 +51,9 @@ func (r monitorRepo) UpdateSetting(setting *request.MonitorSetting) error {
if err := r.setting.Set(biz.SettingKeyMonitorDays, cast.ToString(setting.Days)); err != nil {
return err
}
if err := r.setting.Set(biz.SettingKeyMonitorInterval, cast.ToString(setting.Interval)); err != nil {
return err
}
return nil
}
+3 -2
View File
@@ -1,8 +1,9 @@
package request
type MonitorSetting struct {
Enabled bool `json:"enabled"`
Days uint `json:"days"`
Enabled bool `json:"enabled"`
Days uint `json:"days"`
Interval uint `json:"interval" validate:"required|min:1|max:120"` // 采集间隔(分钟),最小 1
}
type MonitorList struct {
+11
View File
@@ -17,6 +17,7 @@ type Monitoring struct {
db *gorm.DB
log *slog.Logger
settingRepo biz.SettingRepo
lastRun time.Time
}
func NewMonitoring(db *gorm.DB, log *slog.Logger, setting biz.SettingRepo) *Monitoring {
@@ -37,6 +38,16 @@ func (r *Monitoring) Run() {
return
}
// 根据采集间隔判断是否该采集
interval, _ := r.settingRepo.GetInt(biz.SettingKeyMonitorInterval, 1)
if interval < 1 {
interval = 1
}
if !r.lastRun.IsZero() && time.Since(r.lastRun) < time.Duration(interval)*time.Minute-30*time.Second {
return
}
r.lastRun = time.Now()
info := tools.CurrentInfo(nil, nil)
info.TopProcesses = tools.CollectTopProcesses()
+1
View File
@@ -1039,6 +1039,7 @@ func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error {
{Key: biz.SettingKeyVersion, Value: app.Version},
{Key: biz.SettingKeyMonitor, Value: "true"},
{Key: biz.SettingKeyMonitorDays, Value: "30"},
{Key: biz.SettingKeyMonitorInterval, Value: "1"},
{Key: biz.SettingKeyBackupPath, Value: filepath.Join(app.Root, "backup")},
{Key: biz.SettingKeyWebsitePath, Value: filepath.Join(app.Root, "sites")},
{Key: biz.SettingKeyProjectPath, Value: filepath.Join(app.Root, "projects")},
+11 -5
View File
@@ -118,6 +118,12 @@ func (s *MonitorService) List(w http.ResponseWriter, r *http.Request) {
continue
}
// 计算与上一条记录的时间差(秒),用于速率计算
elapsed := monitor.CreatedAt.Sub(monitors[i-1].CreatedAt).Seconds()
if elapsed < 1 {
elapsed = 1
}
// 处理网络数据
for _, net := range monitor.Info.Net {
if net.Name == "lo" {
@@ -136,8 +142,8 @@ func (s *MonitorService) List(w http.ResponseWriter, r *http.Request) {
device := netDeviceData[net.Name]
device.Sent = append(device.Sent, fmt.Sprintf("%.2f", float64(net.BytesSent)/1024/1024))
device.Recv = append(device.Recv, fmt.Sprintf("%.2f", float64(net.BytesRecv)/1024/1024))
device.Tx = append(device.Tx, fmt.Sprintf("%.2f", float64(net.BytesSent-prev.sent)/60/1024/1024))
device.Rx = append(device.Rx, fmt.Sprintf("%.2f", float64(net.BytesRecv-prev.recv)/60/1024/1024))
device.Tx = append(device.Tx, fmt.Sprintf("%.2f", float64(net.BytesSent-prev.sent)/elapsed/1024/1024))
device.Rx = append(device.Rx, fmt.Sprintf("%.2f", float64(net.BytesRecv-prev.recv)/elapsed/1024/1024))
netDevicePrev[net.Name] = struct {
sent uint64
recv uint64
@@ -157,9 +163,9 @@ func (s *MonitorService) List(w http.ResponseWriter, r *http.Request) {
diskData := diskIOData[disk.Name]
diskData.ReadBytes = append(diskData.ReadBytes, fmt.Sprintf("%.2f", float64(disk.ReadBytes)/1024/1024))
diskData.WriteBytes = append(diskData.WriteBytes, fmt.Sprintf("%.2f", float64(disk.WriteBytes)/1024/1024))
// 监控频率为 1 分钟,所以这里除以 60 即可得到每秒速度 (KB/s)
diskData.ReadSpeed = append(diskData.ReadSpeed, fmt.Sprintf("%.2f", float64(disk.ReadBytes-prev.read)/60/1024))
diskData.WriteSpeed = append(diskData.WriteSpeed, fmt.Sprintf("%.2f", float64(disk.WriteBytes-prev.write)/60/1024))
// 根据实际时间差计算每秒速度 (KB/s)
diskData.ReadSpeed = append(diskData.ReadSpeed, fmt.Sprintf("%.2f", float64(disk.ReadBytes-prev.read)/elapsed/1024))
diskData.WriteSpeed = append(diskData.WriteSpeed, fmt.Sprintf("%.2f", float64(disk.WriteBytes-prev.write)/elapsed/1024))
diskIOPrev[disk.Name] = struct {
read uint64
write uint64
+3 -3
View File
@@ -3,9 +3,9 @@ import { http } from '@/utils'
export default {
// 开关
setting: (): any => http.Get('/monitor/setting'),
// 保存天数
updateSetting: (enabled: boolean, days: number): any =>
http.Post('/monitor/setting', { enabled, days }),
// 保存设置
updateSetting: (enabled: boolean, days: number, interval: number): any =>
http.Post('/monitor/setting', { enabled, days, interval }),
// 清空监控记录
clear: (): any => http.Post('/monitor/clear'),
// 监控记录
+9 -1
View File
@@ -34,11 +34,13 @@ use([
// 监控设置
const monitorSwitch = ref(false)
const saveDay = ref(30)
const monitorInterval = ref(1)
const updateLoading = ref(false)
useRequest(monitor.setting()).onSuccess(({ data }) => {
monitorSwitch.value = data.enabled
saveDay.value = data.days
monitorInterval.value = data.interval
})
// 时间预设选项
@@ -688,7 +690,7 @@ const diskIOOption = computed<EChartsOption>(() => {
// 操作函数
const handleUpdate = async () => {
updateLoading.value = true
useRequest(monitor.updateSetting(monitorSwitch.value, saveDay.value))
useRequest(monitor.updateSetting(monitorSwitch.value, saveDay.value, monitorInterval.value))
.onSuccess(() => {
window.$message.success($gettext('Operation successful'))
})
@@ -719,6 +721,12 @@ const handleClear = async () => {
<template #suffix> {{ $gettext('days') }} </template>
</n-input-number>
</div>
<div class="pl-20 flex gap-10 items-center">
{{ $gettext('Collection Interval') }}
<n-input-number v-model:value="monitorInterval" :min="1" :max="120">
<template #suffix> {{ $gettext('minutes') }} </template>
</n-input-number>
</div>
<div>
<n-button type="primary" :loading="updateLoading" :disabled="updateLoading" @click="handleUpdate">{{ $gettext('Confirm') }}</n-button>
</div>