mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-01-16 20:14:14 +08:00
parent
b0fbb39cd3
commit
606d3c1717
24 changed files with 336 additions and 74 deletions
|
|
@ -20,9 +20,10 @@ type MonitorSetting struct {
|
|||
MonitorStoreDays string `json:"monitorStoreDays"`
|
||||
MonitorInterval string `json:"monitorInterval"`
|
||||
DefaultNetwork string `json:"defaultNetwork"`
|
||||
DefaultIO string `json:"defaultIO"`
|
||||
}
|
||||
|
||||
type MonitorSettingUpdate struct {
|
||||
Key string `json:"key" validate:"required,oneof=MonitorStatus MonitorStoreDays MonitorInterval DefaultNetwork"`
|
||||
Key string `json:"key" validate:"required,oneof=MonitorStatus MonitorStoreDays MonitorInterval DefaultNetwork DefaultIO"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ type SettingInfo struct {
|
|||
NtpSite string `json:"ntpSite"`
|
||||
|
||||
DefaultNetwork string `json:"defaultNetwork"`
|
||||
DefaultIO string `json:"defaultIO"`
|
||||
LastCleanTime string `json:"lastCleanTime"`
|
||||
LastCleanSize string `json:"lastCleanSize"`
|
||||
LastCleanData string `json:"lastCleanData"`
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func (m *MonitorService) LoadMonitorData(req dto.MonitorSearch) ([]dto.MonitorDa
|
|||
data = append(data, itemData)
|
||||
}
|
||||
if req.Param == "all" || req.Param == "io" {
|
||||
bases, err := monitorRepo.GetIO(repo.WithByCreatedAt(req.StartTime, req.EndTime))
|
||||
bases, err := monitorRepo.GetIO(repo.WithByName(req.Info), repo.WithByCreatedAt(req.StartTime, req.EndTime))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -201,9 +201,18 @@ func (m *MonitorService) Run() {
|
|||
func (m *MonitorService) loadDiskIO() {
|
||||
ioStat, _ := disk.IOCounters()
|
||||
var diskIOList []disk.IOCountersStat
|
||||
var ioStatAll disk.IOCountersStat
|
||||
for _, io := range ioStat {
|
||||
ioStatAll.Name = "all"
|
||||
ioStatAll.ReadBytes += io.ReadBytes
|
||||
ioStatAll.WriteBytes += io.WriteBytes
|
||||
ioStatAll.ReadTime += io.ReadTime
|
||||
ioStatAll.WriteTime += io.WriteTime
|
||||
ioStatAll.WriteCount += io.WriteCount
|
||||
ioStatAll.ReadCount += io.ReadCount
|
||||
diskIOList = append(diskIOList, io)
|
||||
}
|
||||
diskIOList = append(diskIOList, ioStatAll)
|
||||
m.DiskIO <- diskIOList
|
||||
}
|
||||
|
||||
|
|
@ -234,29 +243,29 @@ func (m *MonitorService) saveIODataToDB(ctx context.Context, interval float64) {
|
|||
var itemIO model.MonitorIO
|
||||
itemIO.Name = io1.Name
|
||||
if io2.ReadBytes != 0 && io1.ReadBytes != 0 && io2.ReadBytes > io1.ReadBytes {
|
||||
itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / interval / 60)
|
||||
itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / interval)
|
||||
}
|
||||
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
|
||||
itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / interval / 60)
|
||||
itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / interval)
|
||||
}
|
||||
|
||||
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
|
||||
itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / interval / 60)
|
||||
itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / interval)
|
||||
}
|
||||
writeCount := uint64(0)
|
||||
if io2.WriteCount != 0 && io1.WriteCount != 0 && io2.WriteCount > io1.WriteCount {
|
||||
writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / interval * 60)
|
||||
writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / interval)
|
||||
}
|
||||
if writeCount > itemIO.Count {
|
||||
itemIO.Count = writeCount
|
||||
}
|
||||
|
||||
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
|
||||
itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / interval / 60)
|
||||
itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / interval)
|
||||
}
|
||||
writeTime := uint64(0)
|
||||
if io2.WriteTime != 0 && io1.WriteTime != 0 && io2.WriteTime > io1.WriteTime {
|
||||
writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / interval / 60)
|
||||
writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / interval)
|
||||
}
|
||||
if writeTime > itemIO.Time {
|
||||
itemIO.Time = writeTime
|
||||
|
|
@ -294,10 +303,10 @@ func (m *MonitorService) saveNetDataToDB(ctx context.Context, interval float64)
|
|||
itemNet.Name = net1.Name
|
||||
|
||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / interval / 60
|
||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / interval
|
||||
}
|
||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / interval / 60
|
||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / interval
|
||||
}
|
||||
netList = append(netList, itemNet)
|
||||
break
|
||||
|
|
@ -330,7 +339,7 @@ func StartMonitor(removeBefore bool, interval string) error {
|
|||
now := time.Now()
|
||||
nextMinute := now.Truncate(time.Minute).Add(time.Minute)
|
||||
time.AfterFunc(time.Until(nextMinute), func() {
|
||||
monitorID, err := global.Cron.AddJob(fmt.Sprintf("@every %sm", interval), service)
|
||||
monitorID, err := global.Cron.AddJob(fmt.Sprintf("@every %ss", interval), service)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ func InitAgentDB() {
|
|||
migrations.UpdateCronjobSpec,
|
||||
migrations.UpdateWebsiteSSLAddColumn,
|
||||
migrations.AddTensorRTLLMModel,
|
||||
migrations.UpdateMonitorInterval,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
|
@ -634,3 +635,27 @@ var AddTensorRTLLMModel = &gormigrate.Migration{
|
|||
return tx.AutoMigrate(&model.TensorRTLLM{})
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateMonitorInterval = &gormigrate.Migration{
|
||||
ID: "20251026-update-monitor-interval",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
var monitorInterval model.Setting
|
||||
if err := tx.Where("key = ?", "MonitorInterval").First(&monitorInterval).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
interval, _ := strconv.Atoi(monitorInterval.Value)
|
||||
if interval == 0 {
|
||||
interval = 300
|
||||
}
|
||||
if err := tx.Model(&model.Setting{}).
|
||||
Where("key = ?", "MonitorInterval").
|
||||
Updates(map[string]interface{}{"value": fmt.Sprintf("%v", interval*60)}).
|
||||
Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "DefaultIO", Value: "all"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ export namespace Host {
|
|||
|
||||
export interface MonitorSetting {
|
||||
defaultNetwork: string;
|
||||
defaultIO: string;
|
||||
monitorStatus: string;
|
||||
monitorStoreDays: string;
|
||||
monitorInterval: string;
|
||||
|
|
|
|||
|
|
@ -1168,11 +1168,13 @@ const message = {
|
|||
},
|
||||
monitor: {
|
||||
globalFilter: 'Global Filter',
|
||||
enableMonitor: 'Enable',
|
||||
storeDays: 'Expiration days',
|
||||
defaultNetwork: 'Default Network Adapter',
|
||||
defaultNetworkHelper: 'Network adapter option displayed in the default monitoring and overview interface',
|
||||
cleanMonitor: 'Clean monitoring records',
|
||||
enableMonitor: 'Monitoring Status',
|
||||
storeDays: 'Retention Days',
|
||||
defaultNetwork: 'Default Network Card',
|
||||
defaultNetworkHelper: 'Default network card option displayed in monitoring and overview interfaces',
|
||||
defaultIO: 'Default Disk',
|
||||
defaultIOHelper: 'Default disk option displayed in monitoring and overview interfaces',
|
||||
cleanMonitor: 'Clear Monitoring Records',
|
||||
|
||||
avgLoad: 'Load average',
|
||||
loadDetail: 'Load detail',
|
||||
|
|
@ -1193,7 +1195,8 @@ const message = {
|
|||
network: 'Network',
|
||||
up: 'Up',
|
||||
down: 'Down',
|
||||
interval: 'Interval(minute)',
|
||||
interval: 'Collection Interval',
|
||||
intervalHelper: 'Please enter an appropriate monitoring collection interval (5 seconds - 12 hours)',
|
||||
|
||||
gpuUtil: 'GPU Utilization',
|
||||
temperature: 'Temperature',
|
||||
|
|
|
|||
|
|
@ -1171,13 +1171,16 @@ const message = {
|
|||
},
|
||||
},
|
||||
monitor: {
|
||||
globalFilter: 'Filtro global',
|
||||
enableMonitor: 'Habilitar',
|
||||
storeDays: 'Días de retención',
|
||||
defaultNetwork: 'Adaptador de red predeterminado',
|
||||
globalFilter: 'Filtro Global',
|
||||
enableMonitor: 'Estado de Monitoreo',
|
||||
storeDays: 'Días de Retención',
|
||||
defaultNetwork: 'Tarjeta de Red Predeterminada',
|
||||
defaultNetworkHelper:
|
||||
'Opción de adaptador de red mostrada en la vista predeterminada de monitorización y resumen',
|
||||
cleanMonitor: 'Limpiar registros de monitorización',
|
||||
'Opción de tarjeta de red predeterminada mostrada en las interfaces de monitoreo y resumen',
|
||||
defaultIO: 'Disco Predeterminado',
|
||||
defaultIOHelper: 'Opción de disco predeterminada mostrada en las interfaces de monitoreo y resumen',
|
||||
cleanMonitor: 'Limpiar Registros de Monitoreo',
|
||||
|
||||
avgLoad: 'Carga promedio',
|
||||
loadDetail: 'Detalle de carga',
|
||||
resourceUsage: 'Utilización',
|
||||
|
|
@ -1197,7 +1200,8 @@ const message = {
|
|||
network: 'Red',
|
||||
up: 'Subida',
|
||||
down: 'Bajada',
|
||||
interval: 'Intervalo (minutos)',
|
||||
interval: 'Intervalo de Recolección',
|
||||
intervalHelper: 'Ingrese un intervalo de recolección de monitoreo apropiado (5 segundos - 12 horas)',
|
||||
gpuUtil: 'Uso de GPU',
|
||||
temperature: 'Temperatura',
|
||||
performanceState: 'Estado de rendimiento',
|
||||
|
|
|
|||
|
|
@ -1131,9 +1131,13 @@ const message = {
|
|||
},
|
||||
monitor: {
|
||||
globalFilter: 'グローバルフィルター',
|
||||
enableMonitor: '有効にする',
|
||||
storeDays: '有効期限',
|
||||
cleanMonitor: '監視記録をきれいにします',
|
||||
enableMonitor: '監視ステータス',
|
||||
storeDays: '保存日数',
|
||||
defaultNetwork: 'デフォルトネットワークカード',
|
||||
defaultNetworkHelper: '監視および概要インターフェースに表示されるデフォルトのネットワークカードオプション',
|
||||
defaultIO: 'デフォルトディスク',
|
||||
defaultIOHelper: '監視および概要インターフェースに表示されるデフォルトのディスクオプション',
|
||||
cleanMonitor: '監視記録をクリア',
|
||||
|
||||
avgLoad: 'ロード平均',
|
||||
loadDetail: '詳細を読み込みます',
|
||||
|
|
@ -1152,7 +1156,8 @@ const message = {
|
|||
network: 'ネットワーク',
|
||||
up: '上',
|
||||
down: '下',
|
||||
interval: '間隔(分)',
|
||||
interval: '収集間隔',
|
||||
intervalHelper: '適切な監視収集間隔を入力してください(5秒 - 12時間)',
|
||||
|
||||
gpuUtil: 'GPU利用',
|
||||
temperature: '温度',
|
||||
|
|
|
|||
|
|
@ -1123,9 +1123,13 @@ const message = {
|
|||
},
|
||||
monitor: {
|
||||
globalFilter: '전역 필터',
|
||||
enableMonitor: '활성화',
|
||||
storeDays: '만료일',
|
||||
cleanMonitor: '모니터링 기록 정리',
|
||||
enableMonitor: '모니터링 상태',
|
||||
storeDays: '보관 일수',
|
||||
defaultNetwork: '기본 네트워크 카드',
|
||||
defaultNetworkHelper: '모니터링 및 개요 인터페이스에 표시되는 기본 네트워크 카드 옵션',
|
||||
defaultIO: '기본 디스크',
|
||||
defaultIOHelper: '모니터링 및 개요 인터페이스에 표시되는 기본 디스크 옵션',
|
||||
cleanMonitor: '모니터링 기록 지우기',
|
||||
|
||||
avgLoad: '평균 부하',
|
||||
loadDetail: '부하 세부사항',
|
||||
|
|
@ -1144,7 +1148,8 @@ const message = {
|
|||
network: '네트워크',
|
||||
up: '업',
|
||||
down: '다운',
|
||||
interval: '간격(분)',
|
||||
interval: '수집 간격',
|
||||
intervalHelper: '적절한 모니터링 수집 간격을 입력하세요 (5초 - 12시간)',
|
||||
|
||||
gpuUtil: 'GPU 사용률',
|
||||
temperature: '온도',
|
||||
|
|
|
|||
|
|
@ -1163,9 +1163,14 @@ const message = {
|
|||
},
|
||||
monitor: {
|
||||
globalFilter: 'Penapis Global',
|
||||
enableMonitor: 'Aktifkan',
|
||||
storeDays: 'Hari luput',
|
||||
cleanMonitor: 'Bersihkan rekod pemantauan',
|
||||
enableMonitor: 'Status Pemantauan',
|
||||
storeDays: 'Hari Penyimpanan',
|
||||
defaultNetwork: 'Kad Rangkaian Lalai',
|
||||
defaultNetworkHelper:
|
||||
'Pilihan kad rangkaian lalai yang dipaparkan dalam antara muka pemantauan dan gambaran keseluruhan',
|
||||
defaultIO: 'Cakera Lalai',
|
||||
defaultIOHelper: 'Pilihan cakera lalai yang dipaparkan dalam antara muka pemantauan dan gambaran keseluruhan',
|
||||
cleanMonitor: 'Kosongkan Rekod Pemantauan',
|
||||
|
||||
avgLoad: 'Purata beban',
|
||||
loadDetail: 'Butiran beban',
|
||||
|
|
@ -1184,7 +1189,8 @@ const message = {
|
|||
network: 'Rangkaian',
|
||||
up: 'Naik',
|
||||
down: 'Turun',
|
||||
interval: 'Selang (minit)',
|
||||
interval: 'Selang Kumpulan',
|
||||
intervalHelper: 'Sila masukkan selang kumpulan pemantauan yang sesuai (5 saat - 12 jam)',
|
||||
|
||||
gpuUtil: 'Penggunaan GPU',
|
||||
temperature: 'Suhu',
|
||||
|
|
|
|||
|
|
@ -1156,10 +1156,14 @@ const message = {
|
|||
},
|
||||
},
|
||||
monitor: {
|
||||
globalFilter: 'Filtro global',
|
||||
enableMonitor: 'Ativar',
|
||||
storeDays: 'Dias de expiração',
|
||||
cleanMonitor: 'Limpar registros de monitoramento',
|
||||
globalFilter: 'Filtro Global',
|
||||
enableMonitor: 'Status de Monitoramento',
|
||||
storeDays: 'Dias de Retenção',
|
||||
defaultNetwork: 'Placa de Rede Padrão',
|
||||
defaultNetworkHelper: 'Opção de placa de rede padrão exibida nas interfaces de monitoramento e visão geral',
|
||||
defaultIO: 'Disco Padrão',
|
||||
defaultIOHelper: 'Opção de disco padrão exibida nas interfaces de monitoramento e visão geral',
|
||||
cleanMonitor: 'Limpar Registros de Monitoramento',
|
||||
|
||||
avgLoad: 'Média de carga',
|
||||
loadDetail: 'Detalhes da carga',
|
||||
|
|
@ -1178,7 +1182,8 @@ const message = {
|
|||
network: 'Rede',
|
||||
up: 'Para cima',
|
||||
down: 'Para baixo',
|
||||
interval: 'Intervalo (minuto)',
|
||||
interval: 'Intervalo de Coleta',
|
||||
intervalHelper: 'Insira um intervalo de coleta de monitoramento apropriado (5 segundos - 12 horas)',
|
||||
|
||||
gpuUtil: 'Utilização da GPU',
|
||||
temperature: 'Temperatura',
|
||||
|
|
|
|||
|
|
@ -1160,10 +1160,14 @@ const message = {
|
|||
},
|
||||
},
|
||||
monitor: {
|
||||
globalFilter: 'Глобальный фильтр',
|
||||
enableMonitor: 'Включить',
|
||||
storeDays: 'Дни хранения',
|
||||
cleanMonitor: 'Очистить записи мониторинга',
|
||||
globalFilter: 'Глобальный Фильтр',
|
||||
enableMonitor: 'Статус Мониторинга',
|
||||
storeDays: 'Дни Хранения',
|
||||
defaultNetwork: 'Сетевая Карта по Умолчанию',
|
||||
defaultNetworkHelper: 'Опция сетевой карты по умолчанию, отображаемая в интерфейсах мониторинга и обзора',
|
||||
defaultIO: 'Диск по Умолчанию',
|
||||
defaultIOHelper: 'Опция диска по умолчанию, отображаемая в интерфейсах мониторинга и обзора',
|
||||
cleanMonitor: 'Очистить Записи Мониторинга',
|
||||
|
||||
avgLoad: 'Средняя нагрузка',
|
||||
loadDetail: 'Детали нагрузки',
|
||||
|
|
@ -1182,7 +1186,8 @@ const message = {
|
|||
network: 'Сеть',
|
||||
up: 'Исходящий',
|
||||
down: 'Входящий',
|
||||
interval: 'Интервал(минут)',
|
||||
interval: 'Интервал Сбора',
|
||||
intervalHelper: 'Пожалуйста, введите подходящий интервал сбора мониторинга (5 секунд - 12 часов)',
|
||||
|
||||
gpuUtil: 'Использование GPU',
|
||||
temperature: 'Температура',
|
||||
|
|
|
|||
|
|
@ -1182,11 +1182,13 @@ const message = {
|
|||
},
|
||||
monitor: {
|
||||
globalFilter: 'Genel Filtre',
|
||||
enableMonitor: 'Etkinleştir',
|
||||
storeDays: 'Son kullanma günleri',
|
||||
defaultNetwork: 'Varsayılan Ağ Adaptörü',
|
||||
defaultNetworkHelper: 'Varsayılan izleme ve genel bakış arayüzünde görüntülenen ağ adaptörü seçeneği',
|
||||
cleanMonitor: 'İzleme kayıtlarını temizle',
|
||||
enableMonitor: 'İzleme Durumu',
|
||||
storeDays: 'Saklama Günleri',
|
||||
defaultNetwork: 'Varsayılan Ağ Kartı',
|
||||
defaultNetworkHelper: 'İzleme ve genel bakış arayüzlerinde görüntülenen varsayılan ağ kartı seçeneği',
|
||||
defaultIO: 'Varsayılan Disk',
|
||||
defaultIOHelper: 'İzleme ve genel bakış arayüzlerinde görüntülenen varsayılan disk seçeneği',
|
||||
cleanMonitor: 'İzleme Kayıtlarını Temizle',
|
||||
|
||||
avgLoad: 'Ortalama yük',
|
||||
loadDetail: 'Yük detayı',
|
||||
|
|
@ -1207,7 +1209,8 @@ const message = {
|
|||
network: 'Ağ',
|
||||
up: 'Yukarı',
|
||||
down: 'Aşağı',
|
||||
interval: 'Aralık(dakika)',
|
||||
interval: 'Toplama Aralığı',
|
||||
intervalHelper: 'Lütfen uygun bir izleme toplama aralığı girin (5 saniye - 12 saat)',
|
||||
|
||||
gpuUtil: 'GPU Kullanımı',
|
||||
temperature: 'Sıcaklık',
|
||||
|
|
|
|||
|
|
@ -1107,9 +1107,11 @@ const message = {
|
|||
monitor: {
|
||||
globalFilter: '全域過濾',
|
||||
enableMonitor: '監控狀態',
|
||||
storeDays: '儲存天數',
|
||||
storeDays: '保存天數',
|
||||
defaultNetwork: '預設網卡',
|
||||
defaultNetworkHelper: '預設監控和概覽介面顯示的網卡選項',
|
||||
defaultIO: '預設磁碟',
|
||||
defaultIOHelper: '預設監控和概覽介面顯示的磁碟選項',
|
||||
cleanMonitor: '清空監控記錄',
|
||||
|
||||
avgLoad: '平均負載',
|
||||
|
|
@ -1131,7 +1133,8 @@ const message = {
|
|||
network: '網路',
|
||||
up: '上行',
|
||||
down: '下行',
|
||||
interval: '採集間隔(分鐘)',
|
||||
interval: '採集間隔',
|
||||
intervalHelper: '請輸入合適的監控採集時間間隔(5秒 - 12小時)',
|
||||
|
||||
gpuUtil: 'GPU 使用率',
|
||||
temperature: '溫度',
|
||||
|
|
|
|||
|
|
@ -1111,6 +1111,8 @@ const message = {
|
|||
storeDays: '保存天数',
|
||||
defaultNetwork: '默认网卡',
|
||||
defaultNetworkHelper: '默认监控和概览界面显示的网卡选项',
|
||||
defaultIO: '默认磁盘',
|
||||
defaultIOHelper: '默认监控和概览界面显示的磁盘选项',
|
||||
cleanMonitor: '清空监控记录',
|
||||
|
||||
avgLoad: '平均负载',
|
||||
|
|
@ -1132,7 +1134,8 @@ const message = {
|
|||
network: '网络',
|
||||
up: '上行',
|
||||
down: '下行',
|
||||
interval: '采集间隔(分钟)',
|
||||
interval: '采集间隔',
|
||||
intervalHelper: '请输入合适的监控采集时间间隔(5秒 - 12小时)',
|
||||
|
||||
gpuUtil: 'GPU 使用率',
|
||||
temperature: '温度',
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export interface GlobalState {
|
|||
currentRedisDB: string;
|
||||
showEntranceWarn: boolean;
|
||||
defaultNetwork: string;
|
||||
defaultIO: string;
|
||||
isFxplay: boolean;
|
||||
|
||||
isProductPro: boolean;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ const GlobalStore = defineStore({
|
|||
currentRedisDB: '',
|
||||
showEntranceWarn: true,
|
||||
defaultNetwork: 'all',
|
||||
defaultIO: 'all',
|
||||
isFxplay: false,
|
||||
|
||||
isProductPro: false,
|
||||
|
|
@ -117,6 +118,9 @@ const GlobalStore = defineStore({
|
|||
setDefaultNetwork(net: string) {
|
||||
this.defaultNetwork = net;
|
||||
},
|
||||
setDefaultIO(net: string) {
|
||||
this.defaultIO = net;
|
||||
},
|
||||
},
|
||||
persist: piniaPersistConfig('GlobalState'),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -165,7 +165,9 @@ export function dateFormatWithoutYear(dataStr: any) {
|
|||
h = h < 10 ? `0${String(h)}` : h;
|
||||
let minute: string | number = date.getMinutes();
|
||||
minute = minute < 10 ? `0${String(minute)}` : minute;
|
||||
return `${String(m)}-${String(d)}\n${String(h)}:${String(minute)}`;
|
||||
let s: string | number = date.getSeconds();
|
||||
s = s < 10 ? `0${String(s)}` : s;
|
||||
return `${String(m)}-${String(d)}\n${String(h)}:${String(minute)}:${String(s)}`;
|
||||
}
|
||||
|
||||
// 20221013151302
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ const onLoadSimpleNode = async () => {
|
|||
const onLoadIOOptions = async () => {
|
||||
const res = await getIOOptions();
|
||||
ioOptions.value = res.data;
|
||||
searchInfo.ioOption = ioOptions.value && ioOptions.value[0];
|
||||
searchInfo.ioOption = globalStore.defaultIO || (ioOptions.value && ioOptions.value[0]);
|
||||
};
|
||||
|
||||
const onLoadBaseInfo = async (isInit: boolean, range: string) => {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
style="max-width: 360px; width: 100%"
|
||||
:size="mobile ? 'small' : 'default'"
|
||||
></el-date-picker>
|
||||
<TableRefresh class="float-right" @search="searchGlobal()" />
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
|
@ -118,7 +119,26 @@
|
|||
<el-card style="overflow: inherit">
|
||||
<template #header>
|
||||
<div :class="mobile ? 'flx-wrap' : 'flex justify-between'">
|
||||
<span class="title">{{ $t('monitor.disk') }} I/O</span>
|
||||
<div>
|
||||
<span class="title">{{ $t('monitor.disk') }} I/O{{ $t('commons.colon') }}</span>
|
||||
<el-dropdown max-height="300px">
|
||||
<span class="networkOption">
|
||||
{{ ioChoose === 'all' ? $t('commons.table.all') : ioChoose }}
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<div v-for="item in ioOptions" :key="item">
|
||||
<el-dropdown-item v-if="item === 'all'" @click="changeIO('all')">
|
||||
{{ $t('commons.table.all') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-else @click="changeIO(item)">
|
||||
{{ item }}
|
||||
</el-dropdown-item>
|
||||
</div>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<el-date-picker
|
||||
@change="search('io')"
|
||||
v-model="timeRangeIO"
|
||||
|
|
@ -199,7 +219,7 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { loadMonitor, getNetworkOptions } from '@/api/modules/host';
|
||||
import { loadMonitor, getNetworkOptions, getIOOptions } from '@/api/modules/host';
|
||||
import { computeSizeFromKBs, dateFormatWithoutYear } from '@/utils/util';
|
||||
import i18n from '@/lang';
|
||||
import MonitorRouter from '@/views/host/monitor/index.vue';
|
||||
|
|
@ -223,6 +243,8 @@ const timeRangeIO = ref<[Date, Date]>([new Date(new Date().setHours(0, 0, 0, 0))
|
|||
const timeRangeNetwork = ref<[Date, Date]>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
|
||||
const networkChoose = ref();
|
||||
const netOptions = ref();
|
||||
const ioChoose = ref();
|
||||
const ioOptions = ref();
|
||||
const chartsOption = ref({ loadLoadChart: null, loadCPUChart: null, loadMemoryChart: null, loadNetworkChart: null });
|
||||
|
||||
const searchTime = ref();
|
||||
|
|
@ -260,6 +282,7 @@ const search = async (param: string) => {
|
|||
break;
|
||||
case 'io':
|
||||
searchTime.value = timeRangeIO.value;
|
||||
searchInfo.info = ioChoose.value;
|
||||
break;
|
||||
case 'network':
|
||||
searchTime.value = timeRangeNetwork.value;
|
||||
|
|
@ -366,6 +389,11 @@ const changeNetwork = (item: string) => {
|
|||
search('network');
|
||||
};
|
||||
|
||||
const changeIO = (item: string) => {
|
||||
ioChoose.value = item;
|
||||
search('io');
|
||||
};
|
||||
|
||||
const loadNetworkOptions = async () => {
|
||||
const res = await getNetworkOptions();
|
||||
netOptions.value = res.data;
|
||||
|
|
@ -374,6 +402,14 @@ const loadNetworkOptions = async () => {
|
|||
search('all');
|
||||
};
|
||||
|
||||
const loadIOOptions = async () => {
|
||||
const res = await getIOOptions();
|
||||
ioOptions.value = res.data;
|
||||
searchInfo.info = globalStore.defaultIO || (ioOptions.value && ioOptions.value[0]);
|
||||
ioChoose.value = searchInfo.info;
|
||||
search('all');
|
||||
};
|
||||
|
||||
function initLoadCharts(item: Host.MonitorData) {
|
||||
let itemLoadDate = item.date.length === 0 ? loadEmptyDate(timeRangeLoad.value) : item.date;
|
||||
let loadDate = itemLoadDate.map(function (item: any) {
|
||||
|
|
@ -565,6 +601,7 @@ function getSideWidth(b: boolean) {
|
|||
onMounted(() => {
|
||||
zoomStart.value = dateFormatWithoutYear(new Date(new Date().setHours(0, 0, 0, 0)));
|
||||
loadNetworkOptions();
|
||||
loadIOOptions();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
87
frontend/src/views/host/monitor/setting/default-io/index.vue
Normal file
87
frontend/src/views/host/monitor/setting/default-io/index.vue
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<template>
|
||||
<DrawerPro v-model="drawerVisible" :header="$t('monitor.defaultIO')" @close="handleClose" size="small">
|
||||
<el-form ref="formRef" label-position="top" :model="form" @submit.prevent v-loading="loading">
|
||||
<el-form-item :label="$t('monitor.defaultIO')" prop="defaultIO" :rules="Rules.requiredSelect">
|
||||
<el-select v-model="form.defaultIO" filterable>
|
||||
<el-option
|
||||
v-for="item in ioOptions"
|
||||
:key="item"
|
||||
:label="item == 'all' ? $t('commons.table.all') : item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { getIOOptions, updateMonitorSetting } from '@/api/modules/host';
|
||||
import { GlobalStore } from '@/store';
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
|
||||
interface DialogProps {
|
||||
defaultIO: string;
|
||||
}
|
||||
const drawerVisible = ref();
|
||||
const loading = ref();
|
||||
const ioOptions = ref();
|
||||
|
||||
const form = reactive({
|
||||
defaultIO: '',
|
||||
});
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
form.defaultIO = params.defaultIO;
|
||||
loadIOOptions();
|
||||
drawerVisible.value = true;
|
||||
};
|
||||
|
||||
const loadIOOptions = async () => {
|
||||
const res = await getIOOptions();
|
||||
ioOptions.value = res.data;
|
||||
};
|
||||
|
||||
const onSave = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
await updateMonitorSetting('DefaultIO', form.defaultIO)
|
||||
.then(async () => {
|
||||
globalStore.setDefaultIO(form.defaultIO);
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
loading.value = false;
|
||||
drawerVisible.value = false;
|
||||
emit('search');
|
||||
return;
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
drawerVisible.value = false;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
||||
|
|
@ -25,8 +25,8 @@
|
|||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('monitor.interval')" prop="monitorInterval">
|
||||
<el-input disabled v-model="form.monitorInterval">
|
||||
<el-form-item :label="$t('monitor.interval')" prop="monitorIntervalItem">
|
||||
<el-input disabled v-model="form.monitorIntervalItem">
|
||||
<template #append>
|
||||
<el-button @click="onChangeInterval" icon="Setting">
|
||||
{{ $t('commons.button.set') }}
|
||||
|
|
@ -44,6 +44,16 @@
|
|||
</el-input>
|
||||
<span class="input-help">{{ $t('monitor.defaultNetworkHelper') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('monitor.defaultIO')">
|
||||
<el-input disabled v-model="form.defaultIO">
|
||||
<template #append>
|
||||
<el-button @click="onChangeIO" icon="Setting">
|
||||
{{ $t('commons.button.set') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<span class="input-help">{{ $t('monitor.defaultIOHelper') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="onClean()" icon="Delete">{{ $t('monitor.cleanMonitor') }}</el-button>
|
||||
</el-form-item>
|
||||
|
|
@ -56,6 +66,7 @@
|
|||
<Interval ref="intervalRef" @search="search" />
|
||||
<StoreDays ref="daysRef" @search="search" />
|
||||
<Network ref="networkRef" @search="search()" />
|
||||
<IO ref="ioRef" @search="search()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -67,29 +78,42 @@ import MonitorRouter from '@/views/host/monitor/index.vue';
|
|||
import Interval from '@/views/host/monitor/setting/interval/index.vue';
|
||||
import StoreDays from '@/views/host/monitor/setting/days/index.vue';
|
||||
import Network from '@/views/host/monitor/setting/default-network/index.vue';
|
||||
import IO from '@/views/host/monitor/setting/default-io/index.vue';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { splitTimeFromSecond, transTimeUnit } from '@/utils/util';
|
||||
|
||||
const loading = ref();
|
||||
const form = reactive({
|
||||
monitorStatus: 'Disable',
|
||||
monitorStoreDays: 30,
|
||||
monitorInterval: 1,
|
||||
monitorInterval: 300,
|
||||
timeItem: 5,
|
||||
timeUnit: 'm',
|
||||
monitorIntervalItem: '',
|
||||
defaultNetwork: '',
|
||||
defaultIO: '',
|
||||
});
|
||||
const panelFormRef = ref<FormInstance>();
|
||||
|
||||
const intervalRef = ref();
|
||||
const daysRef = ref();
|
||||
const networkRef = ref();
|
||||
const ioRef = ref();
|
||||
|
||||
const search = async () => {
|
||||
const res = await loadMonitorSetting();
|
||||
form.monitorStatus = res.data.monitorStatus;
|
||||
form.monitorInterval = Number(res.data.monitorInterval);
|
||||
let item = splitTimeFromSecond(form.monitorInterval);
|
||||
form.timeItem = item.timeItem;
|
||||
form.timeUnit = item.timeUnit;
|
||||
form.monitorIntervalItem = transTimeUnit(form.timeItem + form.timeUnit);
|
||||
|
||||
form.monitorStoreDays = Number(res.data.monitorStoreDays);
|
||||
form.defaultNetwork =
|
||||
res.data.defaultNetwork === 'all' ? i18n.global.t('commons.table.all') : res.data.defaultNetwork;
|
||||
form.defaultIO = res.data.defaultIO === 'all' ? i18n.global.t('commons.table.all') : res.data.defaultIO;
|
||||
};
|
||||
|
||||
const onSaveStatus = async () => {
|
||||
|
|
@ -108,11 +132,14 @@ const onChangeStoreDays = () => {
|
|||
daysRef.value.acceptParams({ monitorStoreDays: form.monitorStoreDays });
|
||||
};
|
||||
const onChangeInterval = () => {
|
||||
intervalRef.value.acceptParams({ monitorInterval: form.monitorInterval });
|
||||
intervalRef.value.acceptParams({ timeItem: form.timeItem, timeUnit: form.timeUnit });
|
||||
};
|
||||
const onChangeNetwork = () => {
|
||||
networkRef.value.acceptParams({ defaultNetwork: form.defaultNetwork });
|
||||
};
|
||||
const onChangeIO = () => {
|
||||
ioRef.value.acceptParams({ defaultIO: form.defaultIO });
|
||||
};
|
||||
|
||||
const onClean = async () => {
|
||||
ElMessageBox.confirm(i18n.global.t('commons.msg.clean'), i18n.global.t('monitor.cleanMonitor'), {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
<template>
|
||||
<DrawerPro v-model="drawerVisible" :header="$t('monitor.interval')" @close="handleClose" size="small">
|
||||
<el-form ref="formRef" label-position="top" :model="form" @submit.prevent v-loading="loading">
|
||||
<el-form-item
|
||||
:label="$t('monitor.interval')"
|
||||
:rules="[Rules.integerNumber, checkNumberRange(1, 60)]"
|
||||
prop="monitorInterval"
|
||||
>
|
||||
<el-input clearable v-model.number="form.monitorInterval" />
|
||||
<el-form ref="formRef" label-position="top" :model="form" :rules="rules" @submit.prevent v-loading="loading">
|
||||
<el-form-item :label="$t('monitor.interval')" prop="monitorInterval">
|
||||
<el-input type="number" @input="loadInterval()" class="selectClass" v-model.number="form.timeItem">
|
||||
<template #append>
|
||||
<el-select v-model="form.timeUnit" @change="loadInterval" style="width: 80px">
|
||||
<el-option :label="$t('commons.units.second')" value="s" />
|
||||
<el-option :label="$t('commons.units.minute')" value="m" />
|
||||
<el-option :label="$t('commons.units.hour')" value="h" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
|
|
@ -24,28 +28,48 @@ import { reactive, ref } from 'vue';
|
|||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { Rules, checkNumberRange } from '@/global/form-rules';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { updateMonitorSetting } from '@/api/modules/host';
|
||||
import { transferTimeToSecond } from '@/utils/util';
|
||||
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
|
||||
interface DialogProps {
|
||||
monitorInterval: number;
|
||||
timeItem: number;
|
||||
timeUnit: string;
|
||||
}
|
||||
const drawerVisible = ref();
|
||||
const loading = ref();
|
||||
|
||||
const form = reactive({
|
||||
monitorInterval: 1,
|
||||
timeItem: 5,
|
||||
timeUnit: 'h',
|
||||
monitorInterval: 300,
|
||||
});
|
||||
|
||||
const verifyInterval = (rule: any, value: any, callback: any) => {
|
||||
if (value < 10 || value > 43200) {
|
||||
callback(new Error(i18n.global.t('monitor.intervalHelper')));
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
};
|
||||
const rules = reactive({
|
||||
monitorInterval: [Rules.integerNumber, { validator: verifyInterval, trigger: 'blur', required: true }],
|
||||
});
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
form.monitorInterval = params.monitorInterval;
|
||||
form.timeItem = params.timeItem;
|
||||
form.timeUnit = params.timeUnit;
|
||||
drawerVisible.value = true;
|
||||
};
|
||||
|
||||
const loadInterval = () => {
|
||||
form.monitorInterval = transferTimeToSecond(form.timeItem + form.timeUnit);
|
||||
};
|
||||
|
||||
const onSave = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue