新增Windows代理程序支持
This commit is contained in:
@@ -511,6 +511,18 @@ func HandleMetricsPost(c *gin.Context) {
|
||||
var globalStorage *storage.Storage
|
||||
var deviceStorage device.Storage
|
||||
|
||||
// 硬件信息缓存结构
|
||||
type hardwareCacheItem struct {
|
||||
Data map[string]interface{}
|
||||
ExpiresAt time.Time
|
||||
}
|
||||
|
||||
// 硬件信息缓存
|
||||
var (
|
||||
hardwareCache sync.Map
|
||||
cacheDuration = 5 * time.Minute // 缓存过期时间5分钟
|
||||
)
|
||||
|
||||
// SetStorage 设置全局存储实例
|
||||
func SetStorage(s *storage.Storage) {
|
||||
globalStorage = s
|
||||
@@ -1275,12 +1287,35 @@ func GetHardwareMetrics(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 从存储中查询硬件信息
|
||||
hardwareInfo, err := globalStorage.QueryHardwareMetrics(context.Background(), deviceID)
|
||||
// 尝试从缓存中获取硬件信息
|
||||
var hardwareInfo map[string]interface{}
|
||||
var err error
|
||||
|
||||
if cached, ok := hardwareCache.Load(deviceID); ok {
|
||||
cacheItem := cached.(hardwareCacheItem)
|
||||
if time.Now().Before(cacheItem.ExpiresAt) {
|
||||
// 缓存有效
|
||||
hardwareInfo = cacheItem.Data
|
||||
} else {
|
||||
// 缓存过期,删除并重新查询
|
||||
hardwareCache.Delete(deviceID)
|
||||
hardwareInfo, err = globalStorage.QueryHardwareMetrics(context.Background(), deviceID)
|
||||
}
|
||||
} else {
|
||||
// 缓存未命中,查询数据库
|
||||
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{})
|
||||
} else if len(hardwareInfo) > 0 {
|
||||
// 查询成功且有数据,更新缓存
|
||||
hardwareCache.Store(deviceID, hardwareCacheItem{
|
||||
Data: hardwareInfo,
|
||||
ExpiresAt: time.Now().Add(cacheDuration),
|
||||
})
|
||||
}
|
||||
|
||||
// 为了确保返回的结构与前端期望的一致,我们需要将查询结果转换为期望的格式
|
||||
|
||||
@@ -484,18 +484,19 @@ func (s *Storage) QueryHardwareMetrics(ctx context.Context, deviceID string) (ma
|
||||
if hardwareType == "os" || hardwareType == "cpu" || hardwareType == "memory" {
|
||||
// 对于os、cpu、memory类型,我们只需要一个结果
|
||||
query = `from(bucket: "` + s.bucket + `")
|
||||
|> range(start: -24h)
|
||||
|> filter(fn: (r) => r["_measurement"] == "hardware")
|
||||
|> filter(fn: (r) => r["device_id"] == "` + deviceID + `")
|
||||
|> filter(fn: (r) => r["type"] == "` + hardwareType + `")
|
||||
|> last()`
|
||||
|> range(start: -24h) // 扩大查询范围到最近24小时
|
||||
|> filter(fn: (r) => r["_measurement"] == "hardware")
|
||||
|> filter(fn: (r) => r["device_id"] == "` + deviceID + `")
|
||||
|> filter(fn: (r) => r["type"] == "` + hardwareType + `")
|
||||
|> last()`
|
||||
} else {
|
||||
// 对于disk和network类型,我们需要获取所有设备的所有字段记录
|
||||
// 对于disk和network类型,我们需要获取所有设备的最新完整记录
|
||||
// 先获取所有记录,然后按时间排序,最后只保留最新的记录
|
||||
query = `from(bucket: "` + s.bucket + `")
|
||||
|> range(start: -24h)
|
||||
|> filter(fn: (r) => r["_measurement"] == "hardware")
|
||||
|> filter(fn: (r) => r["device_id"] == "` + deviceID + `")
|
||||
|> filter(fn: (r) => r["type"] == "` + hardwareType + `")`
|
||||
|> range(start: -24h) // 扩大查询范围到最近24小时
|
||||
|> filter(fn: (r) => r["_measurement"] == "hardware")
|
||||
|> filter(fn: (r) => r["device_id"] == "` + deviceID + `")
|
||||
|> filter(fn: (r) => r["type"] == "` + hardwareType + `")`
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
@@ -517,7 +518,14 @@ func (s *Storage) QueryHardwareMetrics(ctx context.Context, deviceID string) (ma
|
||||
record := queryResult.Record()
|
||||
fieldName := record.Field()
|
||||
fieldValue := record.Value()
|
||||
fieldMap[fieldName] = fieldValue
|
||||
|
||||
// 处理布尔类型的值,转换为字符串以避免InfluxDB客户端错误
|
||||
switch v := fieldValue.(type) {
|
||||
case bool:
|
||||
fieldMap[fieldName] = fmt.Sprintf("%t", v)
|
||||
default:
|
||||
fieldMap[fieldName] = fieldValue
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有字段数据,添加到硬件信息结果中
|
||||
@@ -543,38 +551,53 @@ func (s *Storage) QueryHardwareMetrics(ctx context.Context, deviceID string) (ma
|
||||
|
||||
// 获取设备唯一标识
|
||||
deviceKey := ""
|
||||
// 优先使用id字段作为设备标识
|
||||
if id, isString := fieldValue.(string); fieldName == "id" && isString {
|
||||
deviceKey = id
|
||||
|
||||
// 首先从字段中查找id
|
||||
if fieldName == "id" {
|
||||
if id, isString := fieldValue.(string); isString {
|
||||
deviceKey = id
|
||||
} else if id, isFloat := fieldValue.(float64); isFloat {
|
||||
deviceKey = fmt.Sprintf("%d", int(id))
|
||||
}
|
||||
// 创建设备字段映射
|
||||
deviceFields[deviceKey] = make(map[string]interface{})
|
||||
deviceFields[deviceKey]["id"] = id
|
||||
} else {
|
||||
// 否则,查找已存在的设备映射
|
||||
// 遍历所有设备映射,查找当前记录对应的设备
|
||||
for key, fields := range deviceFields {
|
||||
// 如果设备映射中没有id字段,或者id字段为空,跳过
|
||||
if id, ok := fields["id"].(string); ok && id != "" {
|
||||
// 假设当前记录属于该设备
|
||||
deviceKey = key
|
||||
break
|
||||
}
|
||||
if deviceKey != "" {
|
||||
deviceFields[deviceKey] = make(map[string]interface{})
|
||||
deviceFields[deviceKey]["id"] = deviceKey
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到设备标识,使用index作为设备标识
|
||||
// 如果没有通过id字段找到设备标识,尝试从index获取
|
||||
if deviceKey == "" {
|
||||
index := 0
|
||||
if idx, ok := record.ValueByKey("index").(int); ok {
|
||||
index = idx
|
||||
if index, ok := record.ValueByKey("index").(int); ok {
|
||||
deviceKey = fmt.Sprintf("%d", index)
|
||||
// 创建设备字段映射
|
||||
deviceFields[deviceKey] = make(map[string]interface{})
|
||||
}
|
||||
}
|
||||
|
||||
// 如果仍然没有设备标识,查找已存在的设备映射
|
||||
if deviceKey == "" {
|
||||
// 遍历所有设备映射,查找当前记录对应的设备
|
||||
for key := range deviceFields {
|
||||
deviceKey = key
|
||||
break
|
||||
}
|
||||
|
||||
// 如果没有找到任何设备映射,创建一个新的
|
||||
if deviceKey == "" {
|
||||
deviceKey = "0" // 默认使用0作为第一个设备的标识
|
||||
deviceFields[deviceKey] = make(map[string]interface{})
|
||||
}
|
||||
deviceKey = fmt.Sprintf("%d", index)
|
||||
// 创建设备字段映射
|
||||
deviceFields[deviceKey] = make(map[string]interface{})
|
||||
}
|
||||
|
||||
// 添加字段值到设备字段映射中
|
||||
deviceFields[deviceKey][fieldName] = fieldValue
|
||||
// 处理布尔类型的值,转换为字符串以避免InfluxDB客户端错误
|
||||
switch v := fieldValue.(type) {
|
||||
case bool:
|
||||
deviceFields[deviceKey][fieldName] = fmt.Sprintf("%t", v)
|
||||
default:
|
||||
deviceFields[deviceKey][fieldName] = fieldValue
|
||||
}
|
||||
}
|
||||
|
||||
// 将deviceFields转换为切片
|
||||
|
||||
Reference in New Issue
Block a user