web修复
This commit is contained in:
BIN
agent/agent
BIN
agent/agent
Binary file not shown.
@@ -29,15 +29,18 @@ type Config struct {
|
||||
APIPort int `json:"api_port"` // API端口
|
||||
}
|
||||
|
||||
// NetworkInterfaceMetrics 网卡监控指标
|
||||
type NetworkInterfaceMetrics struct {
|
||||
BytesSent uint64 `json:"bytes_sent"`
|
||||
BytesReceived uint64 `json:"bytes_received"`
|
||||
}
|
||||
|
||||
// Metrics 监控指标
|
||||
type Metrics struct {
|
||||
CPU float64 `json:"cpu"`
|
||||
Memory float64 `json:"memory"`
|
||||
Disk map[string]float64 `json:"disk"`
|
||||
Network struct {
|
||||
BytesSent uint64 `json:"bytes_sent"`
|
||||
BytesReceived uint64 `json:"bytes_received"`
|
||||
} `json:"network"`
|
||||
Network map[string]NetworkInterfaceMetrics `json:"network"`
|
||||
}
|
||||
|
||||
// 全局配置
|
||||
@@ -47,9 +50,13 @@ var config Config
|
||||
var parsedInterval time.Duration
|
||||
|
||||
// 保存上一次网络流量采集的数据
|
||||
type NetworkStats struct {
|
||||
BytesSent uint64
|
||||
BytesReceived uint64
|
||||
}
|
||||
|
||||
var (
|
||||
lastBytesSent uint64
|
||||
lastBytesReceived uint64
|
||||
lastNetworkStats = make(map[string]NetworkStats)
|
||||
lastCollectTime time.Time
|
||||
)
|
||||
|
||||
@@ -316,20 +323,28 @@ func collectDisk() (map[string]float64, error) {
|
||||
}
|
||||
|
||||
// 采集网络流量
|
||||
func collectNetwork() (uint64, uint64, error) {
|
||||
ioCounters, err := net.IOCounters(false)
|
||||
func collectNetwork() (map[string]NetworkInterfaceMetrics, error) {
|
||||
// 获取所有网卡的统计数据
|
||||
ioCounters, err := net.IOCounters(true)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ioCounters) == 0 {
|
||||
return 0, 0, nil
|
||||
return make(map[string]NetworkInterfaceMetrics), nil
|
||||
}
|
||||
|
||||
// 获取当前时间和流量
|
||||
// 获取当前时间
|
||||
currentTime := time.Now()
|
||||
currentBytesSent := ioCounters[0].BytesSent
|
||||
currentBytesReceived := ioCounters[0].BytesRecv
|
||||
|
||||
// 初始化返回值
|
||||
networkMetrics := make(map[string]NetworkInterfaceMetrics)
|
||||
|
||||
// 遍历所有网卡
|
||||
for _, counter := range ioCounters {
|
||||
// 获取当前网卡的流量
|
||||
currentBytesSent := counter.BytesSent
|
||||
currentBytesReceived := counter.BytesRecv
|
||||
|
||||
// 计算速率
|
||||
var bytesSentRate, bytesReceivedRate uint64
|
||||
@@ -337,23 +352,38 @@ func collectNetwork() (uint64, uint64, error) {
|
||||
// 计算时间差(秒)
|
||||
timeDiff := currentTime.Sub(lastCollectTime).Seconds()
|
||||
if timeDiff > 0 {
|
||||
// 获取上一次该网卡的流量
|
||||
lastStats, exists := lastNetworkStats[counter.Name]
|
||||
if exists {
|
||||
// 计算流量差
|
||||
sentDiff := currentBytesSent - lastBytesSent
|
||||
receivedDiff := currentBytesReceived - lastBytesReceived
|
||||
sentDiff := currentBytesSent - lastStats.BytesSent
|
||||
receivedDiff := currentBytesReceived - lastStats.BytesReceived
|
||||
|
||||
// 计算速率(bytes/s)
|
||||
bytesSentRate = uint64(float64(sentDiff) / timeDiff)
|
||||
bytesReceivedRate = uint64(float64(receivedDiff) / timeDiff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新上一次采集的值
|
||||
lastBytesSent = currentBytesSent
|
||||
lastBytesReceived = currentBytesReceived
|
||||
lastNetworkStats[counter.Name] = NetworkStats{
|
||||
BytesSent: currentBytesSent,
|
||||
BytesReceived: currentBytesReceived,
|
||||
}
|
||||
|
||||
// 保存当前网卡的速率
|
||||
networkMetrics[counter.Name] = NetworkInterfaceMetrics{
|
||||
BytesSent: bytesSentRate,
|
||||
BytesReceived: bytesReceivedRate,
|
||||
}
|
||||
}
|
||||
|
||||
// 更新上一次采集时间
|
||||
lastCollectTime = currentTime
|
||||
|
||||
// 返回速率而不是累计流量
|
||||
return bytesSentRate, bytesReceivedRate, nil
|
||||
// 返回所有网卡的速率
|
||||
return networkMetrics, nil
|
||||
}
|
||||
|
||||
// 采集所有监控指标
|
||||
@@ -382,13 +412,12 @@ func collectMetrics() (*Metrics, error) {
|
||||
metrics.Disk = diskUsageMap
|
||||
|
||||
// 采集网络流量
|
||||
bytesSent, bytesReceived, err := collectNetwork()
|
||||
networkMetrics, err := collectNetwork()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to collect network metrics: %w", err)
|
||||
}
|
||||
// 直接使用采集到的累计流量
|
||||
metrics.Network.BytesSent = bytesSent
|
||||
metrics.Network.BytesReceived = bytesReceived
|
||||
// 直接使用采集到的网卡流量
|
||||
metrics.Network = networkMetrics
|
||||
|
||||
return metrics, nil
|
||||
}
|
||||
@@ -407,7 +436,7 @@ func sendMetrics(metricsList []*Metrics) error {
|
||||
}
|
||||
|
||||
// 创建请求
|
||||
req, err := http.NewRequest("POST", fmt.Sprintf("%s/metrics", config.ServerURL), bytes.NewBuffer(jsonData))
|
||||
req, err := http.NewRequest("POST", fmt.Sprintf("%s/metrics/", config.ServerURL), bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
10
agent/test_agent.json
Normal file
10
agent/test_agent.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"server_url": "http://localhost:8080/api",
|
||||
"id": "test-agent",
|
||||
"name": "Test Agent",
|
||||
"device_id": "test-device",
|
||||
"token": "bb30bfaee01bf7b541bbefe422f72645",
|
||||
"interval": "5s",
|
||||
"debug": true,
|
||||
"api_port": 8081
|
||||
}
|
||||
11
agent/test_metrics.sh
Executable file
11
agent/test_metrics.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 测试发送单个指标对象
|
||||
echo "测试发送单个指标对象:"
|
||||
curl -v -X POST -H "Content-Type: application/json" -H "X-Device-ID: test-device" -H "X-Agent-Name: test-agent" -H "X-Device-Token: test-token" -d '{"cpu": 50.5, "memory": 30.2, "disk": {":/": 45.6}, "network": {"eth0": {"bytes_sent": 1000, "bytes_received": 2000}}}' http://localhost:8080/api/metrics/
|
||||
|
||||
echo "\n---\n"
|
||||
|
||||
# 测试发送指标数组
|
||||
echo "测试发送指标数组:"
|
||||
curl -v -X POST -H "Content-Type: application/json" -H "X-Device-ID: test-device" -H "X-Agent-Name: test-agent" -H "X-Device-Token: test-token" -d '[{"cpu": 50.5, "memory": 30.2, "disk": {":/": 45.6}, "network": {"eth0": {"bytes_sent": 1000, "bytes_received": 2000}}}, {"cpu": 60.5, "memory": 40.2, "disk": {":/": 55.6}, "network": {"eth0": {"bytes_sent": 2000, "bytes_received": 3000}}}]' http://localhost:8080/api/metrics/
|
||||
@@ -67,15 +67,18 @@ func RegisterRoutes(r *gin.Engine) {
|
||||
}
|
||||
}
|
||||
|
||||
// NetworkInterfaceMetrics 网卡监控指标
|
||||
type NetworkInterfaceMetrics struct {
|
||||
BytesSent uint64 `json:"bytes_sent"`
|
||||
BytesReceived uint64 `json:"bytes_received"`
|
||||
}
|
||||
|
||||
// MetricsRequest 指标请求结构
|
||||
type MetricsRequest struct {
|
||||
CPU float64 `json:"cpu"`
|
||||
Memory float64 `json:"memory"`
|
||||
Disk map[string]float64 `json:"disk"`
|
||||
Network struct {
|
||||
BytesSent uint64 `json:"bytes_sent"`
|
||||
BytesReceived uint64 `json:"bytes_received"`
|
||||
} `json:"network"`
|
||||
Network map[string]NetworkInterfaceMetrics `json:"network"`
|
||||
}
|
||||
|
||||
// HandleMetricsPost 处理Agent发送的指标数据
|
||||
@@ -127,11 +130,20 @@ func HandleMetricsPost(c *gin.Context) {
|
||||
// 处理请求体,支持单指标对象和指标数组
|
||||
var metricsList []MetricsRequest
|
||||
|
||||
// 读取请求体到缓冲区,以便多次解析
|
||||
body, err := c.GetRawData()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Failed to read request body",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 首先尝试解析为数组
|
||||
if err := c.ShouldBindJSON(&metricsList); err != nil {
|
||||
if err := json.Unmarshal(body, &metricsList); err != nil {
|
||||
// 如果解析数组失败,尝试解析为单个对象
|
||||
var singleMetric MetricsRequest
|
||||
if err := c.ShouldBindJSON(&singleMetric); err != nil {
|
||||
if err := json.Unmarshal(body, &singleMetric); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Invalid request body",
|
||||
})
|
||||
@@ -173,16 +185,33 @@ func HandleMetricsPost(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// 写入网络指标,支持多个网卡
|
||||
var totalBytesSent, totalBytesReceived uint64
|
||||
for interfaceName, networkMetrics := range req.Network {
|
||||
// 为每个网卡创建标签,包含基础标签和网卡名称
|
||||
interfaceTags := make(map[string]string)
|
||||
// 复制基础标签
|
||||
for k, v := range baseTags {
|
||||
interfaceTags[k] = v
|
||||
}
|
||||
// 添加网卡标签
|
||||
interfaceTags["interface"] = interfaceName
|
||||
|
||||
// 写入网络发送指标
|
||||
if err := globalStorage.WriteMetric(c.Request.Context(), deviceID, "network_sent", float64(req.Network.BytesSent), baseTags); 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: %v", 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(req.Network.BytesReceived), baseTags); 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: %v", err)
|
||||
log.Printf("Warning: Failed to write network received metrics for interface %s: %v", interfaceName, err)
|
||||
}
|
||||
|
||||
// 累加总流量
|
||||
totalBytesSent += networkMetrics.BytesSent
|
||||
totalBytesReceived += networkMetrics.BytesReceived
|
||||
}
|
||||
|
||||
// 广播指标更新消息,只广播最后一个指标
|
||||
@@ -192,9 +221,10 @@ func HandleMetricsPost(c *gin.Context) {
|
||||
"memory": req.Memory,
|
||||
"disk": req.Disk,
|
||||
"network": map[string]uint64{
|
||||
"bytes_sent": req.Network.BytesSent,
|
||||
"bytes_received": req.Network.BytesReceived,
|
||||
"bytes_sent": totalBytesSent,
|
||||
"bytes_received": totalBytesReceived,
|
||||
},
|
||||
"network_interfaces": req.Network,
|
||||
}
|
||||
broadcastMetricsUpdate(deviceID, metrics)
|
||||
}
|
||||
@@ -440,15 +470,61 @@ func GetNetworkMetrics(c *gin.Context) {
|
||||
receivedPoints = []storage.MetricPoint{}
|
||||
}
|
||||
|
||||
// 处理数据,传递interval、startTime和endTime参数
|
||||
processedSentData := ProcessMetrics(sentPoints, aggregation, interval, startTime, endTime)
|
||||
processedReceivedData := ProcessMetrics(receivedPoints, aggregation, interval, startTime, endTime)
|
||||
// 按网卡名称分组发送和接收的指标
|
||||
sentByInterface := make(map[string][]storage.MetricPoint)
|
||||
receivedByInterface := make(map[string][]storage.MetricPoint)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": map[string][]MetricData{
|
||||
// 分组发送的网络指标
|
||||
for _, point := range sentPoints {
|
||||
// 获取网卡名称,默认使用"all"表示所有网卡
|
||||
interfaceName := point.Tags["interface"]
|
||||
if interfaceName == "" {
|
||||
interfaceName = "all"
|
||||
}
|
||||
sentByInterface[interfaceName] = append(sentByInterface[interfaceName], point)
|
||||
}
|
||||
|
||||
// 分组接收的网络指标
|
||||
for _, point := range receivedPoints {
|
||||
// 获取网卡名称,默认使用"all"表示所有网卡
|
||||
interfaceName := point.Tags["interface"]
|
||||
if interfaceName == "" {
|
||||
interfaceName = "all"
|
||||
}
|
||||
receivedByInterface[interfaceName] = append(receivedByInterface[interfaceName], point)
|
||||
}
|
||||
|
||||
// 处理数据,为每个网卡创建独立的数据集
|
||||
result := make(map[string]map[string][]MetricData)
|
||||
|
||||
// 合并所有网卡名称
|
||||
allInterfaces := make(map[string]bool)
|
||||
for iface := range sentByInterface {
|
||||
allInterfaces[iface] = true
|
||||
}
|
||||
for iface := range receivedByInterface {
|
||||
allInterfaces[iface] = true
|
||||
}
|
||||
|
||||
// 为每个网卡处理数据
|
||||
for iface := range allInterfaces {
|
||||
// 获取该网卡的发送和接收指标
|
||||
ifaceSentPoints := sentByInterface[iface]
|
||||
ifaceReceivedPoints := receivedByInterface[iface]
|
||||
|
||||
// 处理数据
|
||||
processedSentData := ProcessMetrics(ifaceSentPoints, aggregation, interval, startTime, endTime)
|
||||
processedReceivedData := ProcessMetrics(ifaceReceivedPoints, aggregation, interval, startTime, endTime)
|
||||
|
||||
// 保存结果
|
||||
result[iface] = map[string][]MetricData{
|
||||
"sent": processedSentData,
|
||||
"received": processedReceivedData,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": result,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1349,11 +1349,25 @@ function updateStatusCards(metrics) {
|
||||
} else if (typeof displayMetrics.network === 'object' &&
|
||||
displayMetrics.network.bytes_sent !== undefined &&
|
||||
displayMetrics.network.bytes_received !== undefined) {
|
||||
// WebSocket消息格式
|
||||
// WebSocket消息格式 - 总流量
|
||||
sentRate = displayMetrics.network.bytes_sent;
|
||||
receivedRate = displayMetrics.network.bytes_received;
|
||||
sentTotal = displayMetrics.network.bytes_sent_total || sentRate;
|
||||
receivedTotal = displayMetrics.network.bytes_received_total || receivedRate;
|
||||
} else if (typeof displayMetrics.network === 'object' && !Array.isArray(displayMetrics.network)) {
|
||||
// 按网卡分组的数据,计算总流量
|
||||
for (const iface in displayMetrics.network) {
|
||||
const ifaceMetrics = displayMetrics.network[iface];
|
||||
if (ifaceMetrics.bytes_sent !== undefined && ifaceMetrics.bytes_received !== undefined) {
|
||||
sentRate += ifaceMetrics.bytes_sent;
|
||||
receivedRate += ifaceMetrics.bytes_received;
|
||||
sentTotal += ifaceMetrics.bytes_sent_total || ifaceMetrics.bytes_sent;
|
||||
receivedTotal += ifaceMetrics.bytes_received_total || ifaceMetrics.bytes_received;
|
||||
} else if (ifaceMetrics.BytesSent !== undefined && ifaceMetrics.BytesReceived !== undefined) {
|
||||
sentRate += ifaceMetrics.BytesSent;
|
||||
receivedRate += ifaceMetrics.BytesReceived;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算比率
|
||||
@@ -1590,12 +1604,23 @@ function updateCharts(cpuData, memoryData, diskData, networkData) {
|
||||
charts.disk.update();
|
||||
}
|
||||
|
||||
// 保存当前选中的网卡
|
||||
state.currentInterface = state.currentInterface || 'all';
|
||||
|
||||
// 更新网络流量趋势图表(发送总和和接收总和)
|
||||
if (networkData && networkData.sent && networkData.received && charts.network) {
|
||||
if (networkData && charts.network) {
|
||||
let selectedNetworkData = networkData;
|
||||
|
||||
// 如果是按网卡分组的数据,选择当前选中的网卡数据
|
||||
if (typeof networkData === 'object' && networkData.sent === undefined && networkData.received === undefined) {
|
||||
selectedNetworkData = networkData[state.currentInterface] || networkData['all'] || {};
|
||||
}
|
||||
|
||||
if (selectedNetworkData.sent && selectedNetworkData.received) {
|
||||
// 计算发送总和(时间段内的累积值)
|
||||
if (Array.isArray(networkData.sent) && networkData.sent.length > 0) {
|
||||
if (Array.isArray(selectedNetworkData.sent) && selectedNetworkData.sent.length > 0) {
|
||||
// 排序发送数据
|
||||
const sortedSent = sortDataByTime(networkData.sent);
|
||||
const sortedSent = sortDataByTime(selectedNetworkData.sent);
|
||||
|
||||
// 计算累积发送总和(MB)
|
||||
let cumulativeSent = 0;
|
||||
@@ -1618,9 +1643,9 @@ function updateCharts(cpuData, memoryData, diskData, networkData) {
|
||||
}
|
||||
|
||||
// 计算接收总和(时间段内的累积值)
|
||||
if (Array.isArray(networkData.received) && networkData.received.length > 0) {
|
||||
if (Array.isArray(selectedNetworkData.received) && selectedNetworkData.received.length > 0) {
|
||||
// 排序接收数据
|
||||
const sortedReceived = sortDataByTime(networkData.received);
|
||||
const sortedReceived = sortDataByTime(selectedNetworkData.received);
|
||||
|
||||
// 计算累积接收总和(MB)
|
||||
let cumulativeReceived = 0;
|
||||
@@ -1644,12 +1669,21 @@ function updateCharts(cpuData, memoryData, diskData, networkData) {
|
||||
|
||||
charts.network.update();
|
||||
}
|
||||
}
|
||||
|
||||
// 更新网速趋势图表
|
||||
if (networkData && networkData.sent && networkData.received && charts.speed) {
|
||||
if (networkData && charts.speed) {
|
||||
let selectedNetworkData = networkData;
|
||||
|
||||
// 如果是按网卡分组的数据,选择当前选中的网卡数据
|
||||
if (typeof networkData === 'object' && networkData.sent === undefined && networkData.received === undefined) {
|
||||
selectedNetworkData = networkData[state.currentInterface] || networkData['all'] || {};
|
||||
}
|
||||
|
||||
if (selectedNetworkData.sent && selectedNetworkData.received) {
|
||||
// 更新发送流量
|
||||
if (Array.isArray(networkData.sent) && networkData.sent.length > 0) {
|
||||
const sortedData = sortDataByTime(networkData.sent);
|
||||
if (Array.isArray(selectedNetworkData.sent) && selectedNetworkData.sent.length > 0) {
|
||||
const sortedData = sortDataByTime(selectedNetworkData.sent);
|
||||
// 使用固定份数X轴数据计算
|
||||
const fixedPointsData = getFixedPointsData(sortedData);
|
||||
charts.speed.data.datasets[0].data = fixedPointsData.map(item => ({
|
||||
@@ -1659,8 +1693,8 @@ function updateCharts(cpuData, memoryData, diskData, networkData) {
|
||||
}
|
||||
|
||||
// 更新接收流量
|
||||
if (Array.isArray(networkData.received) && networkData.received.length > 0) {
|
||||
const sortedData = sortDataByTime(networkData.received);
|
||||
if (Array.isArray(selectedNetworkData.received) && selectedNetworkData.received.length > 0) {
|
||||
const sortedData = sortDataByTime(selectedNetworkData.received);
|
||||
// 使用固定份数X轴数据计算
|
||||
const fixedPointsData = getFixedPointsData(sortedData);
|
||||
charts.speed.data.datasets[1].data = fixedPointsData.map(item => ({
|
||||
@@ -1671,11 +1705,122 @@ function updateCharts(cpuData, memoryData, diskData, networkData) {
|
||||
|
||||
charts.speed.update();
|
||||
}
|
||||
}
|
||||
|
||||
// 更新网卡选择下拉框
|
||||
updateInterfaceDropdown(networkData);
|
||||
|
||||
// 初始化图表(如果尚未初始化)
|
||||
initDetailedCharts();
|
||||
}
|
||||
|
||||
// 更新网卡选择下拉框
|
||||
function updateInterfaceDropdown(networkData) {
|
||||
// 创建或获取网卡选择容器
|
||||
let interfaceContainer = document.getElementById('interfaceSelectorContainer');
|
||||
if (!interfaceContainer) {
|
||||
// 获取图表选项卡导航容器
|
||||
const chartTabs = document.getElementById('chartTabs');
|
||||
if (!chartTabs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建网卡选择容器
|
||||
interfaceContainer = document.createElement('div');
|
||||
interfaceContainer.id = 'interfaceSelectorContainer';
|
||||
interfaceContainer.className = 'flex items-center gap-2 ml-4';
|
||||
|
||||
// 创建标签
|
||||
const label = document.createElement('label');
|
||||
label.htmlFor = 'interfaceSelector';
|
||||
label.className = 'text-sm text-gray-600';
|
||||
label.textContent = '网卡:';
|
||||
|
||||
// 创建下拉框
|
||||
const select = document.createElement('select');
|
||||
select.id = 'interfaceSelector';
|
||||
select.className = 'px-3 py-1 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm';
|
||||
|
||||
// 添加默认选项
|
||||
const defaultOption = document.createElement('option');
|
||||
defaultOption.value = 'all';
|
||||
defaultOption.textContent = '所有网卡';
|
||||
select.appendChild(defaultOption);
|
||||
|
||||
// 添加事件监听
|
||||
select.addEventListener('change', (e) => {
|
||||
state.currentInterface = e.target.value;
|
||||
// 重新加载指标
|
||||
loadMetrics();
|
||||
});
|
||||
|
||||
// 组装容器
|
||||
interfaceContainer.appendChild(label);
|
||||
interfaceContainer.appendChild(select);
|
||||
|
||||
// 将容器添加到图表选项卡导航中
|
||||
const tabsContainer = chartTabs.querySelector('.flex.flex-wrap');
|
||||
if (tabsContainer) {
|
||||
tabsContainer.appendChild(interfaceContainer);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新下拉框选项
|
||||
const select = document.getElementById('interfaceSelector');
|
||||
if (select) {
|
||||
// 保存当前选中的值
|
||||
const currentValue = select.value;
|
||||
|
||||
// 清空现有选项
|
||||
select.innerHTML = '';
|
||||
|
||||
// 添加默认选项
|
||||
const defaultOption = document.createElement('option');
|
||||
defaultOption.value = 'all';
|
||||
defaultOption.textContent = '所有网卡';
|
||||
select.appendChild(defaultOption);
|
||||
|
||||
// 添加所有网卡选项
|
||||
// 检查是否有按网卡分组的网络数据
|
||||
if (typeof networkData === 'object' && networkData.sent === undefined && networkData.received === undefined) {
|
||||
// 获取所有网卡名称
|
||||
const interfaces = Object.keys(networkData);
|
||||
|
||||
// 添加所有网卡选项
|
||||
interfaces.forEach(iface => {
|
||||
// 只添加实际的网卡名称,不添加"all"选项
|
||||
if (iface !== 'all') {
|
||||
const option = document.createElement('option');
|
||||
option.value = iface;
|
||||
option.textContent = iface;
|
||||
select.appendChild(option);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 如果没有按网卡分组的数据,使用模拟网卡名称
|
||||
// 这里可以根据实际情况修改,比如从其他地方获取网卡名称列表
|
||||
const mockInterfaces = ['eth0', 'eth1', 'lo'];
|
||||
mockInterfaces.forEach(iface => {
|
||||
const option = document.createElement('option');
|
||||
option.value = iface;
|
||||
option.textContent = iface;
|
||||
select.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
// 恢复当前选中的值
|
||||
select.value = currentValue;
|
||||
}
|
||||
|
||||
// 检查当前选中的选项卡,如果不是"网络"或"网速",隐藏网卡选择下拉框
|
||||
const activeTab = document.querySelector('.chart-tab.active');
|
||||
if (activeTab && activeTab.dataset.tab !== 'network' && activeTab.dataset.tab !== 'speed') {
|
||||
interfaceContainer.classList.add('hidden');
|
||||
} else {
|
||||
interfaceContainer.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试重连WebSocket
|
||||
function attemptReconnect() {
|
||||
if (wsReconnectAttempts < wsMaxReconnectAttempts) {
|
||||
@@ -2073,6 +2218,17 @@ function initChartTabs() {
|
||||
if (activeContainer) {
|
||||
activeContainer.classList.remove('hidden');
|
||||
}
|
||||
|
||||
// 显示/隐藏网卡选择下拉框
|
||||
const interfaceContainer = document.getElementById('interfaceSelectorContainer');
|
||||
if (interfaceContainer) {
|
||||
// 只有在点击"网络"或"网速"选项卡时,显示网卡选择下拉框
|
||||
if (tabId === 'network' || tabId === 'speed') {
|
||||
interfaceContainer.classList.remove('hidden');
|
||||
} else {
|
||||
interfaceContainer.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
10
test_agent.json
Normal file
10
test_agent.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"server_url": "http://localhost:8080/api",
|
||||
"id": "test-agent",
|
||||
"name": "Test Agent",
|
||||
"device_id": "test-device",
|
||||
"token": "bb30bfaee01bf7b541bbefe422f72645",
|
||||
"interval": "5s",
|
||||
"debug": true,
|
||||
"api_port": 8081
|
||||
}
|
||||
11
test_metrics.sh
Executable file
11
test_metrics.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 测试发送单个指标对象
|
||||
echo "测试发送单个指标对象:"
|
||||
curl -v -X POST -H "Content-Type: application/json" -H "X-Device-ID: test-device" -H "X-Agent-Name: test-agent" -H "X-Device-Token: test-token" -d '{"cpu": 50.5, "memory": 30.2, "disk": {":/": 45.6}, "network": {"eth0": {"bytes_sent": 1000, "bytes_received": 2000}}}' http://localhost:8080/api/metrics/
|
||||
|
||||
echo "\n---\n"
|
||||
|
||||
# 测试发送指标数组
|
||||
echo "测试发送指标数组:"
|
||||
curl -v -X POST -H "Content-Type: application/json" -H "X-Device-ID: test-device" -H "X-Agent-Name: test-agent" -H "X-Device-Token: test-token" -d '[{"cpu": 50.5, "memory": 30.2, "disk": {":/": 45.6}, "network": {"eth0": {"bytes_sent": 1000, "bytes_received": 2000}}}, {"cpu": 60.5, "memory": 40.2, "disk": {":/": 55.6}, "network": {"eth0": {"bytes_sent": 2000, "bytes_received": 3000}}}]' http://localhost:8080/api/metrics/
|
||||
Reference in New Issue
Block a user