Skip to content

Commit 8081246

Browse files
committed
cleanup: better logging for device & type, use Kingpin to check option values
* use kingpin to check `smartctl.powermode-check` option value * better help message for `smartctl.powermode-check` with possible values * better logging labels, with device name & type, without device path Signed-off-by: Konstantin Shalygin <[email protected]>
1 parent ef5c03d commit 8081246

File tree

3 files changed

+52
-52
lines changed

3 files changed

+52
-52
lines changed

.golangci.yml

+31-17
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
1+
version: "2"
12
linters:
23
enable:
34
- misspell
45
- revive
56
- sloglint
67
disable:
78
- unused
8-
9-
issues:
10-
exclude-rules:
11-
- path: _test.go
12-
linters:
13-
- errcheck
14-
15-
linters-settings:
16-
errcheck:
17-
exclude-functions:
18-
# Used in HTTP handlers, any error is handled by the server itself.
19-
- (net/http.ResponseWriter).Write
20-
revive:
9+
settings:
10+
errcheck:
11+
exclude-functions:
12+
- (net/http.ResponseWriter).Write
13+
revive:
14+
rules:
15+
- name: unused-parameter
16+
severity: warning
17+
disabled: true
18+
exclusions:
19+
generated: lax
20+
presets:
21+
- comments
22+
- common-false-positives
23+
- legacy
24+
- std-error-handling
2125
rules:
22-
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter
23-
- name: unused-parameter
24-
severity: warning
25-
disabled: true
26+
- linters:
27+
- errcheck
28+
path: _test.go
29+
paths:
30+
- third_party$
31+
- builtin$
32+
- examples$
33+
formatters:
34+
exclusions:
35+
generated: lax
36+
paths:
37+
- third_party$
38+
- builtin$
39+
- examples$

main.go

+10-24
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
package main
1515

1616
import (
17-
"fmt"
1817
"log/slog"
1918
"net/http"
2019
"os"
@@ -102,30 +101,31 @@ var (
102101
"The interval between smartctl polls",
103102
).Default("60s").Duration()
104103
smartctlRescanInterval = kingpin.Flag("smartctl.rescan",
105-
"The interval between rescanning for new/disappeared devices. If the interval is smaller than 1s no rescanning takes place. If any devices are configured with smartctl.device also no rescanning takes place.",
104+
"The interval between rescanning for new/disappeared devices. If the interval is smaller than 1s no rescanning takes place. If any devices are configured with smartctl.device also no rescanning takes place",
106105
).Default("10m").Duration()
107-
smartctlScan = kingpin.Flag("smartctl.scan", "Enable scanning. This is a default if no devices are specified").Default("false").Bool()
106+
smartctlScan = kingpin.Flag("smartctl.scan", "Enable scanning. This is a default if no devices are specified",
107+
).Default("false").Bool()
108108
smartctlDevices = kingpin.Flag("smartctl.device",
109109
"The device to monitor. Device type can be specified after a semicolon, eg. '/dev/bus/0;megaraid,1' (repeatable)",
110110
).Strings()
111111
smartctlDeviceExclude = kingpin.Flag(
112112
"smartctl.device-exclude",
113-
"Regexp of devices to exclude from automatic scanning. (mutually exclusive to device-include)",
113+
"Regexp of devices to exclude from automatic scanning (mutually exclusive to device-include)",
114114
).Default("").String()
115115
smartctlDeviceInclude = kingpin.Flag(
116116
"smartctl.device-include",
117-
"Regexp of devices to exclude from automatic scanning. (mutually exclusive to device-exclude)",
117+
"Regexp of devices to exclude from automatic scanning (mutually exclusive to device-exclude)",
118118
).Default("").String()
119119
smartctlScanDeviceTypes = kingpin.Flag(
120120
"smartctl.scan-device-type",
121-
"Device type to use during automatic scan. Special by-id value forces predictable device names. (repeatable)",
121+
"Device type to use during automatic scan. Special by-id value forces predictable device names (repeatable)",
122122
).Strings()
123123
smartctlFakeData = kingpin.Flag("smartctl.fake-data",
124124
"The device to monitor (repeatable)",
125125
).Default("false").Hidden().Bool()
126126
smartctlPowerModeCheck = kingpin.Flag("smartctl.powermode-check",
127-
"Whether or not to check powermode before fetching data",
128-
).Default("standby").String()
127+
"Whether or not to check powermode before fetching data. Must be one of: 'never', 'sleep', 'standby', 'idle'. Default is 'standby'",
128+
).Default("standby").Enum("never", "sleep", "standby", "idle")
129129
)
130130

131131
// scanDevices uses smartctl to gather the list of available devices.
@@ -177,15 +177,6 @@ func buildDevicesFromFlag(devices []Device) []Device {
177177
return devices
178178
}
179179

180-
func validatePowerMode(mode string) error {
181-
switch strings.ToLower(mode) {
182-
case "never", "sleep", "standby", "idle":
183-
return nil
184-
default:
185-
return fmt.Errorf("invalid power mode: %s. Must be one of: never, sleep, standby, idle", mode)
186-
}
187-
}
188-
189180
func main() {
190181
metricsPath := kingpin.Flag(
191182
"web.telemetry-path", "Path under which to expose metrics",
@@ -198,11 +189,6 @@ func main() {
198189
kingpin.HelpFlag.Short('h')
199190
kingpin.Parse()
200191
logger := promslog.New(promslogConfig)
201-
202-
if err := validatePowerMode(*smartctlPowerModeCheck); err != nil {
203-
logger.Error(err.Error())
204-
os.Exit(1)
205-
}
206192
logger.Info("Starting smartctl_exporter", "version", version.Info())
207193
logger.Info("Build context", "build_context", version.BuildContext())
208194
var devices []Device
@@ -258,15 +244,15 @@ func main() {
258244
}
259245
landingPage, err := web.NewLandingPage(landingConfig)
260246
if err != nil {
261-
logger.Error("error creating landing page", "err", err)
247+
logger.Error("Error creating landing page", "err", err)
262248
os.Exit(1)
263249
}
264250
http.Handle("/", landingPage)
265251
}
266252

267253
srv := &http.Server{}
268254
if err := web.ListenAndServe(srv, toolkitFlags, logger); err != nil {
269-
logger.Error("error running HTTP server", "err", err)
255+
logger.Error("Error running HTTP server", "err", err)
270256
os.Exit(1)
271257
}
272258
}

readjson.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ func readSMARTctl(logger *slog.Logger, device Device, wg *sync.WaitGroup) {
6969
logger.Debug("Calling smartctl with args", "args", strings.Join(smartctlArgs, " "))
7070
out, err := exec.Command(*smartctlPath, smartctlArgs...).Output()
7171
if err != nil {
72-
logger.Warn("S.M.A.R.T. output reading", "err", err, "device", device)
72+
logger.Warn("S.M.A.R.T. output reading", "device", device.Label, "type", device.Type, "err", err)
7373
}
7474
// Accommodate a smartmontools pre-7.3 bug
7575
cleaned_out := strings.TrimPrefix(string(out), " Pending defect count:")
7676
json := parseJSON(cleaned_out)
7777
rcOk := resultCodeIsOk(logger, device, json.Get("smartctl.exit_status").Int())
7878
jsonOk := jsonIsOk(logger, json)
79-
logger.Debug("Collected S.M.A.R.T. json data", "device", device, "duration", time.Since(start))
79+
logger.Debug("Collected S.M.A.R.T. json data", "device", device.Label, "type", device.Type, "duration", time.Since(start))
8080
if rcOk && jsonOk {
8181
jsonCache.Store(device, JSONCache{JSON: json, LastCollect: time.Now()})
8282
}
@@ -127,7 +127,7 @@ func readData(logger *slog.Logger, device Device) gjson.Result {
127127

128128
cacheValue, found := jsonCache.Load(device)
129129
if !found {
130-
logger.Warn("device not found", "device", device)
130+
logger.Warn("Device not found", "device", device.Label, "type", device.Type)
131131
return gjson.Result{}
132132
}
133133
return cacheValue.(JSONCache).JSON
@@ -139,30 +139,30 @@ func resultCodeIsOk(logger *slog.Logger, device Device, SMARTCtlResult int64) bo
139139
if SMARTCtlResult > 0 {
140140
b := SMARTCtlResult
141141
if (b & 1) != 0 {
142-
logger.Error("Command line did not parse", "device", device)
142+
logger.Error("Command line did not parse", "device", device.Label, "type", device.Type)
143143
result = false
144144
}
145145
if (b & (1 << 1)) != 0 {
146-
logger.Error("Device open failed, device did not return an IDENTIFY DEVICE structure, or device is in a low-power mode", "device", device)
146+
logger.Error("Device open failed, device did not return an IDENTIFY DEVICE structure, or device is in a low-power mode", "device", device.Label, "type", device.Type)
147147
result = false
148148
}
149149
if (b & (1 << 2)) != 0 {
150-
logger.Warn("Some SMART or other ATA command to the disk failed, or there was a checksum error in a SMART data structure", "device", device)
150+
logger.Warn("Some SMART or other ATA command to the disk failed, or there was a checksum error in a SMART data structure", "device", device.Label, "type", device.Type)
151151
}
152152
if (b & (1 << 3)) != 0 {
153-
logger.Warn("SMART status check returned 'DISK FAILING'", "device", device)
153+
logger.Warn("SMART status check returned 'DISK FAILING'", "device", device.Label, "type", device.Type)
154154
}
155155
if (b & (1 << 4)) != 0 {
156-
logger.Warn("We found prefail Attributes <= threshold", "device", device)
156+
logger.Warn("We found prefail Attributes <= threshold", "device", device.Label, "type", device.Type)
157157
}
158158
if (b & (1 << 5)) != 0 {
159-
logger.Warn("SMART status check returned 'DISK OK' but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past", "device", device)
159+
logger.Warn("SMART status check returned 'DISK OK' but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past", "device", device.Label, "type", device.Type)
160160
}
161161
if (b & (1 << 6)) != 0 {
162-
logger.Warn("The device error log contains records of errors", "device", device)
162+
logger.Warn("The device error log contains records of errors", "device", device.Label, "type", device.Type)
163163
}
164164
if (b & (1 << 7)) != 0 {
165-
logger.Warn("The device self-test log contains records of errors. [ATA only] Failed self-tests outdated by a newer successful extended self-test are ignored", "device", device)
165+
logger.Warn("The device self-test log contains records of errors. [ATA only] Failed self-tests outdated by a newer successful extended self-test are ignored", "device", device.Label, "type", device.Type)
166166
}
167167
}
168168
return result

0 commit comments

Comments
 (0)