From dd76886d51ab9ccd59878fab2d0d92bcfadb30e4 Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Thu, 15 Jan 2026 10:06:58 +0800 Subject: [PATCH] fix(host): compatible with telegraf 1.36 and add ipmi_sensor conf (#24082) * fix(host): compatible with telegraf 1.36 and add ipmi_sensor conf * feat(monitor): add ipmi_sensor metric --- pkg/hostman/hostmetrics/container_metrics.go | 20 ++++++++--- pkg/hostman/system_service/telegraf.go | 24 +++++++++++++ pkg/monitor/dbinit/measurements/all.go | 1 + .../dbinit/measurements/ipmi_sensor.go | 35 +++++++++++++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 pkg/monitor/dbinit/measurements/ipmi_sensor.go diff --git a/pkg/hostman/hostmetrics/container_metrics.go b/pkg/hostman/hostmetrics/container_metrics.go index 80c63b33f7..45e5eaa9f8 100644 --- a/pkg/hostman/hostmetrics/container_metrics.go +++ b/pkg/hostman/hostmetrics/container_metrics.go @@ -686,10 +686,22 @@ func (m *SGuestMonitor) getCadvisorDiskIoMetrics(cur stats.DiskIoStats, prev map if diffTime > 0 && prev != nil { prevStat, ok := prev[devName] if ok { - devR.ReadBPS = float64(stat.ReadBytes-prevStat.ReadBytes) / diffTime - devR.WriteBPS = float64(stat.WriteBytes-prevStat.WriteBytes) / diffTime - devR.ReadIOPS = float64(stat.ReadCount-prevStat.ReadCount) / diffTime - devR.WriteIOPS = float64(stat.WriteCount-prevStat.WriteCount) / diffTime + // 检查计数器是否回退(可能是容器重启导致) + if stat.ReadCount < prevStat.ReadCount || stat.WriteCount < prevStat.WriteCount || + stat.ReadBytes < prevStat.ReadBytes || stat.WriteBytes < prevStat.WriteBytes { + log.Warningf("Disk IO counters decreased: guest=%s(%s), device=%s, ReadCount %d -> %d, WriteCount %d -> %d, ReadBytes %d -> %d, WriteBytes %d -> %d. Possible container restart, skipping rate calculation.", + m.Name, m.Id, devName, + prevStat.ReadCount, stat.ReadCount, + prevStat.WriteCount, stat.WriteCount, + prevStat.ReadBytes, stat.ReadBytes, + prevStat.WriteBytes, stat.WriteBytes) + // 跳过计算,避免产生负值 + } else { + devR.ReadBPS = float64(stat.ReadBytes-prevStat.ReadBytes) / diffTime + devR.WriteBPS = float64(stat.WriteBytes-prevStat.WriteBytes) / diffTime + devR.ReadIOPS = float64(stat.ReadCount-prevStat.ReadCount) / diffTime + devR.WriteIOPS = float64(stat.WriteCount-prevStat.WriteCount) / diffTime + } } } ret[devName] = devR diff --git a/pkg/hostman/system_service/telegraf.go b/pkg/hostman/system_service/telegraf.go index 0e1f99e537..568e0f999c 100644 --- a/pkg/hostman/system_service/telegraf.go +++ b/pkg/hostman/system_service/telegraf.go @@ -295,6 +295,7 @@ func (s *STelegraf) GetConfig(kwargs map[string]interface{}) string { conf += "[[inputs.http_listener_v2]]\n" conf += " service_address = \"localhost:8087\"\n" conf += " path = \"/write\"\n" + conf += " paths = [\"/write\"]\n" // Compatible with telegraf v1.36 conf += " data_source = \"body\"\n" conf += " data_format = \"influx\"\n" conf += "\n" @@ -341,6 +342,14 @@ func (s *STelegraf) GetConfig(kwargs map[string]interface{}) string { conf += "\n" } + // 检查 IPMI 设备文件是否存在 + if hasIPMIDevice() { + conf += "[[inputs.ipmi_sensor]]\n" + conf += " metric_version = 2\n" + conf += " sensors = [\"sdr\"]\n" + conf += "\n" + } + return conf } @@ -425,3 +434,18 @@ func (s *STelegraf) reloadTelegrafByHTTP() error { } return nil } + +// hasIPMIDevice 检查 IPMI 设备文件是否存在 +func hasIPMIDevice() bool { + ipmiDevices := []string{ + "/dev/ipmi0", + "/dev/ipmi/0", + "/dev/ipmidev/0", + } + for _, device := range ipmiDevices { + if _, err := os.Stat(device); err == nil { + return true + } + } + return false +} diff --git a/pkg/monitor/dbinit/measurements/all.go b/pkg/monitor/dbinit/measurements/all.go index 4df96b04a0..a74373ee99 100644 --- a/pkg/monitor/dbinit/measurements/all.go +++ b/pkg/monitor/dbinit/measurements/all.go @@ -109,6 +109,7 @@ var All = []SMeasurement{ redisKeyspace, sensors, + ipmiSensor, smartctl, diff --git a/pkg/monitor/dbinit/measurements/ipmi_sensor.go b/pkg/monitor/dbinit/measurements/ipmi_sensor.go new file mode 100644 index 0000000000..8cf25220f8 --- /dev/null +++ b/pkg/monitor/dbinit/measurements/ipmi_sensor.go @@ -0,0 +1,35 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package measurements + +import "yunion.io/x/onecloud/pkg/apis/monitor" + +var ipmiSensor = SMeasurement{ + Context: []SMonitorContext{ + { + Name: "ipmi_sensor", + DisplayName: "IPMI sensor", + ResourceType: monitor.METRIC_RES_TYPE_HOST, + Database: monitor.METRIC_DATABASE_TELE, + }, + }, + Metrics: []SMetric{ + { + Name: "value", + DisplayName: "Sensor value", + Unit: monitor.METRIC_UNIT_NULL, + }, + }, +}