From 9cebeb55827fe3387a47282bbb0b07aba46a7f35 Mon Sep 17 00:00:00 2001 From: Joshua Powers Date: Tue, 19 Apr 2022 15:07:23 -0600 Subject: [PATCH] fix: correctly parse various numeric forms (#10923) --- plugins/inputs/smart/smart.go | 20 +- plugins/inputs/smart/smart_test.go | 333 +++++++++++++++++++++++++++++ 2 files changed, 350 insertions(+), 3 deletions(-) diff --git a/plugins/inputs/smart/smart.go b/plugins/inputs/smart/smart.go index d8f8917506cc7..4064c0ffbb928 100644 --- a/plugins/inputs/smart/smart.go +++ b/plugins/inputs/smart/smart.go @@ -822,6 +822,7 @@ func (m *Smart) gatherDisk(acc telegraf.Accumulator, device string, wg *sync.Wai } if err := parse(fields, deviceFields, matches[2]); err != nil { + acc.AddError(fmt.Errorf("error parsing %s: '%s': %s", attr.Name, matches[2], err.Error())) continue } // if the field is classified as an attribute, only add it @@ -969,8 +970,20 @@ func parseInt(str string) int64 { } func parseCommaSeparatedInt(fields, _ map[string]interface{}, str string) error { - str = strings.Join(strings.Fields(str), "") - i, err := strconv.ParseInt(strings.Replace(str, ",", "", -1), 10, 64) + // remove any non-utf8 values + // '1\xa0292' --> 1292 + value := strings.ToValidUTF8(strings.Join(strings.Fields(str), ""), "") + + // remove any non-alphanumeric values + // '16,626,888' --> 16626888 + // '16 829 004' --> 16829004 + numRegex, err := regexp.Compile(`[^0-9\-]+`) + if err != nil { + return fmt.Errorf("failed to compile numeric regex") + } + value = numRegex.ReplaceAllString(value, "") + + i, err := strconv.ParseInt(value, 10, 64) if err != nil { return err } @@ -985,7 +998,8 @@ func parsePercentageInt(fields, deviceFields map[string]interface{}, str string) } func parseDataUnits(fields, deviceFields map[string]interface{}, str string) error { - units := strings.Fields(str)[0] + // Remove everything after '[' + units := strings.Split(str, "[")[0] return parseCommaSeparatedInt(fields, deviceFields, units) } diff --git a/plugins/inputs/smart/smart_test.go b/plugins/inputs/smart/smart_test.go index 6801ca764afa5..c7d1f3ffe348c 100644 --- a/plugins/inputs/smart/smart_test.go +++ b/plugins/inputs/smart/smart_test.go @@ -313,6 +313,24 @@ func TestGatherNVMe(t *testing.T) { testutil.SortMetrics(), testutil.IgnoreTime()) } +func TestGatherNVMeWindows(t *testing.T) { + runCmd = func(timeout config.Duration, sudo bool, command string, args ...string) ([]byte, error) { + return []byte(smartctlNVMeInfoDataWindows), nil + } + + var ( + acc = &testutil.Accumulator{} + wg = &sync.WaitGroup{} + ) + + wg.Add(1) + sampleSmart.gatherDisk(acc, "nvme0", wg) + + metrics := acc.GetTelegrafMetrics() + testutil.RequireMetricsEqual(t, testSmartctlNVMeWindowsAttributes, metrics, + testutil.SortMetrics(), testutil.IgnoreTime()) +} + func TestGatherIntelNVMeMetrics(t *testing.T) { runCmd = func(timeout config.Duration, sudo bool, command string, args ...string) ([]byte, error) { return []byte(nvmeIntelInfoDataMetricsFormat), nil @@ -1123,6 +1141,253 @@ var ( ), } + testSmartctlNVMeWindowsAttributes = []telegraf.Metric{ + testutil.MustMetric("smart_device", + map[string]string{ + "device": "nvme0", + "model": "Samsung SSD 970 EVO 1TB", + "serial_no": "xxx", + }, + map[string]interface{}{ + "exit_status": 0, + "health_ok": true, + "temp_c": 47, + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "id": "9", + "name": "Power_On_Hours", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": 1290, + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + "name": "Unsafe_Shutdowns", + }, + map[string]interface{}{ + "raw_value": 9, + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "id": "12", + "name": "Power_Cycle_Count", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": 10779, + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Media_and_Data_Integrity_Errors", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": 0, + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Error_Information_Log_Entries", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": 979, + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Available_Spare", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": 100, + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Available_Spare_Threshold", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": 10, + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "id": "194", + "name": "Temperature_Celsius", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": 47, + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Critical_Warning", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": int64(0), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Percentage_Used", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": int64(0), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Data_Units_Read", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": int64(16626888), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Data_Units_Written", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": int64(16829004), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Host_Read_Commands", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": int64(205868508), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Host_Write_Commands", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": int64(228472943), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Controller_Busy_Time", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": int64(686), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "name": "Critical_Temperature_Time", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + }, + map[string]interface{}{ + "raw_value": int64(0), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + "name": "Temperature_Sensor_1", + }, + map[string]interface{}{ + "raw_value": int64(47), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + "name": "Temperature_Sensor_2", + }, + map[string]interface{}{ + "raw_value": int64(68), + }, + time.Now(), + ), + testutil.MustMetric("smart_attribute", + map[string]string{ + "device": "nvme0", + "serial_no": "xxx", + "model": "Samsung SSD 970 EVO 1TB", + "name": "Warning_Temperature_Time", + }, + map[string]interface{}{ + "raw_value": int64(0), + }, + time.Now(), + ), + } + testsAda0Device = []struct { fields map[string]interface{} tags map[string]string @@ -1956,6 +2221,74 @@ Temperature Sensor 7: 44 C Temperature Sensor 8: 43 C ` + smartctlNVMeInfoDataWindows = `smartctl 7.3 2022-02-28 r5338 [x86_64-w64-mingw32-w10-20H2] (sf-7.3-1) +Copyright (C) 2002-22, Bruce Allen, Christian Franke, www.smartmontools.org + +=== START OF INFORMATION SECTION === +Model Number: Samsung SSD 970 EVO 1TB +Serial Number: xxx +Firmware Version: 2B2QEXE7 +PCI Vendor/Subsystem ID: 0x144d +IEEE OUI Identifier: 0x002538 +Total NVM Capacity: 1 000 204 886 016 [1,00 TB] +Unallocated NVM Capacity: 0 +Controller ID: 4 +NVMe Version: 1.3 +Number of Namespaces: 1 +Namespace 1 Size/Capacity: 1 000 204 886 016 [1,00 TB] +Namespace 1 Utilization: 732 789 374 976 [732 GB] +Namespace 1 Formatted LBA Size: 512 +Namespace 1 IEEE EUI-64: 002538 590141cfa4 +Local Time is: Wed Mar 30 13:30:12 2022 +Firmware Updates (0x16): 3 Slots, no Reset required +Optional Admin Commands (0x0017): Security Format Frmw_DL Self_Test +Optional NVM Commands (0x005f): Comp Wr_Unc DS_Mngmt Wr_Zero Sav/Sel_Feat Timestmp +Log Page Attributes (0x03): S/H_per_NS Cmd_Eff_Lg +Maximum Data Transfer Size: 512 Pages +Warning Comp. Temp. Threshold: 85 Celsius +Critical Comp. Temp. Threshold: 85 Celsius + +Supported Power States +St Op Max Active Idle RL RT WL WT Ent_Lat Ex_Lat + 0 + 6.20W - - 0 0 0 0 0 0 + 1 + 4.30W - - 1 1 1 1 0 0 + 2 + 2.10W - - 2 2 2 2 0 0 + 3 - 0.0400W - - 3 3 3 3 210 1200 + 4 - 0.0050W - - 4 4 4 4 2000 8000 + +Supported LBA Sizes (NSID 0x1) +Id Fmt Data Metadt Rel_Perf + 0 + 512 0 0 + +=== START OF SMART DATA SECTION === +SMART overall-health self-assessment test result: PASSED + +SMART/Health Information (NVMe Log 0x02) +Critical Warning: 0x00 +Temperature: 47 Celsius +Available Spare: 100% +Available Spare Threshold: 10% +Percentage Used: 0% +Data Units Read: 16,626,888 [8,51 TB] +Data Units Written: 16 829 004 [8,61 TB] +Host Read Commands: 205 868 508 +Host Write Commands: 228 472 943 +Controller Busy Time: 686 +Power Cycles: 10�779 +Power On Hours: 1�290 +Unsafe Shutdowns: 9 +Media and Data Integrity Errors: 0 +Error Information Log Entries: 979 +Warning Comp. Temperature Time: 0 +Critical Comp. Temperature Time: 0 +Temperature Sensor 1: 47 Celsius +Temperature Sensor 2: 68 Celsius + +Error Information (NVMe Log 0x01, 16 of 64 entries) +Num ErrCount SQId CmdId Status PELoc LBA NSID VS + 0 979 0 0x002a 0x4212 0x028 0 - - +` + smartctlNVMeInfoDataWithOverflow = ` Temperature Sensor 1: 9223372036854775808 C Temperature Sensor 2: -9223372036854775809 C