Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
61
plugins/inputs/temp/README.md
Normal file
61
plugins/inputs/temp/README.md
Normal file
|
@ -0,0 +1,61 @@
|
|||
# Temperature Input Plugin
|
||||
|
||||
The temp input plugin gather metrics on system temperature. This plugin is
|
||||
meant to be multi platform and uses platform specific collection methods.
|
||||
|
||||
Currently supports Linux and Windows.
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Read metrics about temperature
|
||||
[[inputs.temp]]
|
||||
## Desired output format (Linux only)
|
||||
## Available values are
|
||||
## v1 -- use pre-v1.22.4 sensor naming, e.g. coretemp_core0_input
|
||||
## v2 -- use v1.22.4+ sensor naming, e.g. coretemp_core_0_input
|
||||
# metric_format = "v2"
|
||||
|
||||
## Add device tag to distinguish devices with the same name (Linux only)
|
||||
# add_device_tag = false
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
- temp
|
||||
- tags:
|
||||
- sensor
|
||||
- fields:
|
||||
- temp (float, celcius)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
On **Windows**, the plugin uses a WMI call that is can be replicated with the
|
||||
following command:
|
||||
|
||||
```shell
|
||||
wmic /namespace:\\root\wmi PATH MSAcpi_ThermalZoneTemperature
|
||||
```
|
||||
|
||||
If the result is "Not Supported" you may be running in a virtualized environment
|
||||
and not a physical machine. Additionally, if you still get this result your
|
||||
motherboard or system may not support querying these values. Finally, you may
|
||||
be required to run as admin to get the values.
|
||||
|
||||
## Example Output
|
||||
|
||||
```text
|
||||
temp,sensor=coretemp_physicalid0_crit temp=100 1531298763000000000
|
||||
temp,sensor=coretemp_physicalid0_critalarm temp=0 1531298763000000000
|
||||
temp,sensor=coretemp_physicalid0_input temp=100 1531298763000000000
|
||||
temp,sensor=coretemp_physicalid0_max temp=100 1531298763000000000
|
||||
```
|
10
plugins/inputs/temp/sample.conf
Normal file
10
plugins/inputs/temp/sample.conf
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Read metrics about temperature
|
||||
[[inputs.temp]]
|
||||
## Desired output format (Linux only)
|
||||
## Available values are
|
||||
## v1 -- use pre-v1.22.4 sensor naming, e.g. coretemp_core0_input
|
||||
## v2 -- use v1.22.4+ sensor naming, e.g. coretemp_core_0_input
|
||||
# metric_format = "v2"
|
||||
|
||||
## Add device tag to distinguish devices with the same name (Linux only)
|
||||
# add_device_tag = false
|
28
plugins/inputs/temp/temp.go
Normal file
28
plugins/inputs/temp/temp.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package temp
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type Temperature struct {
|
||||
MetricFormat string `toml:"metric_format"`
|
||||
DeviceTag bool `toml:"add_device_tag"`
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
}
|
||||
|
||||
func (*Temperature) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("temp", func() telegraf.Input {
|
||||
return &Temperature{}
|
||||
})
|
||||
}
|
249
plugins/inputs/temp/temp_linux.go
Normal file
249
plugins/inputs/temp/temp_linux.go
Normal file
|
@ -0,0 +1,249 @@
|
|||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package temp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
)
|
||||
|
||||
const scalingFactor = float64(1000.0)
|
||||
|
||||
type temperatureStat struct {
|
||||
name string
|
||||
label string
|
||||
device string
|
||||
temperature float64
|
||||
additional map[string]interface{}
|
||||
}
|
||||
|
||||
func (t *Temperature) Init() error {
|
||||
switch t.MetricFormat {
|
||||
case "":
|
||||
t.MetricFormat = "v2"
|
||||
case "v1", "v2":
|
||||
// Do nothing as those are valid
|
||||
default:
|
||||
return fmt.Errorf("invalid 'metric_format' %q", t.MetricFormat)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Temperature) Gather(acc telegraf.Accumulator) error {
|
||||
// Get all sensors and honor the HOST_SYS environment variable
|
||||
path := internal.GetSysPath()
|
||||
|
||||
// Try to use the hwmon interface
|
||||
temperatures, err := t.gatherHwmon(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting temperatures failed: %w", err)
|
||||
}
|
||||
|
||||
if len(temperatures) == 0 {
|
||||
// There is no hwmon interface, fallback to thermal-zone parsing
|
||||
temperatures, err = t.gatherThermalZone(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting temperatures (via fallback) failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
switch t.MetricFormat {
|
||||
case "v1":
|
||||
t.createMetricsV1(acc, temperatures)
|
||||
case "v2":
|
||||
t.createMetricsV2(acc, temperatures)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Temperature) createMetricsV1(acc telegraf.Accumulator, temperatures []temperatureStat) {
|
||||
for _, temp := range temperatures {
|
||||
sensor := temp.name
|
||||
if temp.label != "" {
|
||||
sensor += "_" + strings.ReplaceAll(temp.label, " ", "")
|
||||
}
|
||||
|
||||
// Mandatory measurement value
|
||||
tags := map[string]string{"sensor": sensor + "_input"}
|
||||
if t.DeviceTag {
|
||||
tags["device"] = temp.device
|
||||
}
|
||||
acc.AddFields("temp", map[string]interface{}{"temp": temp.temperature}, tags)
|
||||
|
||||
// Optional values values
|
||||
for measurement, value := range temp.additional {
|
||||
tags := map[string]string{"sensor": sensor + "_" + measurement}
|
||||
if t.DeviceTag {
|
||||
tags["device"] = temp.device
|
||||
}
|
||||
acc.AddFields("temp", map[string]interface{}{"temp": value}, tags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Temperature) createMetricsV2(acc telegraf.Accumulator, temperatures []temperatureStat) {
|
||||
for _, temp := range temperatures {
|
||||
sensor := temp.name
|
||||
if temp.label != "" {
|
||||
sensor += "_" + strings.ReplaceAll(temp.label, " ", "_")
|
||||
}
|
||||
|
||||
// Mandatory measurement value
|
||||
tags := map[string]string{"sensor": sensor}
|
||||
if t.DeviceTag {
|
||||
tags["device"] = temp.device
|
||||
}
|
||||
acc.AddFields("temp", map[string]interface{}{"temp": temp.temperature}, tags)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Temperature) gatherHwmon(syspath string) ([]temperatureStat, error) {
|
||||
// Get all hwmon devices
|
||||
sensors, err := filepath.Glob(filepath.Join(syspath, "class", "hwmon", "hwmon*", "temp*_input"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting sensors failed: %w", err)
|
||||
}
|
||||
|
||||
// Handle CentOS special path containing an additional "device" directory
|
||||
// see https://github.com/shirou/gopsutil/blob/master/host/host_linux.go
|
||||
if len(sensors) == 0 {
|
||||
sensors, err = filepath.Glob(filepath.Join(syspath, "class", "hwmon", "hwmon*", "device", "temp*_input"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting sensors on CentOS failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Exit early if we cannot find any device
|
||||
if len(sensors) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Collect the sensor information
|
||||
stats := make([]temperatureStat, 0, len(sensors))
|
||||
for _, s := range sensors {
|
||||
// Get the sensor directory and the temperature prefix from the path
|
||||
path := filepath.Dir(s)
|
||||
prefix := strings.SplitN(filepath.Base(s), "_", 2)[0]
|
||||
|
||||
// Read the sensor and device name
|
||||
deviceName, err := os.Readlink(filepath.Join(path, "device"))
|
||||
if err == nil {
|
||||
deviceName = filepath.Base(deviceName)
|
||||
}
|
||||
|
||||
// Read the sensor name and use the device name as fallback
|
||||
name := deviceName
|
||||
n, err := os.ReadFile(filepath.Join(path, "name"))
|
||||
if err == nil {
|
||||
name = strings.TrimSpace(string(n))
|
||||
}
|
||||
|
||||
// Get the sensor label
|
||||
var label string
|
||||
if buf, err := os.ReadFile(filepath.Join(path, prefix+"_label")); err == nil {
|
||||
label = strings.TrimSpace(string(buf))
|
||||
}
|
||||
|
||||
// Do the actual sensor readings
|
||||
temp := temperatureStat{
|
||||
name: name,
|
||||
label: strings.ToLower(label),
|
||||
device: deviceName,
|
||||
additional: make(map[string]interface{}),
|
||||
}
|
||||
|
||||
// Temperature (mandatory)
|
||||
fn := filepath.Join(path, prefix+"_input")
|
||||
buf, err := os.ReadFile(fn)
|
||||
if err != nil {
|
||||
t.Log.Debugf("Couldn't read temperature from %q: %v", fn, err)
|
||||
continue
|
||||
}
|
||||
if v, err := strconv.ParseFloat(strings.TrimSpace(string(buf)), 64); err == nil {
|
||||
temp.temperature = v / scalingFactor
|
||||
}
|
||||
|
||||
// Read all possible values of the sensor
|
||||
matches, err := filepath.Glob(filepath.Join(path, prefix+"_*"))
|
||||
if err != nil {
|
||||
t.Log.Warnf("Couldn't read files from %q: %v", filepath.Join(path, prefix+"_*"), err)
|
||||
continue
|
||||
}
|
||||
for _, fn := range matches {
|
||||
buf, err = os.ReadFile(fn)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(filepath.Base(fn), "_", 2)
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
measurement := parts[1]
|
||||
|
||||
// Skip already added values
|
||||
switch measurement {
|
||||
case "label", "input":
|
||||
continue
|
||||
}
|
||||
|
||||
v, err := strconv.ParseFloat(strings.TrimSpace(string(buf)), 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
temp.additional[measurement] = v / scalingFactor
|
||||
}
|
||||
|
||||
stats = append(stats, temp)
|
||||
}
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func (t *Temperature) gatherThermalZone(syspath string) ([]temperatureStat, error) {
|
||||
// For file layout see https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt
|
||||
zones, err := filepath.Glob(filepath.Join(syspath, "class", "thermal", "thermal_zone*"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting thermal zones failed: %w", err)
|
||||
}
|
||||
|
||||
// Exit early if we cannot find any zone
|
||||
if len(zones) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Collect the sensor information
|
||||
stats := make([]temperatureStat, 0, len(zones))
|
||||
for _, path := range zones {
|
||||
// Type of the zone corresponding to the sensor name in our nomenclature
|
||||
buf, err := os.ReadFile(filepath.Join(path, "type"))
|
||||
if err != nil {
|
||||
t.Log.Errorf("Cannot read name of zone %q", path)
|
||||
continue
|
||||
}
|
||||
name := strings.TrimSpace(string(buf))
|
||||
|
||||
// Actual temperature
|
||||
buf, err = os.ReadFile(filepath.Join(path, "temp"))
|
||||
if err != nil {
|
||||
t.Log.Errorf("Cannot read temperature of zone %q", path)
|
||||
continue
|
||||
}
|
||||
v, err := strconv.ParseFloat(strings.TrimSpace(string(buf)), 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
temp := temperatureStat{name: name, temperature: v / scalingFactor}
|
||||
stats = append(stats, temp)
|
||||
}
|
||||
|
||||
return stats, nil
|
||||
}
|
47
plugins/inputs/temp/temp_notlinux.go
Normal file
47
plugins/inputs/temp/temp_notlinux.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package temp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/v4/sensors"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
)
|
||||
|
||||
func (t *Temperature) Init() error {
|
||||
if t.MetricFormat != "" {
|
||||
t.Log.Warn("Ignoring 'metric_format' on non-Linux platforms!")
|
||||
}
|
||||
|
||||
if t.DeviceTag {
|
||||
t.Log.Warn("Ignoring 'add_device_tag' on non-Linux platforms!")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*Temperature) Gather(acc telegraf.Accumulator) error {
|
||||
temps, err := sensors.SensorsTemperatures()
|
||||
if err != nil {
|
||||
var sensorsWarnings *sensors.Warnings
|
||||
if !errors.As(err, &sensorsWarnings) {
|
||||
if strings.Contains(err.Error(), "not implemented yet") {
|
||||
return fmt.Errorf("plugin is not supported on this platform: %w", err)
|
||||
}
|
||||
return fmt.Errorf("getting temperatures failed: %w", err)
|
||||
}
|
||||
}
|
||||
for _, temp := range temps {
|
||||
acc.AddFields(
|
||||
"temp",
|
||||
map[string]interface{}{"temp": temp.Temperature},
|
||||
map[string]string{"sensor": temp.SensorKey},
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
344
plugins/inputs/temp/temp_test.go
Normal file
344
plugins/inputs/temp/temp_test.go
Normal file
|
@ -0,0 +1,344 @@
|
|||
//go:build linux
|
||||
|
||||
package temp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/shirou/gopsutil/v4/sensors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
"github.com/influxdata/telegraf/plugins/parsers/influx"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func TestDefaultMetricFormat(t *testing.T) {
|
||||
plugin := &Temperature{
|
||||
Log: &testutil.Logger{},
|
||||
}
|
||||
require.NoError(t, plugin.Init())
|
||||
require.Equal(t, "v2", plugin.MetricFormat)
|
||||
}
|
||||
|
||||
func TestInvalidMetricFormat(t *testing.T) {
|
||||
plugin := &Temperature{
|
||||
MetricFormat: "foo",
|
||||
Log: &testutil.Logger{},
|
||||
}
|
||||
require.ErrorContains(t, plugin.Init(), "invalid 'metric_format'")
|
||||
}
|
||||
|
||||
func TestNameCollisions(t *testing.T) {
|
||||
t.Setenv("HOST_SYS", filepath.Join("testcases", "with_name", "sys"))
|
||||
|
||||
plugin := &Temperature{Log: &testutil.Logger{}}
|
||||
require.NoError(t, plugin.Init())
|
||||
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, plugin.Gather(&acc))
|
||||
require.Len(t, acc.GetTelegrafMetrics(), 8)
|
||||
}
|
||||
|
||||
func TestCases(t *testing.T) {
|
||||
// Get all directories in testdata
|
||||
folders, err := os.ReadDir("testcases")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Register the plugin
|
||||
inputs.Add("temp", func() telegraf.Input {
|
||||
return &Temperature{}
|
||||
})
|
||||
|
||||
// Prepare the influx parser for expectations
|
||||
parser := &influx.Parser{}
|
||||
require.NoError(t, parser.Init())
|
||||
|
||||
for _, f := range folders {
|
||||
// Only handle folders
|
||||
if !f.IsDir() {
|
||||
continue
|
||||
}
|
||||
// Compare options
|
||||
options := []cmp.Option{
|
||||
testutil.IgnoreTime(),
|
||||
testutil.SortMetrics(),
|
||||
}
|
||||
|
||||
// Test v1
|
||||
t.Run(f.Name()+"_v1", func(t *testing.T) {
|
||||
testcasePath := filepath.Join("testcases", f.Name())
|
||||
configFilename := filepath.Join(testcasePath, "telegraf.conf")
|
||||
expectedFilename := filepath.Join(testcasePath, "expected_v1.out")
|
||||
|
||||
// Read the expected output if any
|
||||
var expected []telegraf.Metric
|
||||
if _, err := os.Stat(expectedFilename); err == nil {
|
||||
var err error
|
||||
expected, err = testutil.ParseMetricsFromFile(expectedFilename, parser)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Prepare the environment
|
||||
t.Setenv("HOST_SYS", filepath.Join(testcasePath, "sys"))
|
||||
|
||||
// Configure the plugin
|
||||
cfg := config.NewConfig()
|
||||
require.NoError(t, cfg.LoadConfig(configFilename))
|
||||
require.Len(t, cfg.Inputs, 1)
|
||||
plugin := cfg.Inputs[0].Input.(*Temperature)
|
||||
plugin.MetricFormat = "v1"
|
||||
require.NoError(t, plugin.Init())
|
||||
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, plugin.Gather(&acc))
|
||||
|
||||
// Check the metric nevertheless as we might get some metrics despite errors.
|
||||
actual := acc.GetTelegrafMetrics()
|
||||
testutil.RequireMetricsEqual(t, expected, actual, options...)
|
||||
})
|
||||
|
||||
// Test v2
|
||||
t.Run(f.Name()+"_v2", func(t *testing.T) {
|
||||
testcasePath := filepath.Join("testcases", f.Name())
|
||||
configFilename := filepath.Join(testcasePath, "telegraf.conf")
|
||||
expectedFilename := filepath.Join(testcasePath, "expected_v2.out")
|
||||
|
||||
// Read the expected output if any
|
||||
var expected []telegraf.Metric
|
||||
if _, err := os.Stat(expectedFilename); err == nil {
|
||||
var err error
|
||||
expected, err = testutil.ParseMetricsFromFile(expectedFilename, parser)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Prepare the environment
|
||||
t.Setenv("HOST_SYS", filepath.Join(testcasePath, "sys"))
|
||||
|
||||
// Configure the plugin
|
||||
cfg := config.NewConfig()
|
||||
require.NoError(t, cfg.LoadConfig(configFilename))
|
||||
require.Len(t, cfg.Inputs, 1)
|
||||
plugin := cfg.Inputs[0].Input.(*Temperature)
|
||||
plugin.MetricFormat = "v2"
|
||||
require.NoError(t, plugin.Init())
|
||||
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, plugin.Gather(&acc))
|
||||
|
||||
// Check the metric nevertheless as we might get some metrics despite errors.
|
||||
actual := acc.GetTelegrafMetrics()
|
||||
testutil.RequireMetricsEqual(t, expected, actual, options...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegression(t *testing.T) {
|
||||
// Get all directories in testdata
|
||||
folders, err := os.ReadDir("testcases")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Register the plugin
|
||||
inputs.Add("temp", func() telegraf.Input {
|
||||
return &Temperature{}
|
||||
})
|
||||
|
||||
// Prepare the influx parser for expectations
|
||||
parser := &influx.Parser{}
|
||||
require.NoError(t, parser.Init())
|
||||
|
||||
for _, f := range folders {
|
||||
// Only handle folders
|
||||
if !f.IsDir() {
|
||||
continue
|
||||
}
|
||||
// Compare options
|
||||
options := []cmp.Option{
|
||||
testutil.IgnoreTime(),
|
||||
testutil.SortMetrics(),
|
||||
}
|
||||
|
||||
// Test v1 metrics
|
||||
t.Run(f.Name()+"_v1", func(t *testing.T) {
|
||||
testcasePath := filepath.Join("testcases", f.Name())
|
||||
actualFilename := filepath.Join(testcasePath, "expected_v1.out")
|
||||
|
||||
// Read the expected output if any
|
||||
var actual []telegraf.Metric
|
||||
if _, err := os.Stat(actualFilename); err == nil {
|
||||
var err error
|
||||
actual, err = testutil.ParseMetricsFromFile(actualFilename, parser)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Remove potential device-tags
|
||||
for i := range actual {
|
||||
actual[i].RemoveTag("device")
|
||||
}
|
||||
|
||||
// Use the <v1.22.4 code to compare against
|
||||
temps, err := sensorsTemperaturesOld(filepath.Join(testcasePath, "sys"))
|
||||
require.NoError(t, err)
|
||||
|
||||
var acc testutil.Accumulator
|
||||
for _, temp := range temps {
|
||||
tags := map[string]string{
|
||||
"sensor": temp.SensorKey,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"temp": temp.Temperature,
|
||||
}
|
||||
acc.AddFields("temp", fields, tags)
|
||||
}
|
||||
|
||||
expected := acc.GetTelegrafMetrics()
|
||||
testutil.RequireMetricsEqual(t, expected, actual, options...)
|
||||
})
|
||||
|
||||
// Test v2 metrics
|
||||
t.Run(f.Name()+"_v2", func(t *testing.T) {
|
||||
testcasePath := filepath.Join("testcases", f.Name())
|
||||
actualFilename := filepath.Join(testcasePath, "expected_v2.out")
|
||||
|
||||
// Read the expected output if any
|
||||
var actual []telegraf.Metric
|
||||
if _, err := os.Stat(actualFilename); err == nil {
|
||||
var err error
|
||||
actual, err = testutil.ParseMetricsFromFile(actualFilename, parser)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Remove potential device-tags
|
||||
for i := range actual {
|
||||
actual[i].RemoveTag("device")
|
||||
}
|
||||
|
||||
// Prepare the environment
|
||||
t.Setenv("HOST_SYS", filepath.Join(testcasePath, "sys"))
|
||||
|
||||
// Use the v1.28.x code to compare against
|
||||
var acc testutil.Accumulator
|
||||
temps, err := sensors.SensorsTemperatures()
|
||||
require.NoError(t, err)
|
||||
for _, temp := range temps {
|
||||
tags := map[string]string{
|
||||
"sensor": temp.SensorKey,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"temp": temp.Temperature,
|
||||
}
|
||||
acc.AddFields("temp", fields, tags)
|
||||
}
|
||||
|
||||
expected := acc.GetTelegrafMetrics()
|
||||
testutil.RequireMetricsEqual(t, expected, actual, options...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func sensorsTemperaturesOld(syspath string) ([]sensors.TemperatureStat, error) {
|
||||
files, err := filepath.Glob(syspath + "/class/hwmon/hwmon*/temp*_*")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(files) == 0 {
|
||||
// CentOS has an intermediate /device directory:
|
||||
// https://github.com/giampaolo/psutil/issues/971
|
||||
files, err = filepath.Glob(syspath + "/class/hwmon/hwmon*/device/temp*_*")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files
|
||||
files, err = filepath.Glob(syspath + "/class/thermal/thermal_zone*/")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
temperatures := make([]sensors.TemperatureStat, 0, len(files))
|
||||
for _, file := range files {
|
||||
// Get the name of the temperature you are reading
|
||||
name, err := os.ReadFile(filepath.Join(file, "type"))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
// Get the temperature reading
|
||||
current, err := os.ReadFile(filepath.Join(file, "temp"))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
temperature, err := strconv.ParseInt(strings.TrimSpace(string(current)), 10, 64)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
|
||||
temperatures = append(temperatures, sensors.TemperatureStat{
|
||||
SensorKey: strings.TrimSpace(string(name)),
|
||||
Temperature: float64(temperature) / 1000.0,
|
||||
})
|
||||
}
|
||||
return temperatures, nil
|
||||
}
|
||||
|
||||
// example directory
|
||||
// device/ temp1_crit_alarm temp2_crit_alarm temp3_crit_alarm temp4_crit_alarm temp5_crit_alarm temp6_crit_alarm temp7_crit_alarm
|
||||
// name temp1_input temp2_input temp3_input temp4_input temp5_input temp6_input temp7_input
|
||||
// power/ temp1_label temp2_label temp3_label temp4_label temp5_label temp6_label temp7_label
|
||||
// subsystem/ temp1_max temp2_max temp3_max temp4_max temp5_max temp6_max temp7_max
|
||||
// temp1_crit temp2_crit temp3_crit temp4_crit temp5_crit temp6_crit temp7_crit uevent
|
||||
temperatures := make([]sensors.TemperatureStat, 0, len(files))
|
||||
for _, file := range files {
|
||||
filename := strings.Split(filepath.Base(file), "_")
|
||||
if filename[1] == "label" {
|
||||
// Do not try to read the temperature of the label file
|
||||
continue
|
||||
}
|
||||
|
||||
// Get the label of the temperature you are reading
|
||||
var label string
|
||||
//nolint:errcheck // skip on error
|
||||
c, _ := os.ReadFile(filepath.Join(filepath.Dir(file), filename[0]+"_label"))
|
||||
if c != nil {
|
||||
// format the label from "Core 0" to "core0_"
|
||||
label = strings.Join(strings.Split(strings.TrimSpace(strings.ToLower(string(c))), " "), "") + "_"
|
||||
}
|
||||
|
||||
// Get the name of the temperature you are reading
|
||||
name, err := os.ReadFile(filepath.Join(filepath.Dir(file), "name"))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Get the temperature reading
|
||||
current, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
temperature, err := strconv.ParseFloat(strings.TrimSpace(string(current)), 64)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
|
||||
tempName := strings.TrimSpace(strings.ToLower(strings.Join(filename[1:], "")))
|
||||
temperatures = append(temperatures, sensors.TemperatureStat{
|
||||
SensorKey: fmt.Sprintf("%s_%s%s", strings.TrimSpace(string(name)), label, tempName),
|
||||
Temperature: temperature / 1000.0,
|
||||
})
|
||||
}
|
||||
return temperatures, nil
|
||||
}
|
13
plugins/inputs/temp/testcases/general/expected_v1.out
Normal file
13
plugins/inputs/temp/testcases/general/expected_v1.out
Normal file
|
@ -0,0 +1,13 @@
|
|||
temp,sensor=nvme_composite_input temp=35.85
|
||||
temp,sensor=nvme_composite_alarm temp=0
|
||||
temp,sensor=nvme_composite_crit temp=84.85
|
||||
temp,sensor=nvme_composite_max temp=81.85
|
||||
temp,sensor=nvme_composite_min temp=-273.15
|
||||
temp,sensor=nvme_sensor1_input temp=35.85
|
||||
temp,sensor=nvme_sensor1_min temp=-273.15
|
||||
temp,sensor=nvme_sensor1_max temp=65261.85
|
||||
temp,sensor=nvme_sensor2_input temp=38.85
|
||||
temp,sensor=nvme_sensor2_max temp=65261.85
|
||||
temp,sensor=nvme_sensor2_min temp=-273.15
|
||||
temp,sensor=k10temp_tctl_input temp=33.25
|
||||
temp,sensor=k10temp_tccd1_input temp=33.25
|
5
plugins/inputs/temp/testcases/general/expected_v2.out
Normal file
5
plugins/inputs/temp/testcases/general/expected_v2.out
Normal file
|
@ -0,0 +1,5 @@
|
|||
temp,sensor=nvme_composite temp=35.85
|
||||
temp,sensor=nvme_sensor_1 temp=35.85
|
||||
temp,sensor=nvme_sensor_2 temp=38.85
|
||||
temp,sensor=k10temp_tctl temp=33.25
|
||||
temp,sensor=k10temp_tccd1 temp=33.25
|
|
@ -0,0 +1 @@
|
|||
nvme
|
|
@ -0,0 +1 @@
|
|||
0
|
|
@ -0,0 +1 @@
|
|||
84850
|
|
@ -0,0 +1 @@
|
|||
35850
|
|
@ -0,0 +1 @@
|
|||
Composite
|
|
@ -0,0 +1 @@
|
|||
81850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
35850
|
|
@ -0,0 +1 @@
|
|||
Sensor 1
|
|
@ -0,0 +1 @@
|
|||
65261850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
38850
|
|
@ -0,0 +1 @@
|
|||
Sensor 2
|
|
@ -0,0 +1 @@
|
|||
65261850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
k10temp
|
|
@ -0,0 +1 @@
|
|||
33250
|
|
@ -0,0 +1 @@
|
|||
Tctl
|
|
@ -0,0 +1 @@
|
|||
33250
|
|
@ -0,0 +1 @@
|
|||
Tccd1
|
2
plugins/inputs/temp/testcases/general/telegraf.conf
Normal file
2
plugins/inputs/temp/testcases/general/telegraf.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
[[inputs.temp]]
|
||||
# Metric format will be set in the code
|
|
@ -0,0 +1,24 @@
|
|||
temp,device=nvme0,sensor=nvme_composite_input temp=32.85
|
||||
temp,device=nvme0,sensor=nvme_composite_alarm temp=0
|
||||
temp,device=nvme0,sensor=nvme_composite_crit temp=84.85
|
||||
temp,device=nvme0,sensor=nvme_composite_max temp=81.85
|
||||
temp,device=nvme0,sensor=nvme_composite_min temp=-273.15
|
||||
temp,device=nvme0,sensor=nvme_sensor1_input temp=32.85
|
||||
temp,device=nvme0,sensor=nvme_sensor1_max temp=65261.85
|
||||
temp,device=nvme0,sensor=nvme_sensor1_min temp=-273.15
|
||||
temp,device=nvme0,sensor=nvme_sensor2_input temp=36.85
|
||||
temp,device=nvme0,sensor=nvme_sensor2_max temp=65261.85
|
||||
temp,device=nvme0,sensor=nvme_sensor2_min temp=-273.15
|
||||
temp,device=nvme1,sensor=nvme_composite_input temp=35.85
|
||||
temp,device=nvme1,sensor=nvme_composite_alarm temp=0
|
||||
temp,device=nvme1,sensor=nvme_composite_crit temp=84.85
|
||||
temp,device=nvme1,sensor=nvme_composite_max temp=81.85
|
||||
temp,device=nvme1,sensor=nvme_composite_min temp=-273.15
|
||||
temp,device=nvme1,sensor=nvme_sensor1_input temp=35.85
|
||||
temp,device=nvme1,sensor=nvme_sensor1_max temp=65261.85
|
||||
temp,device=nvme1,sensor=nvme_sensor1_min temp=-273.15
|
||||
temp,device=nvme1,sensor=nvme_sensor2_input temp=37.85
|
||||
temp,device=nvme1,sensor=nvme_sensor2_max temp=65261.85
|
||||
temp,device=nvme1,sensor=nvme_sensor2_min temp=-273.15
|
||||
temp,device=0000:00:18.3,sensor=k10temp_tctl_input temp=31.875
|
||||
temp,device=0000:00:18.3,sensor=k10temp_tccd1_input temp=30.75
|
|
@ -0,0 +1,8 @@
|
|||
temp,device=nvme0,sensor=nvme_composite temp=32.85
|
||||
temp,device=nvme0,sensor=nvme_sensor_1 temp=32.85
|
||||
temp,device=nvme0,sensor=nvme_sensor_2 temp=36.85
|
||||
temp,device=nvme1,sensor=nvme_composite temp=35.85
|
||||
temp,device=nvme1,sensor=nvme_sensor_1 temp=35.85
|
||||
temp,device=nvme1,sensor=nvme_sensor_2 temp=37.85
|
||||
temp,device=0000:00:18.3,sensor=k10temp_tctl temp=31.875
|
||||
temp,device=0000:00:18.3,sensor=k10temp_tccd1 temp=30.75
|
|
@ -0,0 +1 @@
|
|||
../../nvme0/
|
|
@ -0,0 +1 @@
|
|||
nvme
|
|
@ -0,0 +1 @@
|
|||
0
|
|
@ -0,0 +1 @@
|
|||
84850
|
|
@ -0,0 +1 @@
|
|||
32850
|
|
@ -0,0 +1 @@
|
|||
Composite
|
|
@ -0,0 +1 @@
|
|||
81850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
32850
|
|
@ -0,0 +1 @@
|
|||
Sensor 1
|
|
@ -0,0 +1 @@
|
|||
65261850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
36850
|
|
@ -0,0 +1 @@
|
|||
Sensor 2
|
|
@ -0,0 +1 @@
|
|||
65261850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
../../nvme1/
|
|
@ -0,0 +1 @@
|
|||
nvme
|
|
@ -0,0 +1 @@
|
|||
0
|
|
@ -0,0 +1 @@
|
|||
84850
|
|
@ -0,0 +1 @@
|
|||
35850
|
|
@ -0,0 +1 @@
|
|||
Composite
|
|
@ -0,0 +1 @@
|
|||
81850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
35850
|
|
@ -0,0 +1 @@
|
|||
Sensor 1
|
|
@ -0,0 +1 @@
|
|||
65261850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
37850
|
|
@ -0,0 +1 @@
|
|||
Sensor 2
|
|
@ -0,0 +1 @@
|
|||
65261850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
../../../0000:00:18.3/
|
|
@ -0,0 +1 @@
|
|||
k10temp
|
|
@ -0,0 +1 @@
|
|||
31875
|
|
@ -0,0 +1 @@
|
|||
Tctl
|
|
@ -0,0 +1 @@
|
|||
30750
|
|
@ -0,0 +1 @@
|
|||
Tccd1
|
|
@ -0,0 +1,3 @@
|
|||
[[inputs.temp]]
|
||||
add_device_tag = true
|
||||
# Metric format will be set in the code
|
24
plugins/inputs/temp/testcases/with_name/expected_v1.out
Normal file
24
plugins/inputs/temp/testcases/with_name/expected_v1.out
Normal file
|
@ -0,0 +1,24 @@
|
|||
temp,sensor=nvme_composite_input temp=32.85
|
||||
temp,sensor=nvme_composite_alarm temp=0
|
||||
temp,sensor=nvme_composite_crit temp=84.85
|
||||
temp,sensor=nvme_composite_max temp=81.85
|
||||
temp,sensor=nvme_composite_min temp=-273.15
|
||||
temp,sensor=nvme_sensor1_input temp=32.85
|
||||
temp,sensor=nvme_sensor1_max temp=65261.85
|
||||
temp,sensor=nvme_sensor1_min temp=-273.15
|
||||
temp,sensor=nvme_sensor2_input temp=36.85
|
||||
temp,sensor=nvme_sensor2_max temp=65261.85
|
||||
temp,sensor=nvme_sensor2_min temp=-273.15
|
||||
temp,sensor=nvme_composite_input temp=35.85
|
||||
temp,sensor=nvme_composite_alarm temp=0
|
||||
temp,sensor=nvme_composite_crit temp=84.85
|
||||
temp,sensor=nvme_composite_max temp=81.85
|
||||
temp,sensor=nvme_composite_min temp=-273.15
|
||||
temp,sensor=nvme_sensor1_input temp=35.85
|
||||
temp,sensor=nvme_sensor1_max temp=65261.85
|
||||
temp,sensor=nvme_sensor1_min temp=-273.15
|
||||
temp,sensor=nvme_sensor2_input temp=37.85
|
||||
temp,sensor=nvme_sensor2_max temp=65261.85
|
||||
temp,sensor=nvme_sensor2_min temp=-273.15
|
||||
temp,sensor=k10temp_tctl_input temp=31.875
|
||||
temp,sensor=k10temp_tccd1_input temp=30.75
|
8
plugins/inputs/temp/testcases/with_name/expected_v2.out
Normal file
8
plugins/inputs/temp/testcases/with_name/expected_v2.out
Normal file
|
@ -0,0 +1,8 @@
|
|||
temp,sensor=nvme_composite temp=32.85
|
||||
temp,sensor=nvme_sensor_1 temp=32.85
|
||||
temp,sensor=nvme_sensor_2 temp=36.85
|
||||
temp,sensor=nvme_composite temp=35.85
|
||||
temp,sensor=nvme_sensor_1 temp=35.85
|
||||
temp,sensor=nvme_sensor_2 temp=37.85
|
||||
temp,sensor=k10temp_tctl temp=31.875
|
||||
temp,sensor=k10temp_tccd1 temp=30.75
|
|
@ -0,0 +1 @@
|
|||
../../nvme0/
|
|
@ -0,0 +1 @@
|
|||
nvme
|
|
@ -0,0 +1 @@
|
|||
0
|
|
@ -0,0 +1 @@
|
|||
84850
|
|
@ -0,0 +1 @@
|
|||
32850
|
|
@ -0,0 +1 @@
|
|||
Composite
|
|
@ -0,0 +1 @@
|
|||
81850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
32850
|
|
@ -0,0 +1 @@
|
|||
Sensor 1
|
|
@ -0,0 +1 @@
|
|||
65261850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
36850
|
|
@ -0,0 +1 @@
|
|||
Sensor 2
|
|
@ -0,0 +1 @@
|
|||
65261850
|
|
@ -0,0 +1 @@
|
|||
-273150
|
|
@ -0,0 +1 @@
|
|||
../../nvme1/
|
|
@ -0,0 +1 @@
|
|||
nvme
|
|
@ -0,0 +1 @@
|
|||
0
|
|
@ -0,0 +1 @@
|
|||
84850
|
|
@ -0,0 +1 @@
|
|||
35850
|
|
@ -0,0 +1 @@
|
|||
Composite
|
|
@ -0,0 +1 @@
|
|||
81850
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue