数据调优
This commit is contained in:
BIN
agent/agent
BIN
agent/agent
Binary file not shown.
@@ -31,15 +31,24 @@ type Config struct {
|
|||||||
|
|
||||||
// NetworkInterfaceMetrics 网卡监控指标
|
// NetworkInterfaceMetrics 网卡监控指标
|
||||||
type NetworkInterfaceMetrics struct {
|
type NetworkInterfaceMetrics struct {
|
||||||
BytesSent uint64 `json:"bytes_sent"`
|
BytesSent uint64 `json:"bytes_sent"` // 发送速率 (bytes/s)
|
||||||
BytesReceived uint64 `json:"bytes_received"`
|
BytesReceived uint64 `json:"bytes_received"` // 接收速率 (bytes/s)
|
||||||
|
TxBytes uint64 `json:"tx_bytes"` // 累计发送字节数
|
||||||
|
RxBytes uint64 `json:"rx_bytes"` // 累计接收字节数
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiskMetrics 磁盘监控指标
|
||||||
|
type DiskMetrics struct {
|
||||||
|
UsedPercent float64 `json:"used_percent"` // 使用率百分比
|
||||||
|
Total uint64 `json:"total"` // 总容量 (bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metrics 监控指标
|
// Metrics 监控指标
|
||||||
type Metrics struct {
|
type Metrics struct {
|
||||||
CPU float64 `json:"cpu"`
|
CPU float64 `json:"cpu"`
|
||||||
|
CPUHz float64 `json:"cpu_hz"` // CPU频率 (MHz)
|
||||||
Memory float64 `json:"memory"`
|
Memory float64 `json:"memory"`
|
||||||
Disk map[string]float64 `json:"disk"`
|
Disk map[string]DiskMetrics `json:"disk"`
|
||||||
Network map[string]NetworkInterfaceMetrics `json:"network"`
|
Network map[string]NetworkInterfaceMetrics `json:"network"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,14 +280,29 @@ func readConfigFile() {
|
|||||||
log.Printf("Config loaded from %s", configFile)
|
log.Printf("Config loaded from %s", configFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 采集CPU使用率
|
// 采集CPU使用率和频率
|
||||||
func collectCPU() (float64, error) {
|
func collectCPU() (float64, float64, error) {
|
||||||
|
// 采集CPU使用率
|
||||||
percentages, err := cpu.Percent(0, false)
|
percentages, err := cpu.Percent(0, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return percentages[0], nil
|
// 采集CPU频率(使用CPUInfo获取频率信息)
|
||||||
|
cpus, err := cpu.Info()
|
||||||
|
if err != nil {
|
||||||
|
return percentages[0], 0, nil // 频率采集失败,返回使用率和0频率
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算平均频率 (转换为MHz)
|
||||||
|
var totalFreq float64
|
||||||
|
for _, cpuInfo := range cpus {
|
||||||
|
// CPUInfo返回的MHz,直接累加
|
||||||
|
totalFreq += cpuInfo.Mhz
|
||||||
|
}
|
||||||
|
avgFreq := totalFreq / float64(len(cpus))
|
||||||
|
|
||||||
|
return percentages[0], avgFreq, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 采集内存使用率
|
// 采集内存使用率
|
||||||
@@ -291,8 +315,8 @@ func collectMemory() (float64, error) {
|
|||||||
return vm.UsedPercent, nil
|
return vm.UsedPercent, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 采集磁盘使用率
|
// 采集磁盘使用率和总容量
|
||||||
func collectDisk() (map[string]float64, error) {
|
func collectDisk() (map[string]DiskMetrics, error) {
|
||||||
// 获取系统所有挂载点
|
// 获取系统所有挂载点
|
||||||
partitions, err := disk.Partitions(false)
|
partitions, err := disk.Partitions(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -300,26 +324,32 @@ func collectDisk() (map[string]float64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化返回值
|
// 初始化返回值
|
||||||
diskUsageMap := make(map[string]float64)
|
diskMetricsMap := make(map[string]DiskMetrics)
|
||||||
|
|
||||||
// 遍历所有挂载点,采集磁盘使用率
|
// 遍历所有挂载点,采集磁盘使用率和总容量
|
||||||
for _, partition := range partitions {
|
for _, partition := range partitions {
|
||||||
// 只处理本地文件系统,跳过网络文件系统
|
// 只处理本地文件系统,跳过网络文件系统
|
||||||
if partition.Fstype == "" {
|
if partition.Fstype == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 采集磁盘使用率
|
// 采集磁盘使用率和总容量
|
||||||
usage, err := disk.Usage(partition.Mountpoint)
|
usage, err := disk.Usage(partition.Mountpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存磁盘使用率
|
// 创建DiskMetrics结构体
|
||||||
diskUsageMap[partition.Mountpoint] = usage.UsedPercent
|
diskMetrics := DiskMetrics{
|
||||||
|
UsedPercent: usage.UsedPercent,
|
||||||
|
Total: usage.Total,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存磁盘指标
|
||||||
|
diskMetricsMap[partition.Mountpoint] = diskMetrics
|
||||||
}
|
}
|
||||||
|
|
||||||
return diskUsageMap, nil
|
return diskMetricsMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 采集网络流量
|
// 采集网络流量
|
||||||
@@ -342,7 +372,7 @@ func collectNetwork() (map[string]NetworkInterfaceMetrics, error) {
|
|||||||
|
|
||||||
// 遍历所有网卡
|
// 遍历所有网卡
|
||||||
for _, counter := range ioCounters {
|
for _, counter := range ioCounters {
|
||||||
// 获取当前网卡的流量
|
// 获取当前网卡的累计流量
|
||||||
currentBytesSent := counter.BytesSent
|
currentBytesSent := counter.BytesSent
|
||||||
currentBytesReceived := counter.BytesRecv
|
currentBytesReceived := counter.BytesRecv
|
||||||
|
|
||||||
@@ -372,17 +402,19 @@ func collectNetwork() (map[string]NetworkInterfaceMetrics, error) {
|
|||||||
BytesReceived: currentBytesReceived,
|
BytesReceived: currentBytesReceived,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存当前网卡的速率
|
// 保存当前网卡的速率和累计流量
|
||||||
networkMetrics[counter.Name] = NetworkInterfaceMetrics{
|
networkMetrics[counter.Name] = NetworkInterfaceMetrics{
|
||||||
BytesSent: bytesSentRate,
|
BytesSent: bytesSentRate,
|
||||||
BytesReceived: bytesReceivedRate,
|
BytesReceived: bytesReceivedRate,
|
||||||
|
TxBytes: currentBytesSent,
|
||||||
|
RxBytes: currentBytesReceived,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新上一次采集时间
|
// 更新上一次采集时间
|
||||||
lastCollectTime = currentTime
|
lastCollectTime = currentTime
|
||||||
|
|
||||||
// 返回所有网卡的速率
|
// 返回所有网卡的速率和累计流量
|
||||||
return networkMetrics, nil
|
return networkMetrics, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,12 +422,13 @@ func collectNetwork() (map[string]NetworkInterfaceMetrics, error) {
|
|||||||
func collectMetrics() (*Metrics, error) {
|
func collectMetrics() (*Metrics, error) {
|
||||||
metrics := &Metrics{}
|
metrics := &Metrics{}
|
||||||
|
|
||||||
// 采集CPU使用率
|
// 采集CPU使用率和频率
|
||||||
cpuUsage, err := collectCPU()
|
cpuUsage, cpuHz, err := collectCPU()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to collect CPU metrics: %w", err)
|
return nil, fmt.Errorf("failed to collect CPU metrics: %w", err)
|
||||||
}
|
}
|
||||||
metrics.CPU = cpuUsage
|
metrics.CPU = cpuUsage
|
||||||
|
metrics.CPUHz = cpuHz
|
||||||
|
|
||||||
// 采集内存使用率
|
// 采集内存使用率
|
||||||
memoryUsage, err := collectMemory()
|
memoryUsage, err := collectMemory()
|
||||||
@@ -404,12 +437,12 @@ func collectMetrics() (*Metrics, error) {
|
|||||||
}
|
}
|
||||||
metrics.Memory = memoryUsage
|
metrics.Memory = memoryUsage
|
||||||
|
|
||||||
// 采集磁盘使用率
|
// 采集磁盘使用率和总容量
|
||||||
diskUsageMap, err := collectDisk()
|
diskMetricsMap, err := collectDisk()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to collect disk metrics: %w", err)
|
return nil, fmt.Errorf("failed to collect disk metrics: %w", err)
|
||||||
}
|
}
|
||||||
metrics.Disk = diskUsageMap
|
metrics.Disk = diskMetricsMap
|
||||||
|
|
||||||
// 采集网络流量
|
// 采集网络流量
|
||||||
networkMetrics, err := collectNetwork()
|
networkMetrics, err := collectNetwork()
|
||||||
@@ -517,7 +550,7 @@ func startHTTPServer() {
|
|||||||
log.Printf("API Request: %s %s", r.Method, r.URL.Path)
|
log.Printf("API Request: %s %s", r.Method, r.URL.Path)
|
||||||
}
|
}
|
||||||
// 采集当前状态
|
// 采集当前状态
|
||||||
cpu, _ := collectCPU()
|
cpu, cpuHz, _ := collectCPU()
|
||||||
memory, _ := collectMemory()
|
memory, _ := collectMemory()
|
||||||
disk, _ := collectDisk()
|
disk, _ := collectDisk()
|
||||||
|
|
||||||
@@ -529,6 +562,7 @@ func startHTTPServer() {
|
|||||||
"debug": config.Debug,
|
"debug": config.Debug,
|
||||||
"interval": config.Interval,
|
"interval": config.Interval,
|
||||||
"cpu": cpu,
|
"cpu": cpu,
|
||||||
|
"cpu_hz": cpuHz,
|
||||||
"memory": memory,
|
"memory": memory,
|
||||||
"disk": disk,
|
"disk": disk,
|
||||||
}
|
}
|
||||||
@@ -607,7 +641,7 @@ func collectMetricsToBuffer() {
|
|||||||
totalDiskUsage := 0.0
|
totalDiskUsage := 0.0
|
||||||
diskCount := 0
|
diskCount := 0
|
||||||
for _, usage := range metrics.Disk {
|
for _, usage := range metrics.Disk {
|
||||||
totalDiskUsage += usage
|
totalDiskUsage += usage.UsedPercent
|
||||||
diskCount++
|
diskCount++
|
||||||
}
|
}
|
||||||
averageDiskUsage := 0.0
|
averageDiskUsage := 0.0
|
||||||
@@ -649,7 +683,7 @@ func collectAndSendMetrics() {
|
|||||||
totalMemory += metrics.Memory
|
totalMemory += metrics.Memory
|
||||||
// 计算磁盘使用率
|
// 计算磁盘使用率
|
||||||
for _, usage := range metrics.Disk {
|
for _, usage := range metrics.Disk {
|
||||||
totalDiskUsage += usage
|
totalDiskUsage += usage.UsedPercent
|
||||||
diskCount++
|
diskCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
agent/monitor-agent
Executable file
BIN
agent/monitor-agent
Executable file
Binary file not shown.
@@ -67,17 +67,26 @@ func RegisterRoutes(r *gin.Engine) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DiskMetrics 磁盘监控指标
|
||||||
|
type DiskMetrics struct {
|
||||||
|
UsedPercent float64 `json:"used_percent"` // 使用率百分比
|
||||||
|
Total uint64 `json:"total"` // 总容量 (bytes)
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkInterfaceMetrics 网卡监控指标
|
// NetworkInterfaceMetrics 网卡监控指标
|
||||||
type NetworkInterfaceMetrics struct {
|
type NetworkInterfaceMetrics struct {
|
||||||
BytesSent uint64 `json:"bytes_sent"`
|
BytesSent uint64 `json:"bytes_sent"` // 发送速率 (bytes/s)
|
||||||
BytesReceived uint64 `json:"bytes_received"`
|
BytesReceived uint64 `json:"bytes_received"` // 接收速率 (bytes/s)
|
||||||
|
TxBytes uint64 `json:"tx_bytes"` // 累计发送字节数
|
||||||
|
RxBytes uint64 `json:"rx_bytes"` // 累计接收字节数
|
||||||
}
|
}
|
||||||
|
|
||||||
// MetricsRequest 指标请求结构
|
// MetricsRequest 指标请求结构
|
||||||
type MetricsRequest struct {
|
type MetricsRequest struct {
|
||||||
CPU float64 `json:"cpu"`
|
CPU float64 `json:"cpu"`
|
||||||
|
CPUHz float64 `json:"cpu_hz"` // CPU频率 (MHz)
|
||||||
Memory float64 `json:"memory"`
|
Memory float64 `json:"memory"`
|
||||||
Disk map[string]float64 `json:"disk"`
|
Disk map[string]DiskMetrics `json:"disk"`
|
||||||
Network map[string]NetworkInterfaceMetrics `json:"network"`
|
Network map[string]NetworkInterfaceMetrics `json:"network"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,12 +164,20 @@ func HandleMetricsPost(c *gin.Context) {
|
|||||||
|
|
||||||
// 处理所有指标
|
// 处理所有指标
|
||||||
for i, req := range metricsList {
|
for i, req := range metricsList {
|
||||||
// 写入CPU指标
|
// 写入CPU使用率指标
|
||||||
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "cpu", req.CPU, baseTags); err != nil {
|
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "cpu", req.CPU, baseTags); err != nil {
|
||||||
// 只记录警告,不影响后续指标处理
|
// 只记录警告,不影响后续指标处理
|
||||||
log.Printf("Warning: Failed to write CPU metrics: %v", err)
|
log.Printf("Warning: Failed to write CPU metrics: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 写入CPU频率指标(如果有)
|
||||||
|
if req.CPUHz > 0 {
|
||||||
|
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "cpu_hz", req.CPUHz, baseTags); err != nil {
|
||||||
|
// 只记录警告,不影响后续指标处理
|
||||||
|
log.Printf("Warning: Failed to write CPU Hz metrics: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 写入内存指标
|
// 写入内存指标
|
||||||
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "memory", req.Memory, baseTags); err != nil {
|
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "memory", req.Memory, baseTags); err != nil {
|
||||||
// 只记录警告,不影响后续指标处理
|
// 只记录警告,不影响后续指标处理
|
||||||
@@ -168,7 +185,7 @@ func HandleMetricsPost(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 写入磁盘指标,支持多个挂载点
|
// 写入磁盘指标,支持多个挂载点
|
||||||
for mountpoint, usage := range req.Disk {
|
for mountpoint, diskMetrics := range req.Disk {
|
||||||
// 为每个挂载点创建标签,包含基础标签和挂载点
|
// 为每个挂载点创建标签,包含基础标签和挂载点
|
||||||
tags := make(map[string]string)
|
tags := make(map[string]string)
|
||||||
// 复制基础标签
|
// 复制基础标签
|
||||||
@@ -178,8 +195,8 @@ func HandleMetricsPost(c *gin.Context) {
|
|||||||
// 添加挂载点标签
|
// 添加挂载点标签
|
||||||
tags["mountpoint"] = mountpoint
|
tags["mountpoint"] = mountpoint
|
||||||
|
|
||||||
// 写入磁盘指标
|
// 写入磁盘使用率指标
|
||||||
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "disk", usage, tags); err != nil {
|
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "disk", diskMetrics.UsedPercent, tags); err != nil {
|
||||||
// 只记录警告,不影响后续指标处理
|
// 只记录警告,不影响后续指标处理
|
||||||
log.Printf("Warning: Failed to write disk metrics for mountpoint %s: %v", mountpoint, err)
|
log.Printf("Warning: Failed to write disk metrics for mountpoint %s: %v", mountpoint, err)
|
||||||
}
|
}
|
||||||
@@ -187,6 +204,7 @@ func HandleMetricsPost(c *gin.Context) {
|
|||||||
|
|
||||||
// 写入网络指标,支持多个网卡
|
// 写入网络指标,支持多个网卡
|
||||||
var totalBytesSent, totalBytesReceived uint64
|
var totalBytesSent, totalBytesReceived uint64
|
||||||
|
var totalTxBytes, totalRxBytes uint64 // 累计总流量
|
||||||
for interfaceName, networkMetrics := range req.Network {
|
for interfaceName, networkMetrics := range req.Network {
|
||||||
// 为每个网卡创建标签,包含基础标签和网卡名称
|
// 为每个网卡创建标签,包含基础标签和网卡名称
|
||||||
interfaceTags := make(map[string]string)
|
interfaceTags := make(map[string]string)
|
||||||
@@ -197,32 +215,57 @@ func HandleMetricsPost(c *gin.Context) {
|
|||||||
// 添加网卡标签
|
// 添加网卡标签
|
||||||
interfaceTags["interface"] = interfaceName
|
interfaceTags["interface"] = interfaceName
|
||||||
|
|
||||||
// 写入网络发送指标
|
// 写入网络发送速率指标
|
||||||
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "network_sent", float64(networkMetrics.BytesSent), interfaceTags); err != nil {
|
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "network_sent", float64(networkMetrics.BytesSent), interfaceTags); err != nil {
|
||||||
// 只记录警告,不影响后续指标处理
|
// 只记录警告,不影响后续指标处理
|
||||||
log.Printf("Warning: Failed to write network sent metrics for interface %s: %v", interfaceName, err)
|
log.Printf("Warning: Failed to write network sent metrics for interface %s: %v", interfaceName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 写入网络接收指标
|
// 写入网络接收速率指标
|
||||||
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "network_received", float64(networkMetrics.BytesReceived), interfaceTags); err != nil {
|
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "network_received", float64(networkMetrics.BytesReceived), interfaceTags); err != nil {
|
||||||
// 只记录警告,不影响后续指标处理
|
// 只记录警告,不影响后续指标处理
|
||||||
log.Printf("Warning: Failed to write network received metrics for interface %s: %v", interfaceName, err)
|
log.Printf("Warning: Failed to write network received metrics for interface %s: %v", interfaceName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 累加总流量
|
// 写入累计发送字节数指标
|
||||||
|
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "network_tx_bytes", float64(networkMetrics.TxBytes), interfaceTags); err != nil {
|
||||||
|
// 只记录警告,不影响后续指标处理
|
||||||
|
log.Printf("Warning: Failed to write network tx_bytes metrics for interface %s: %v", interfaceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入累计接收字节数指标
|
||||||
|
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "network_rx_bytes", float64(networkMetrics.RxBytes), interfaceTags); err != nil {
|
||||||
|
// 只记录警告,不影响后续指标处理
|
||||||
|
log.Printf("Warning: Failed to write network rx_bytes metrics for interface %s: %v", interfaceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 累加总流量速率
|
||||||
totalBytesSent += networkMetrics.BytesSent
|
totalBytesSent += networkMetrics.BytesSent
|
||||||
totalBytesReceived += networkMetrics.BytesReceived
|
totalBytesReceived += networkMetrics.BytesReceived
|
||||||
|
|
||||||
|
// 累加累计总流量
|
||||||
|
totalTxBytes += networkMetrics.TxBytes
|
||||||
|
totalRxBytes += networkMetrics.RxBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
// 广播指标更新消息,只广播最后一个指标
|
// 广播指标更新消息,只广播最后一个指标
|
||||||
if i == len(metricsList)-1 {
|
if i == len(metricsList)-1 {
|
||||||
|
// 准备广播的磁盘使用率数据(兼容旧格式)
|
||||||
|
compatDisk := make(map[string]float64)
|
||||||
|
for mountpoint, diskMetrics := range req.Disk {
|
||||||
|
compatDisk[mountpoint] = diskMetrics.UsedPercent
|
||||||
|
}
|
||||||
|
|
||||||
metrics := map[string]interface{}{
|
metrics := map[string]interface{}{
|
||||||
"cpu": req.CPU,
|
"cpu": req.CPU,
|
||||||
|
"cpu_hz": req.CPUHz,
|
||||||
"memory": req.Memory,
|
"memory": req.Memory,
|
||||||
"disk": req.Disk,
|
"disk": compatDisk, // 使用兼容格式的磁盘数据
|
||||||
"network": map[string]uint64{
|
"network": map[string]uint64{
|
||||||
"bytes_sent": totalBytesSent,
|
"bytes_sent": totalBytesSent,
|
||||||
"bytes_received": totalBytesReceived,
|
"bytes_received": totalBytesReceived,
|
||||||
|
"tx_bytes": totalTxBytes,
|
||||||
|
"rx_bytes": totalRxBytes,
|
||||||
},
|
},
|
||||||
"network_interfaces": req.Network,
|
"network_interfaces": req.Network,
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -1119,8 +1119,16 @@ async function loadMetrics() {
|
|||||||
fetchMetric('network')
|
fetchMetric('network')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 格式化数据,确保updateStatusCards函数能正确处理
|
||||||
|
const formattedMetrics = {
|
||||||
|
cpu: cpuData,
|
||||||
|
memory: memoryData,
|
||||||
|
disk: formatDiskDataForCards(diskData),
|
||||||
|
network: formatNetworkDataForCards(networkSumData)
|
||||||
|
};
|
||||||
|
|
||||||
// 更新状态卡片
|
// 更新状态卡片
|
||||||
updateStatusCards({ cpu: cpuData, memory: memoryData, disk: diskData, network: networkSumData });
|
updateStatusCards(formattedMetrics);
|
||||||
|
|
||||||
// 更新图表
|
// 更新图表
|
||||||
updateCharts(cpuData, memoryData, diskData, networkSumData);
|
updateCharts(cpuData, memoryData, diskData, networkSumData);
|
||||||
@@ -1131,6 +1139,71 @@ async function loadMetrics() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 格式化磁盘数据,用于状态卡片显示
|
||||||
|
function formatDiskDataForCards(diskData) {
|
||||||
|
// 如果diskData是空对象,返回空对象
|
||||||
|
if (!diskData || typeof diskData !== 'object' || Array.isArray(diskData)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedDiskData = {};
|
||||||
|
|
||||||
|
// 遍历每个挂载点
|
||||||
|
for (const mountpoint in diskData) {
|
||||||
|
const mountpointData = diskData[mountpoint];
|
||||||
|
|
||||||
|
// 如果挂载点数据是数组,获取最新的数据点
|
||||||
|
if (Array.isArray(mountpointData) && mountpointData.length > 0) {
|
||||||
|
// 最新的数据点是数组的最后一个元素
|
||||||
|
const latestData = mountpointData[mountpointData.length - 1];
|
||||||
|
formattedDiskData[mountpoint] = {
|
||||||
|
used_percent: latestData.value,
|
||||||
|
// 尝试从历史数据获取总容量
|
||||||
|
total: state.historyMetrics.disk && state.historyMetrics.disk[mountpoint] && state.historyMetrics.disk[mountpoint].total || 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedDiskData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化网络数据,用于状态卡片显示
|
||||||
|
function formatNetworkDataForCards(networkData) {
|
||||||
|
// 如果networkData是空对象,返回空对象
|
||||||
|
if (!networkData || typeof networkData !== 'object' || Array.isArray(networkData)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedNetworkData = {
|
||||||
|
bytes_sent: 0,
|
||||||
|
bytes_received: 0,
|
||||||
|
tx_bytes: 0,
|
||||||
|
rx_bytes: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// 遍历每个网卡
|
||||||
|
for (const iface in networkData) {
|
||||||
|
const ifaceData = networkData[iface];
|
||||||
|
|
||||||
|
// 检查是否有sent和received数据
|
||||||
|
if (ifaceData.sent && ifaceData.received) {
|
||||||
|
// 如果sent和received是数组,获取最新的数据点
|
||||||
|
if (Array.isArray(ifaceData.sent) && ifaceData.sent.length > 0 &&
|
||||||
|
Array.isArray(ifaceData.received) && ifaceData.received.length > 0) {
|
||||||
|
// 最新的数据点是数组的最后一个元素
|
||||||
|
const latestSent = ifaceData.sent[ifaceData.sent.length - 1].value;
|
||||||
|
const latestReceived = ifaceData.received[ifaceData.received.length - 1].value;
|
||||||
|
|
||||||
|
// 累加速率
|
||||||
|
formattedNetworkData.bytes_sent += latestSent;
|
||||||
|
formattedNetworkData.bytes_received += latestReceived;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedNetworkData;
|
||||||
|
}
|
||||||
|
|
||||||
// WebSocket初始化
|
// WebSocket初始化
|
||||||
function initWebSocket() {
|
function initWebSocket() {
|
||||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||||
@@ -1215,6 +1288,7 @@ function updateStatusCards(metrics) {
|
|||||||
// 使用历史数据或当前数据
|
// 使用历史数据或当前数据
|
||||||
const displayMetrics = {
|
const displayMetrics = {
|
||||||
cpu: metrics.cpu || state.historyMetrics.cpu,
|
cpu: metrics.cpu || state.historyMetrics.cpu,
|
||||||
|
cpu_hz: metrics.cpu_hz || state.historyMetrics.cpu_hz,
|
||||||
memory: metrics.memory || state.historyMetrics.memory,
|
memory: metrics.memory || state.historyMetrics.memory,
|
||||||
disk: metrics.disk || state.historyMetrics.disk,
|
disk: metrics.disk || state.historyMetrics.disk,
|
||||||
network: metrics.network || state.historyMetrics.network
|
network: metrics.network || state.historyMetrics.network
|
||||||
@@ -1228,24 +1302,33 @@ function updateStatusCards(metrics) {
|
|||||||
|
|
||||||
// 解析CPU数据
|
// 解析CPU数据
|
||||||
if (Array.isArray(displayMetrics.cpu) && displayMetrics.cpu.length > 0) {
|
if (Array.isArray(displayMetrics.cpu) && displayMetrics.cpu.length > 0) {
|
||||||
|
// 数组格式:获取最新的数据点
|
||||||
cpuUsage = displayMetrics.cpu[displayMetrics.cpu.length - 1].value;
|
cpuUsage = displayMetrics.cpu[displayMetrics.cpu.length - 1].value;
|
||||||
} else if (typeof displayMetrics.cpu === 'number') {
|
} else if (typeof displayMetrics.cpu === 'number') {
|
||||||
|
// 数值格式
|
||||||
cpuUsage = displayMetrics.cpu;
|
cpuUsage = displayMetrics.cpu;
|
||||||
} else if (typeof displayMetrics.cpu === 'object' && displayMetrics.cpu.usage) {
|
} else if (typeof displayMetrics.cpu === 'object' && displayMetrics.cpu.usage) {
|
||||||
|
// 对象格式,包含usage, frequency, load
|
||||||
cpuUsage = displayMetrics.cpu.usage;
|
cpuUsage = displayMetrics.cpu.usage;
|
||||||
cpuGhz = displayMetrics.cpu.frequency || 0;
|
cpuGhz = displayMetrics.cpu.frequency || 0;
|
||||||
cpuLoad = displayMetrics.cpu.load || 0;
|
cpuLoad = displayMetrics.cpu.load || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从单独的cpu_hz字段获取CPU频率(如果有)
|
||||||
|
if (displayMetrics.cpu_hz && typeof displayMetrics.cpu_hz === 'number') {
|
||||||
|
cpuGhz = displayMetrics.cpu_hz / 1000; // 转换为GHz
|
||||||
|
}
|
||||||
|
|
||||||
// 更新显示
|
// 更新显示
|
||||||
const cpuElement = document.getElementById('cpuValue');
|
const cpuElement = document.getElementById('cpuValue');
|
||||||
const cpuDetailsElement = document.getElementById('cpuDetails');
|
const cpuDetailsElement = document.getElementById('cpuDetails');
|
||||||
if (cpuElement) {
|
if (cpuElement) {
|
||||||
cpuElement.textContent = `${cpuUsage.toFixed(1)}%`;
|
cpuElement.textContent = `${cpuUsage.toFixed(1)}%`;
|
||||||
// 设置红色显示如果达到顶峰
|
// 设置红色显示如果达到顶峰,同时保留原有的样式类
|
||||||
cpuElement.className = cpuUsage > 90 ? 'text-red-500' : '';
|
cpuElement.className = `text-3xl font-bold metric-value ${cpuUsage > 90 ? 'text-red-500' : 'text-gray-900'}`;
|
||||||
}
|
}
|
||||||
if (cpuDetailsElement) {
|
if (cpuDetailsElement) {
|
||||||
|
cpuDetailsElement.className = 'text-xs text-gray-500 mt-1';
|
||||||
cpuDetailsElement.textContent = `${cpuGhz.toFixed(2)} GHz | 负载: ${cpuLoad.toFixed(2)}`;
|
cpuDetailsElement.textContent = `${cpuGhz.toFixed(2)} GHz | 负载: ${cpuLoad.toFixed(2)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1258,24 +1341,50 @@ function updateStatusCards(metrics) {
|
|||||||
|
|
||||||
// 解析内存数据
|
// 解析内存数据
|
||||||
if (Array.isArray(displayMetrics.memory) && displayMetrics.memory.length > 0) {
|
if (Array.isArray(displayMetrics.memory) && displayMetrics.memory.length > 0) {
|
||||||
|
// 数组格式:获取最新的数据点
|
||||||
memoryUsage = displayMetrics.memory[displayMetrics.memory.length - 1].value;
|
memoryUsage = displayMetrics.memory[displayMetrics.memory.length - 1].value;
|
||||||
} else if (typeof displayMetrics.memory === 'number') {
|
} else if (typeof displayMetrics.memory === 'number') {
|
||||||
|
// 数值格式
|
||||||
memoryUsage = displayMetrics.memory;
|
memoryUsage = displayMetrics.memory;
|
||||||
} else if (typeof displayMetrics.memory === 'object') {
|
} else if (typeof displayMetrics.memory === 'object') {
|
||||||
|
// 对象格式,包含usage, used, total
|
||||||
memoryUsage = displayMetrics.memory.usage || 0;
|
memoryUsage = displayMetrics.memory.usage || 0;
|
||||||
memoryUsed = displayMetrics.memory.used || 0;
|
memoryUsed = displayMetrics.memory.used || 0;
|
||||||
memoryTotal = displayMetrics.memory.total || 0;
|
memoryTotal = displayMetrics.memory.total || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果只有使用率,没有使用量和总量,尝试从其他地方获取
|
||||||
|
if (memoryTotal === 0 && state.historyMetrics.memory && typeof state.historyMetrics.memory === 'object') {
|
||||||
|
memoryUsed = state.historyMetrics.memory.used || 0;
|
||||||
|
memoryTotal = state.historyMetrics.memory.total || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果内存总量仍为0,尝试使用默认值或从API获取
|
||||||
|
if (memoryTotal === 0) {
|
||||||
|
// 尝试从系统获取内存总量(如果浏览器支持)
|
||||||
|
if (navigator.deviceMemory) {
|
||||||
|
memoryTotal = navigator.deviceMemory * 1024 * 1024 * 1024; // 转换为字节
|
||||||
|
} else {
|
||||||
|
// 使用默认值16GB
|
||||||
|
memoryTotal = 16 * 1024 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算使用量(如果只有使用率)
|
||||||
|
if (memoryUsed === 0 && memoryTotal > 0) {
|
||||||
|
memoryUsed = (memoryTotal * memoryUsage) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
// 更新显示
|
// 更新显示
|
||||||
const memoryElement = document.getElementById('memoryValue');
|
const memoryElement = document.getElementById('memoryValue');
|
||||||
const memoryDetailsElement = document.getElementById('memoryDetails');
|
const memoryDetailsElement = document.getElementById('memoryDetails');
|
||||||
if (memoryElement) {
|
if (memoryElement) {
|
||||||
memoryElement.textContent = `${memoryUsage.toFixed(1)}%`;
|
memoryElement.textContent = `${memoryUsage.toFixed(1)}%`;
|
||||||
// 设置红色显示如果达到顶峰
|
// 设置红色显示如果达到顶峰,同时保留原有的样式类
|
||||||
memoryElement.className = memoryUsage > 90 ? 'text-red-500' : '';
|
memoryElement.className = `text-3xl font-bold metric-value ${memoryUsage > 90 ? 'text-red-500' : 'text-gray-900'}`;
|
||||||
}
|
}
|
||||||
if (memoryDetailsElement) {
|
if (memoryDetailsElement) {
|
||||||
|
memoryDetailsElement.className = 'text-xs text-gray-500 mt-1';
|
||||||
memoryDetailsElement.textContent = `${formatBytes(memoryUsed)} / ${formatBytes(memoryTotal)}`;
|
memoryDetailsElement.textContent = `${formatBytes(memoryUsed)} / ${formatBytes(memoryTotal)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1292,6 +1401,7 @@ function updateStatusCards(metrics) {
|
|||||||
// 解析磁盘数据
|
// 解析磁盘数据
|
||||||
if (typeof displayMetrics.disk === 'object' && displayMetrics.disk !== null && !Array.isArray(displayMetrics.disk)) {
|
if (typeof displayMetrics.disk === 'object' && displayMetrics.disk !== null && !Array.isArray(displayMetrics.disk)) {
|
||||||
// 按挂载点分组的数据
|
// 按挂载点分组的数据
|
||||||
|
let hasValidData = false;
|
||||||
for (const mountpoint in displayMetrics.disk) {
|
for (const mountpoint in displayMetrics.disk) {
|
||||||
// 跳过排除的挂载点
|
// 跳过排除的挂载点
|
||||||
if (excludedMountpoints.includes(mountpoint)) {
|
if (excludedMountpoints.includes(mountpoint)) {
|
||||||
@@ -1299,9 +1409,41 @@ function updateStatusCards(metrics) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = displayMetrics.disk[mountpoint];
|
const data = displayMetrics.disk[mountpoint];
|
||||||
if (data && typeof data === 'object' && data.used !== undefined && data.total !== undefined) {
|
if (data && typeof data === 'object') {
|
||||||
totalUsed += data.used;
|
if (data.used_percent !== undefined && data.total !== undefined) {
|
||||||
totalSize += data.total;
|
// 新格式:包含used_percent和total字段
|
||||||
|
// 计算已使用大小(total * used_percent / 100)
|
||||||
|
const used = (data.total * data.used_percent) / 100;
|
||||||
|
totalUsed += used;
|
||||||
|
totalSize += data.total;
|
||||||
|
hasValidData = true;
|
||||||
|
} else if (data.used !== undefined && data.total !== undefined) {
|
||||||
|
// 旧格式:包含used和total字段
|
||||||
|
totalUsed += data.used;
|
||||||
|
totalSize += data.total;
|
||||||
|
hasValidData = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有有效数据,尝试使用历史数据
|
||||||
|
if (!hasValidData && state.historyMetrics.disk && typeof state.historyMetrics.disk === 'object' && !Array.isArray(state.historyMetrics.disk)) {
|
||||||
|
for (const mountpoint in state.historyMetrics.disk) {
|
||||||
|
if (excludedMountpoints.includes(mountpoint)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = state.historyMetrics.disk[mountpoint];
|
||||||
|
if (data && typeof data === 'object') {
|
||||||
|
if (data.used_percent !== undefined && data.total !== undefined) {
|
||||||
|
const used = (data.total * data.used_percent) / 100;
|
||||||
|
totalUsed += used;
|
||||||
|
totalSize += data.total;
|
||||||
|
} else if (data.used !== undefined && data.total !== undefined) {
|
||||||
|
totalUsed += data.used;
|
||||||
|
totalSize += data.total;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (typeof displayMetrics.disk === 'object' && displayMetrics.disk.used !== undefined && displayMetrics.disk.total !== undefined) {
|
} else if (typeof displayMetrics.disk === 'object' && displayMetrics.disk.used !== undefined && displayMetrics.disk.total !== undefined) {
|
||||||
@@ -1310,9 +1452,36 @@ function updateStatusCards(metrics) {
|
|||||||
totalSize = displayMetrics.disk.total;
|
totalSize = displayMetrics.disk.total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果只有使用率,没有使用量和总量,尝试计算
|
||||||
|
if (totalSize === 0 && displayMetrics.disk && typeof displayMetrics.disk === 'number') {
|
||||||
|
// 如果disk是一个数字,尝试从历史数据获取总量
|
||||||
|
if (state.historyMetrics.disk && typeof state.historyMetrics.disk === 'object' && !Array.isArray(state.historyMetrics.disk)) {
|
||||||
|
for (const mountpoint in state.historyMetrics.disk) {
|
||||||
|
if (excludedMountpoints.includes(mountpoint)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = state.historyMetrics.disk[mountpoint];
|
||||||
|
if (data && typeof data === 'object') {
|
||||||
|
if (data.total !== undefined) {
|
||||||
|
totalSize += data.total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算使用量
|
||||||
|
if (totalSize > 0) {
|
||||||
|
totalUsed = (totalSize * displayMetrics.disk) / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 计算使用率
|
// 计算使用率
|
||||||
if (totalSize > 0) {
|
if (totalSize > 0) {
|
||||||
usagePercent = (totalUsed / totalSize) * 100;
|
usagePercent = (totalUsed / totalSize) * 100;
|
||||||
|
} else if (typeof displayMetrics.disk === 'number') {
|
||||||
|
// 如果disk是一个数字,直接使用它作为使用率
|
||||||
|
usagePercent = displayMetrics.disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新显示
|
// 更新显示
|
||||||
@@ -1320,10 +1489,11 @@ function updateStatusCards(metrics) {
|
|||||||
const diskDetailsElement = document.getElementById('diskDetails');
|
const diskDetailsElement = document.getElementById('diskDetails');
|
||||||
if (diskElement) {
|
if (diskElement) {
|
||||||
diskElement.textContent = `${usagePercent.toFixed(1)}%`;
|
diskElement.textContent = `${usagePercent.toFixed(1)}%`;
|
||||||
// 设置红色显示如果达到顶峰
|
// 设置红色显示如果达到顶峰,同时保留原有的样式类
|
||||||
diskElement.className = usagePercent > 90 ? 'text-red-500' : '';
|
diskElement.className = `text-3xl font-bold metric-value ${usagePercent > 90 ? 'text-red-500' : 'text-gray-900'}`;
|
||||||
}
|
}
|
||||||
if (diskDetailsElement) {
|
if (diskDetailsElement) {
|
||||||
|
diskDetailsElement.className = 'text-xs text-gray-500 mt-1';
|
||||||
diskDetailsElement.textContent = `${formatBytes(totalUsed)} / ${formatBytes(totalSize)}`;
|
diskDetailsElement.textContent = `${formatBytes(totalUsed)} / ${formatBytes(totalSize)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1336,61 +1506,114 @@ function updateStatusCards(metrics) {
|
|||||||
let receivedTotal = 0;
|
let receivedTotal = 0;
|
||||||
|
|
||||||
// 解析网络数据
|
// 解析网络数据
|
||||||
if (displayMetrics.network.sent && displayMetrics.network.received) {
|
if (typeof displayMetrics.network === 'object') {
|
||||||
// 处理数组格式的数据
|
if (Array.isArray(displayMetrics.network)) {
|
||||||
if (Array.isArray(displayMetrics.network.sent) && displayMetrics.network.sent.length > 0 &&
|
// 数组格式的数据
|
||||||
Array.isArray(displayMetrics.network.received) && displayMetrics.network.received.length > 0) {
|
if (displayMetrics.network.length > 0) {
|
||||||
|
// 获取最新的数据点
|
||||||
|
const latestData = displayMetrics.network[displayMetrics.network.length - 1];
|
||||||
|
sentRate = latestData.sent || 0;
|
||||||
|
receivedRate = latestData.received || 0;
|
||||||
|
sentTotal = latestData.tx_bytes || 0;
|
||||||
|
receivedTotal = latestData.rx_bytes || 0;
|
||||||
|
}
|
||||||
|
} else if (displayMetrics.network.sent && displayMetrics.network.received) {
|
||||||
|
// 包含sent和received字段的数据
|
||||||
|
if (Array.isArray(displayMetrics.network.sent) && displayMetrics.network.sent.length > 0 &&
|
||||||
|
Array.isArray(displayMetrics.network.received) && displayMetrics.network.received.length > 0) {
|
||||||
|
// 处理数组格式的速率数据
|
||||||
|
sentRate = displayMetrics.network.sent[displayMetrics.network.sent.length - 1].value;
|
||||||
|
receivedRate = displayMetrics.network.received[displayMetrics.network.received.length - 1].value;
|
||||||
|
} else if (typeof displayMetrics.network.sent === 'number' && typeof displayMetrics.network.received === 'number') {
|
||||||
|
// 处理数值格式的速率数据
|
||||||
|
sentRate = displayMetrics.network.sent;
|
||||||
|
receivedRate = displayMetrics.network.received;
|
||||||
|
}
|
||||||
|
|
||||||
sentRate = displayMetrics.network.sent[displayMetrics.network.sent.length - 1].value;
|
// 处理总量数据
|
||||||
receivedRate = displayMetrics.network.received[displayMetrics.network.received.length - 1].value;
|
sentTotal = displayMetrics.network.tx_bytes || displayMetrics.network.sent_total || 0;
|
||||||
// 计算总量(假设数组中的值是累积的)
|
receivedTotal = displayMetrics.network.rx_bytes || displayMetrics.network.received_total || 0;
|
||||||
sentTotal = displayMetrics.network.sent.reduce((sum, item) => sum + item.value, 0);
|
} else if (displayMetrics.network.bytes_sent !== undefined && displayMetrics.network.bytes_received !== undefined) {
|
||||||
receivedTotal = displayMetrics.network.received.reduce((sum, item) => sum + item.value, 0);
|
// WebSocket消息格式 - 总流量
|
||||||
}
|
sentRate = displayMetrics.network.bytes_sent;
|
||||||
// 处理数值格式的数据
|
receivedRate = displayMetrics.network.bytes_received;
|
||||||
else if (typeof displayMetrics.network.sent === 'number' && typeof displayMetrics.network.received === 'number') {
|
|
||||||
sentRate = displayMetrics.network.sent;
|
// 优先使用tx_bytes和rx_bytes作为总量
|
||||||
receivedRate = displayMetrics.network.received;
|
sentTotal = displayMetrics.network.tx_bytes || 0;
|
||||||
sentTotal = displayMetrics.network.sent_total || sentRate;
|
receivedTotal = displayMetrics.network.rx_bytes || 0;
|
||||||
receivedTotal = displayMetrics.network.received_total || receivedRate;
|
} else {
|
||||||
}
|
// 按网卡分组的数据,计算总流量
|
||||||
} else if (typeof displayMetrics.network === 'object' &&
|
for (const iface in displayMetrics.network) {
|
||||||
displayMetrics.network.bytes_sent !== undefined &&
|
const ifaceMetrics = displayMetrics.network[iface];
|
||||||
displayMetrics.network.bytes_received !== undefined) {
|
if (typeof ifaceMetrics === 'object') {
|
||||||
// WebSocket消息格式 - 总流量
|
// 计算速率
|
||||||
sentRate = displayMetrics.network.bytes_sent;
|
if (ifaceMetrics.bytes_sent !== undefined) {
|
||||||
receivedRate = displayMetrics.network.bytes_received;
|
sentRate += ifaceMetrics.bytes_sent;
|
||||||
sentTotal = displayMetrics.network.bytes_sent_total || sentRate;
|
} else if (ifaceMetrics.sent !== undefined) {
|
||||||
receivedTotal = displayMetrics.network.bytes_received_total || receivedRate;
|
sentRate += ifaceMetrics.sent;
|
||||||
} else if (typeof displayMetrics.network === 'object' && !Array.isArray(displayMetrics.network)) {
|
}
|
||||||
// 按网卡分组的数据,计算总流量
|
|
||||||
for (const iface in displayMetrics.network) {
|
if (ifaceMetrics.bytes_received !== undefined) {
|
||||||
const ifaceMetrics = displayMetrics.network[iface];
|
receivedRate += ifaceMetrics.bytes_received;
|
||||||
if (ifaceMetrics.bytes_sent !== undefined && ifaceMetrics.bytes_received !== undefined) {
|
} else if (ifaceMetrics.received !== undefined) {
|
||||||
sentRate += ifaceMetrics.bytes_sent;
|
receivedRate += ifaceMetrics.received;
|
||||||
receivedRate += ifaceMetrics.bytes_received;
|
}
|
||||||
sentTotal += ifaceMetrics.bytes_sent_total || ifaceMetrics.bytes_sent;
|
|
||||||
receivedTotal += ifaceMetrics.bytes_received_total || ifaceMetrics.bytes_received;
|
// 计算总量(所有网卡的tx_bytes和rx_bytes之和)
|
||||||
} else if (ifaceMetrics.BytesSent !== undefined && ifaceMetrics.BytesReceived !== undefined) {
|
if (ifaceMetrics.tx_bytes !== undefined) {
|
||||||
sentRate += ifaceMetrics.BytesSent;
|
sentTotal += ifaceMetrics.tx_bytes;
|
||||||
receivedRate += ifaceMetrics.BytesReceived;
|
} else if (ifaceMetrics.bytes_sent_total !== undefined) {
|
||||||
|
sentTotal += ifaceMetrics.bytes_sent_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ifaceMetrics.rx_bytes !== undefined) {
|
||||||
|
receivedTotal += ifaceMetrics.rx_bytes;
|
||||||
|
} else if (ifaceMetrics.bytes_received_total !== undefined) {
|
||||||
|
receivedTotal += ifaceMetrics.bytes_received_total;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算比率
|
// 如果总量为0,尝试使用速率作为总量(临时解决方案)
|
||||||
let ratioText = '0.0';
|
if (sentTotal === 0) {
|
||||||
if (sentRate > 0) {
|
sentTotal = sentRate;
|
||||||
ratioText = (receivedRate / sentRate).toFixed(1);
|
}
|
||||||
|
if (receivedTotal === 0) {
|
||||||
|
receivedTotal = receivedRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算比率并格式化显示
|
||||||
|
let ratioDisplay = "0.0";
|
||||||
|
let ratioDirection = "<span style='color: green;'>↓</span> / <span style='color: red;'>↑</span>";
|
||||||
|
|
||||||
|
if (sentRate === 0 && receivedRate === 0) {
|
||||||
|
// 没有流量
|
||||||
|
ratioDisplay = "0.0";
|
||||||
|
} else if (sentRate === 0) {
|
||||||
|
// 只有接收流量
|
||||||
|
ratioDisplay = "∞";
|
||||||
|
ratioDirection = "<span style='color: green;'>↓</span>";
|
||||||
|
} else if (receivedRate === 0) {
|
||||||
|
// 只有发送流量
|
||||||
|
ratioDisplay = "0.0";
|
||||||
|
ratioDirection = "<span style='color: red;'>↑</span>";
|
||||||
|
} else {
|
||||||
|
// 正常计算比率
|
||||||
|
const ratio = receivedRate / sentRate;
|
||||||
|
ratioDisplay = ratio.toFixed(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新显示
|
// 更新显示
|
||||||
const networkValueElement = document.getElementById('networkValue');
|
const networkValueElement = document.getElementById('networkValue');
|
||||||
const networkDetailsElement = document.getElementById('networkDetails');
|
const networkDetailsElement = document.getElementById('networkDetails');
|
||||||
if (networkValueElement) {
|
if (networkValueElement) {
|
||||||
networkValueElement.innerHTML = `${ratioText} <span style="color: green;">↓</span> / <span style="color: red;">↑</span>`;
|
networkValueElement.className = 'text-3xl font-bold text-gray-900 metric-value';
|
||||||
|
networkValueElement.innerHTML = `${ratioDisplay} ${ratioDirection}`;
|
||||||
}
|
}
|
||||||
if (networkDetailsElement) {
|
if (networkDetailsElement) {
|
||||||
|
networkDetailsElement.className = 'text-xs text-gray-500 mt-1';
|
||||||
networkDetailsElement.innerHTML =
|
networkDetailsElement.innerHTML =
|
||||||
`接收: <span style="color: green;">${formatBytes(receivedRate, 2, true)}</span> | ` +
|
`接收: <span style="color: green;">${formatBytes(receivedRate, 2, true)}</span> | ` +
|
||||||
`发送: <span style="color: red;">${formatBytes(sentRate, 2, true)}</span><br>` +
|
`发送: <span style="color: red;">${formatBytes(sentRate, 2, true)}</span><br>` +
|
||||||
@@ -1405,6 +1628,9 @@ function updateHistoryMetrics(metrics) {
|
|||||||
if (metrics.cpu) {
|
if (metrics.cpu) {
|
||||||
state.historyMetrics.cpu = metrics.cpu;
|
state.historyMetrics.cpu = metrics.cpu;
|
||||||
}
|
}
|
||||||
|
if (metrics.cpu_hz) {
|
||||||
|
state.historyMetrics.cpu_hz = metrics.cpu_hz;
|
||||||
|
}
|
||||||
if (metrics.memory) {
|
if (metrics.memory) {
|
||||||
state.historyMetrics.memory = metrics.memory;
|
state.historyMetrics.memory = metrics.memory;
|
||||||
}
|
}
|
||||||
|
|||||||
72
backend/test/test_influxdb.go
Normal file
72
backend/test/test_influxdb.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
influxdb2 "github.com/influxdata/influxdb-client-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// 使用配置文件中的InfluxDB配置
|
||||||
|
url := "http://10.35.10.130:8066"
|
||||||
|
token := "aVI5qMGz6e8d4pfyhVZNYfS5we7C8Bb-5bi-V7LpL3K6CmQyudauigoxDFv1UFo2Hvda7swKEqTe8eP6xy4jBw=="
|
||||||
|
username := "admin"
|
||||||
|
password := "Wxf26051"
|
||||||
|
org := "AMAZEHOME"
|
||||||
|
bucket := "AMAZEHOME"
|
||||||
|
|
||||||
|
fmt.Printf("Testing InfluxDB connection to %s\n", url)
|
||||||
|
fmt.Printf("Org: %s, Bucket: %s\n", org, bucket)
|
||||||
|
fmt.Printf("Username: %s, Password: %s\n", username, password)
|
||||||
|
fmt.Printf("Token: %s\n", token)
|
||||||
|
|
||||||
|
// 测试1: 使用Token认证
|
||||||
|
fmt.Println("\n=== Test 1: Using Token Authentication ===")
|
||||||
|
client1 := influxdb2.NewClient(url, token)
|
||||||
|
defer client1.Close()
|
||||||
|
|
||||||
|
// 测试连接
|
||||||
|
health, err := client1.Health(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Health check failed: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Health check result: %v\n", health)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试2: 使用Username/Password认证(通过URL嵌入)
|
||||||
|
fmt.Println("\n=== Test 2: Using Username/Password Authentication (Embedded in URL) ===")
|
||||||
|
authURL := fmt.Sprintf("http://%s:%s@10.35.10.130:8066", username, password)
|
||||||
|
client2 := influxdb2.NewClient(authURL, "")
|
||||||
|
defer client2.Close()
|
||||||
|
|
||||||
|
// 测试连接
|
||||||
|
health2, err2 := client2.Health(context.Background())
|
||||||
|
if err2 != nil {
|
||||||
|
fmt.Printf("Health check failed: %v\n", err2)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Health check result: %v\n", health2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试3: 尝试写入数据点
|
||||||
|
fmt.Println("\n=== Test 3: Trying to Write Data Point ===")
|
||||||
|
// 使用client2进行测试
|
||||||
|
writeAPI := client2.WriteAPIBlocking(org, bucket)
|
||||||
|
|
||||||
|
point := influxdb2.NewPoint(
|
||||||
|
"test_metric",
|
||||||
|
map[string]string{"test_tag": "test_value"},
|
||||||
|
map[string]interface{}{"value": 1.0},
|
||||||
|
time.Now(),
|
||||||
|
)
|
||||||
|
|
||||||
|
err = writeAPI.WritePoint(context.Background(), point)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Write failed: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Println("Write successful!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("\n=== Test Completed ===")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user