mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-26 16:00:14 +00:00
* perf(monitor): improve monitor query and chart performance for large ranges - enable LTTB sampling in the shared line chart to bound rendered points - empty io/network in monitor search now means no name filter, returning all device rows in one query instead of fanning out per device - merge device names recorded in the monitor db into io/network/gpu options so removed devices stay selectable; move logic to service layer - add composite indexes (name, created_at) on monitor_ios/monitor_networks and (product_name, created_at) on monitor_gpus - stop migrating the unused MonitorGPU model into MonitorDB - fix the memory param which was compared against "mem" and never matched * chore(monitor): remove monitor test fixtures --------- Co-authored-by: ssongliu <sloooop1x@gmail.com>
195 lines
6.8 KiB
Go
195 lines
6.8 KiB
Go
package repo
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/1Panel-dev/1Panel/agent/app/model"
|
|
"github.com/1Panel-dev/1Panel/agent/global"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type MonitorRepo struct{}
|
|
|
|
type GPUHistoryPoint struct {
|
|
model.MonitorGPU
|
|
Bucket int64
|
|
PowerPercent *float64
|
|
MemoryPercent *float64
|
|
ProcessCount *float64
|
|
}
|
|
|
|
type IMonitorRepo interface {
|
|
CleanHost() error
|
|
CleanGPU() error
|
|
GetBase(opts ...DBOption) ([]model.MonitorBase, error)
|
|
CountGPU(opts ...DBOption) (int64, error)
|
|
GetGPUHistory(start time.Time, bucketSeconds int64, aggregation string, opts ...DBOption) ([]GPUHistoryPoint, error)
|
|
GetGPUDevices() ([]model.MonitorGPU, error)
|
|
GetIO(opts ...DBOption) ([]model.MonitorIO, error)
|
|
GetNetwork(opts ...DBOption) ([]model.MonitorNetwork, error)
|
|
GetIONames() ([]string, error)
|
|
GetNetworkNames() ([]string, error)
|
|
|
|
CreateMonitorBase(model model.MonitorBase) error
|
|
BatchCreateMonitorGPU(list []model.MonitorGPU) error
|
|
BatchCreateMonitorIO(ioList []model.MonitorIO) error
|
|
BatchCreateMonitorNet(ioList []model.MonitorNetwork) error
|
|
DelMonitorBase(timeForDelete time.Time) error
|
|
DelMonitorGPU(timeForDelete time.Time) error
|
|
DelMonitorIO(timeForDelete time.Time) error
|
|
DelMonitorNet(timeForDelete time.Time) error
|
|
|
|
WithByGPUDevice(deviceID, name string, legacy bool) DBOption
|
|
}
|
|
|
|
func NewIMonitorRepo() IMonitorRepo {
|
|
return &MonitorRepo{}
|
|
}
|
|
|
|
func (s *MonitorRepo) CleanHost() error {
|
|
for _, item := range []interface{}{&model.MonitorBase{}, &model.MonitorIO{}, &model.MonitorNetwork{}} {
|
|
if err := global.MonitorDB.Where("1 = 1").Delete(item).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *MonitorRepo) CleanGPU() error {
|
|
return global.GPUMonitorDB.Where("1 = 1").Delete(&model.MonitorGPU{}).Error
|
|
}
|
|
|
|
func (u *MonitorRepo) GetBase(opts ...DBOption) ([]model.MonitorBase, error) {
|
|
var data []model.MonitorBase
|
|
db := global.MonitorDB
|
|
for _, opt := range opts {
|
|
db = opt(db)
|
|
}
|
|
err := db.Find(&data).Error
|
|
return data, err
|
|
}
|
|
func (u *MonitorRepo) GetIO(opts ...DBOption) ([]model.MonitorIO, error) {
|
|
var data []model.MonitorIO
|
|
db := global.MonitorDB
|
|
for _, opt := range opts {
|
|
db = opt(db)
|
|
}
|
|
err := db.Find(&data).Error
|
|
return data, err
|
|
}
|
|
func (u *MonitorRepo) GetNetwork(opts ...DBOption) ([]model.MonitorNetwork, error) {
|
|
var data []model.MonitorNetwork
|
|
db := global.MonitorDB
|
|
for _, opt := range opts {
|
|
db = opt(db)
|
|
}
|
|
err := db.Find(&data).Error
|
|
return data, err
|
|
}
|
|
func (u *MonitorRepo) GetIONames() ([]string, error) {
|
|
var names []string
|
|
err := global.MonitorDB.Model(&model.MonitorIO{}).Distinct().Pluck("name", &names).Error
|
|
return names, err
|
|
}
|
|
|
|
func (u *MonitorRepo) GetNetworkNames() ([]string, error) {
|
|
var names []string
|
|
err := global.MonitorDB.Model(&model.MonitorNetwork{}).Distinct().Pluck("name", &names).Error
|
|
return names, err
|
|
}
|
|
|
|
func (u *MonitorRepo) CreateMonitorBase(model model.MonitorBase) error {
|
|
return global.MonitorDB.Create(&model).Error
|
|
}
|
|
func (s *MonitorRepo) BatchCreateMonitorGPU(list []model.MonitorGPU) error {
|
|
if len(list) == 0 {
|
|
return nil
|
|
}
|
|
return global.GPUMonitorDB.CreateInBatches(&list, len(list)).Error
|
|
}
|
|
func (u *MonitorRepo) BatchCreateMonitorIO(ioList []model.MonitorIO) error {
|
|
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
|
|
}
|
|
func (u *MonitorRepo) BatchCreateMonitorNet(ioList []model.MonitorNetwork) error {
|
|
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
|
|
}
|
|
func (u *MonitorRepo) DelMonitorBase(timeForDelete time.Time) error {
|
|
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorBase{}).Error
|
|
}
|
|
func (u *MonitorRepo) DelMonitorIO(timeForDelete time.Time) error {
|
|
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorIO{}).Error
|
|
}
|
|
func (u *MonitorRepo) DelMonitorNet(timeForDelete time.Time) error {
|
|
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
|
|
}
|
|
func (s *MonitorRepo) DelMonitorGPU(timeForDelete time.Time) error {
|
|
return global.GPUMonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorGPU{}).Error
|
|
}
|
|
|
|
func (u *MonitorRepo) GetGPUDevices() ([]model.MonitorGPU, error) {
|
|
var data []model.MonitorGPU
|
|
err := global.GPUMonitorDB.Model(&model.MonitorGPU{}).Select("device_id, product_name, device_type").Group("device_id, product_name, device_type").Order("product_name, device_id").Find(&data).Error
|
|
return data, err
|
|
}
|
|
|
|
func (u *MonitorRepo) WithByGPUDevice(deviceID, name string, legacy bool) DBOption {
|
|
return func(db *gorm.DB) *gorm.DB {
|
|
if deviceID != "" {
|
|
return db.Where("device_id = ?", deviceID)
|
|
}
|
|
db = db.Where("product_name = ?", name)
|
|
if legacy {
|
|
db = db.Where("device_id IS NULL OR device_id = ''")
|
|
}
|
|
return db
|
|
}
|
|
}
|
|
|
|
func (u *MonitorRepo) CountGPU(opts ...DBOption) (int64, error) {
|
|
db := global.GPUMonitorDB.Model(&model.MonitorGPU{})
|
|
for _, opt := range opts {
|
|
db = opt(db)
|
|
}
|
|
var count int64
|
|
err := db.Count(&count).Error
|
|
return count, err
|
|
}
|
|
|
|
func (u *MonitorRepo) GetGPUHistory(start time.Time, bucketSeconds int64, aggregation string, opts ...DBOption) ([]GPUHistoryPoint, error) {
|
|
db := global.GPUMonitorDB.Model(&model.MonitorGPU{})
|
|
for _, opt := range opts {
|
|
db = opt(db)
|
|
}
|
|
expressions := []string{
|
|
"CASE WHEN max_power_limit > 0 THEN 100.0 * power_draw / max_power_limit END",
|
|
"CASE WHEN mem_total > 0 AND mem_used IS NOT NULL THEN 100.0 * mem_used / mem_total ELSE memory_util END",
|
|
"CASE WHEN (process_status = 'ok' OR process_status IS NULL OR process_status = '') AND json_valid(processes) THEN CASE WHEN json_type(processes) = 'array' THEN json_array_length(processes) END END",
|
|
}
|
|
aliases := []string{"power_percent", "memory_percent", "process_count"}
|
|
columns := []string{"*"}
|
|
if bucketSeconds > 0 {
|
|
operation := "AVG"
|
|
if aggregation == "max" {
|
|
operation = "MAX"
|
|
}
|
|
columns = []string{fmt.Sprintf("(CAST(strftime('%%s', created_at) AS INTEGER) - %d) / %d AS bucket", start.Unix(), bucketSeconds)}
|
|
for _, column := range []string{"memory_activity", "encoder_util", "decoder_util", "jpeg_util", "ofa_util", "media_util", "compute_util", "copy_util", "hotspot_temperature", "fan_rpm", "ai_cpu_util", "ctrl_cpu_util", "ddr_used", "ddr_total", "hbm_used", "hbm_total", "ddr_bandwidth", "hbm_bandwidth", "memory_bandwidth", "media_frequency", "hugepages_used", "hugepages_total", "gpu_util", "temperature", "memory_temperature", "power_draw", "max_power_limit", "mem_used", "mem_total", "frequency", "memory_frequency", "fan_speed"} {
|
|
columns = append(columns, operation+"("+column+") AS "+column)
|
|
}
|
|
for i := range expressions {
|
|
expressions[i] = operation + "(" + expressions[i] + ")"
|
|
}
|
|
db = db.Group("bucket").Order("bucket ASC")
|
|
} else {
|
|
db = db.Order("created_at ASC, id ASC")
|
|
}
|
|
for i, expression := range expressions {
|
|
columns = append(columns, expression+" AS "+aliases[i])
|
|
}
|
|
var data []GPUHistoryPoint
|
|
err := db.Select(strings.Join(columns, ", ")).Scan(&data).Error
|
|
return data, err
|
|
}
|