增加更多采集指标

This commit is contained in:
Alex Yang
2025-12-06 21:12:56 +08:00
parent c87071390d
commit 8a5ca62793
22 changed files with 3541058 additions and 63 deletions

View File

@@ -5,10 +5,12 @@ import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"strconv"
"strings"
"sync"
"time"
@@ -45,6 +47,7 @@ func RegisterRoutes(r *gin.Engine) {
metrics.GET("/processes", GetProcessMetrics) // 添加进程信息查询端点
metrics.GET("/disk_details", GetDiskDetails) // 添加磁盘详细信息查询端点
metrics.GET("/logs", GetLogs) // 添加系统日志查询端点
metrics.GET("/hardware", GetHardwareMetrics) // 添加硬件信息查询端点
// 添加POST端点接收Agent发送的指标数据
metrics.POST("/", HandleMetricsPost)
}
@@ -91,7 +94,7 @@ type ProcessMetrics struct {
// DiskDetailMetrics 磁盘详细信息
type DiskDetailMetrics struct {
DeviceID string `json:"device_id"` // 设备ID
Path string `json:"path"` // 设备路径
Status string `json:"status"` // 设备状态
Type string `json:"type"` // 设备类型
SizeGB float64 `json:"size_gb"` // 设备大小(GB)
@@ -115,6 +118,52 @@ type NetworkInterfaceMetrics struct {
RxBytes uint64 `json:"rx_bytes"` // 累计接收字节数
}
// OSInfo 操作系统信息
type OSInfo struct {
Name string `json:"name"` // 操作系统名称
Version string `json:"version"` // 操作系统版本
Arch string `json:"arch"` // 系统架构
Fullname string `json:"fullname"` // 完整名称Name+Version
}
// CPUInfo CPU详细信息
type CPUInfo struct {
Model string `json:"model"` // CPU型号
Cores int `json:"cores"` // 核心数
Threads int `json:"threads"` // 线程数
MaxFreq float64 `json:"max_freq"` // 最大频率 (MHz)
MinFreq float64 `json:"min_freq"` // 最小频率 (MHz)
AvgFreq float64 `json:"avg_freq"` // 平均频率 (MHz)
Usage float64 `json:"usage"` // 当前使用率
}
// MemoryInfo 内存详细信息
type MemoryInfo struct {
Total uint64 `json:"total"` // 总容量 (bytes)
Used uint64 `json:"used"` // 已使用 (bytes)
Free uint64 `json:"free"` // 空闲 (bytes)
UsedPercent float64 `json:"used_percent"` // 使用率百分比
}
// NetworkHardwareInfo 网卡硬件信息
type NetworkHardwareInfo struct {
Name string `json:"name"` // 网卡名称
MAC string `json:"mac"` // MAC地址
IPAddresses []string `json:"ip_addresses"` // IP地址列表
MTU int `json:"mtu"` // MTU值
Speed int `json:"speed"` // 网卡速度 (Mbps)
Up bool `json:"up"` // 是否启用
}
// HardwareMetrics 硬件信息指标
type HardwareMetrics struct {
OS OSInfo `json:"os"` // 操作系统信息
CPU CPUInfo `json:"cpu"` // CPU信息
Memory MemoryInfo `json:"memory"` // 内存信息
DiskDetails []DiskDetailMetrics `json:"disk_details"` // 磁盘硬件信息
NetworkCards []NetworkHardwareInfo `json:"network_cards"` // 网卡硬件信息
}
// LogEntry 系统日志条目
type LogEntry struct {
Sequence int `json:"sequence"` // 日志序号
@@ -137,6 +186,8 @@ type MetricsRequest struct {
TxTotal uint64 `json:"tx_total"` // 所有网卡累计发送字节数总和
RxRate uint64 `json:"rx_rate"` // 所有网卡实时接收速率总和 (bytes/s)
TxRate uint64 `json:"tx_rate"` // 所有网卡实时发送速率总和 (bytes/s)
// 硬件信息
Hardware HardwareMetrics `json:"hardware"` // 硬件详细信息
}
// HandleMetricsPost 处理Agent发送的指标数据
@@ -212,7 +263,8 @@ func HandleMetricsPost(c *gin.Context) {
}
// 创建单独的上下文用于InfluxDB写入避免HTTP请求结束时上下文被取消
writeCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// 增加超时时间到30秒确保硬件信息能够被成功写入
writeCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// 处理所有指标
@@ -315,9 +367,9 @@ func HandleMetricsPost(c *gin.Context) {
// 写入磁盘详细信息
for _, diskDetail := range req.DiskDetails {
if err := globalStorage.WriteDiskDetailMetric(writeCtx, deviceID, diskDetail.DeviceID, diskDetail.Status, diskDetail.Type, diskDetail.SizeGB, diskDetail.Model, diskDetail.InterfaceType, diskDetail.Description, baseTags); err != nil {
if err := globalStorage.WriteDiskDetailMetric(writeCtx, deviceID, diskDetail.Path, diskDetail.Status, diskDetail.Type, diskDetail.SizeGB, diskDetail.Model, diskDetail.InterfaceType, diskDetail.Description, baseTags); err != nil {
// 只记录警告,不影响后续指标处理
log.Printf("Warning: Failed to write disk details for device %s: %v", diskDetail.DeviceID, err)
log.Printf("Warning: Failed to write disk details for device %s: %v", diskDetail.Path, err)
}
}
@@ -329,6 +381,79 @@ func HandleMetricsPost(c *gin.Context) {
}
}
// 写入硬件信息
// 操作系统信息
osData := map[string]interface{}{
"name": req.Hardware.OS.Name,
"version": req.Hardware.OS.Version,
"arch": req.Hardware.OS.Arch,
"fullname": req.Hardware.OS.Fullname,
}
if err := globalStorage.WriteHardwareMetric(writeCtx, deviceID, "os", osData, baseTags); err != nil {
log.Printf("Warning: Failed to write OS info: %v", err)
}
// CPU信息
cpuData := map[string]interface{}{
"model": req.Hardware.CPU.Model,
"cores": req.Hardware.CPU.Cores,
"threads": req.Hardware.CPU.Threads,
"max_freq": req.Hardware.CPU.MaxFreq,
"min_freq": req.Hardware.CPU.MinFreq,
"avg_freq": req.Hardware.CPU.AvgFreq,
"usage": req.Hardware.CPU.Usage,
}
if err := globalStorage.WriteHardwareMetric(writeCtx, deviceID, "cpu", cpuData, baseTags); err != nil {
log.Printf("Warning: Failed to write CPU info: %v", err)
}
// 内存信息
memoryData := map[string]interface{}{
"total": req.Hardware.Memory.Total,
"used": req.Hardware.Memory.Used,
"free": req.Hardware.Memory.Free,
"used_percent": req.Hardware.Memory.UsedPercent,
}
if err := globalStorage.WriteHardwareMetric(writeCtx, deviceID, "memory", memoryData, baseTags); err != nil {
log.Printf("Warning: Failed to write memory info: %v", err)
}
// 磁盘详细信息
for i, diskDetail := range req.Hardware.DiskDetails {
diskData := map[string]interface{}{
"path": diskDetail.Path,
"status": diskDetail.Status,
"type": diskDetail.Type,
"size_gb": diskDetail.SizeGB,
"model": diskDetail.Model,
"interface_type": diskDetail.InterfaceType,
"description": diskDetail.Description,
"index": i,
}
if err := globalStorage.WriteHardwareMetric(writeCtx, deviceID, "disk", diskData, baseTags); err != nil {
log.Printf("Warning: Failed to write disk info: %v", err)
}
}
// 网络网卡信息
for i, netCard := range req.Hardware.NetworkCards {
netData := map[string]interface{}{
"name": netCard.Name,
"mac": netCard.MAC,
"mtu": netCard.MTU,
"speed": netCard.Speed,
"up": netCard.Up,
"index": i,
}
// 添加IP地址列表
for j, ipAddr := range netCard.IPAddresses {
netData[fmt.Sprintf("ip_address_%d", j)] = ipAddr
}
if err := globalStorage.WriteHardwareMetric(writeCtx, deviceID, "network", netData, baseTags); err != nil {
log.Printf("Warning: Failed to write network card info: %v", err)
}
}
// 广播指标更新消息,只广播最后一个指标
if i == len(metricsList)-1 {
// 准备广播的磁盘使用率数据(兼容旧格式)
@@ -1119,3 +1244,211 @@ func GetLogs(c *gin.Context) {
"logs": logs,
})
}
// GetHardwareMetrics 获取硬件信息指标
func GetHardwareMetrics(c *gin.Context) {
// 获取查询参数
deviceID := c.Query("device_id") // 必须参数,不能为空
if deviceID == "" {
c.JSON(http.StatusBadRequest, gin.H{
"error": "device_id is required",
})
return
}
// 从设备存储获取设备信息
device, ok := deviceStorage.GetDevice(deviceID)
if !ok {
c.JSON(http.StatusNotFound, gin.H{
"error": "Device not found",
})
return
}
// 从存储中查询硬件信息
hardwareInfo, err := globalStorage.QueryHardwareMetrics(context.Background(), deviceID)
if err != nil {
log.Printf("Warning: Failed to query hardware metrics: %v", err)
// 查询失败时,返回一个空的硬件信息对象
hardwareInfo = make(map[string]interface{})
}
// 为了确保返回的结构与前端期望的一致,我们需要将查询结果转换为期望的格式
hardwareResponse := map[string]interface{}{
"os": map[string]string{
"name": "Unknown",
"version": "Unknown",
"arch": "Unknown",
"fullname": "Unknown",
},
"cpu": map[string]interface{}{
"model": "Unknown",
"cores": 0,
"threads": 0,
"max_freq": 0,
"min_freq": 0,
"avg_freq": 0,
"usage": 0,
},
"memory": map[string]interface{}{
"total": 0,
"used": 0,
"free": 0,
"used_percent": 0,
},
"disk_details": []map[string]interface{}{},
"network_cards": []map[string]interface{}{},
}
// 如果查询到了硬件信息,更新响应结构
if osData, ok := hardwareInfo["os"].(map[string]interface{}); ok {
osMap := hardwareResponse["os"].(map[string]string)
if name, ok := osData["name"].(string); ok {
osMap["name"] = name
}
if version, ok := osData["version"].(string); ok {
osMap["version"] = version
}
if arch, ok := osData["arch"].(string); ok {
osMap["arch"] = arch
}
if fullname, ok := osData["fullname"].(string); ok {
osMap["fullname"] = fullname
}
}
if cpuData, ok := hardwareInfo["cpu"].(map[string]interface{}); ok {
if model, ok := cpuData["model"].(string); ok {
hardwareResponse["cpu"].(map[string]interface{})["model"] = model
}
if cores, ok := cpuData["cores"].(int); ok {
hardwareResponse["cpu"].(map[string]interface{})["cores"] = cores
}
if threads, ok := cpuData["threads"].(int); ok {
hardwareResponse["cpu"].(map[string]interface{})["threads"] = threads
}
if maxFreq, ok := cpuData["max_freq"].(float64); ok {
hardwareResponse["cpu"].(map[string]interface{})["max_freq"] = maxFreq
}
if minFreq, ok := cpuData["min_freq"].(float64); ok {
hardwareResponse["cpu"].(map[string]interface{})["min_freq"] = minFreq
}
if avgFreq, ok := cpuData["avg_freq"].(float64); ok {
hardwareResponse["cpu"].(map[string]interface{})["avg_freq"] = avgFreq
}
if usage, ok := cpuData["usage"].(float64); ok {
hardwareResponse["cpu"].(map[string]interface{})["usage"] = usage
}
}
if memoryData, ok := hardwareInfo["memory"].(map[string]interface{}); ok {
if total, ok := memoryData["total"].(uint64); ok {
hardwareResponse["memory"].(map[string]interface{})["total"] = total
}
if used, ok := memoryData["used"].(uint64); ok {
hardwareResponse["memory"].(map[string]interface{})["used"] = used
}
if free, ok := memoryData["free"].(uint64); ok {
hardwareResponse["memory"].(map[string]interface{})["free"] = free
}
if usedPercent, ok := memoryData["used_percent"].(float64); ok {
hardwareResponse["memory"].(map[string]interface{})["used_percent"] = usedPercent
}
}
// 处理磁盘详细信息
if diskDataList, ok := hardwareInfo["disk"].([]map[string]interface{}); ok {
// 如果是磁盘列表
diskDetails := []map[string]interface{}{}
for _, diskData := range diskDataList {
diskDetail := map[string]interface{}{
"path": diskData["path"],
"status": diskData["status"],
"type": diskData["type"],
"size_gb": diskData["size_gb"],
"model": diskData["model"],
"interface_type": diskData["interface_type"],
"description": diskData["description"],
}
diskDetails = append(diskDetails, diskDetail)
}
hardwareResponse["disk_details"] = diskDetails
} else if diskData, ok := hardwareInfo["disk"].(map[string]interface{}); ok {
// 如果是单个磁盘
diskDetails := []map[string]interface{}{
{
"path": diskData["path"],
"status": diskData["status"],
"type": diskData["type"],
"size_gb": diskData["size_gb"],
"model": diskData["model"],
"interface_type": diskData["interface_type"],
"description": diskData["description"],
},
}
hardwareResponse["disk_details"] = diskDetails
}
// 处理网卡信息
if networkDataList, ok := hardwareInfo["network"].([]map[string]interface{}); ok {
// 如果是网卡列表
networkCards := []map[string]interface{}{}
for _, networkData := range networkDataList {
// 提取IP地址
ipAddresses := []string{}
for k, v := range networkData {
if strings.HasPrefix(k, "ip_address_") {
if ip, ok := v.(string); ok {
ipAddresses = append(ipAddresses, ip)
}
}
}
networkCard := map[string]interface{}{
"name": networkData["name"],
"mac": networkData["mac"],
"ip_addresses": ipAddresses,
"mtu": networkData["mtu"],
"speed": networkData["speed"],
"up": networkData["up"],
}
networkCards = append(networkCards, networkCard)
}
hardwareResponse["network_cards"] = networkCards
} else if networkData, ok := hardwareInfo["network"].(map[string]interface{}); ok {
// 如果是单个网卡
// 提取IP地址
ipAddresses := []string{}
for k, v := range networkData {
if strings.HasPrefix(k, "ip_address_") {
if ip, ok := v.(string); ok {
ipAddresses = append(ipAddresses, ip)
}
}
}
networkCard := map[string]interface{}{
"name": networkData["name"],
"mac": networkData["mac"],
"ip_addresses": ipAddresses,
"mtu": networkData["mtu"],
"speed": networkData["speed"],
"up": networkData["up"],
}
hardwareResponse["network_cards"] = []map[string]interface{}{networkCard}
}
// 确保OS的fullname字段被正确设置
osMap := hardwareResponse["os"].(map[string]string)
if osMap["fullname"] == "Unknown" && osMap["name"] != "Unknown" && osMap["version"] != "Unknown" {
// 如果fullname是默认值但name和version已经正确设置那么构建fullname
osMap["fullname"] = osMap["name"] + " " + osMap["version"]
}
// 返回硬件信息
c.JSON(http.StatusOK, gin.H{
"device_id": deviceID,
"name": device.Name,
"hardware": hardwareResponse,
})
}