I've added support for NVMe drives and also created a docker file so a container can be built.

I've added the following metrics for the NVMe drives:
smart_status, critical_warning, available_spare, media_errors
This commit is contained in:
Zoltan Langi 2019-12-19 11:17:35 +01:00
parent a68a2861e5
commit 965204547a
5 changed files with 122 additions and 0 deletions

18
Dockerfile Normal file
View file

@ -0,0 +1,18 @@
# Build /go/bin/smartctl_exporter
FROM quay.io/prometheus/golang-builder:1.13-base AS builder
ADD . /go/src/github.com/Sheridan/smartctl_exporter/
RUN cd /go/src/github.com/Sheridan/smartctl_exporter && make
# Container image
FROM ubuntu:18.04
WORKDIR /
RUN apt-get update \
&& apt-get install smartmontools/bionic-backports -y --no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /go/src/github.com/Sheridan/smartctl_exporter/bin/smartctl_exporter /bin/smartctl_exporter
COPY docker-entrypoint.sh /
COPY smartctl_exporter.yaml /
RUN chmod +x /docker-entrypoint.sh
EXPOSE 9633
ENTRYPOINT ["/docker-entrypoint.sh"]

8
config.yaml Normal file
View file

@ -0,0 +1,8 @@
smartctl_exporter:
bind_to: "[0.0.0.0]:9633"
url_path: "/metrics"
fake_json: no
smartctl_location: /usr/sbin/smartctl
collect_not_more_than_period: 120s
devices:
- /dev/nvme0

6
docker-entrypoint.sh Executable file
View file

@ -0,0 +1,6 @@
#!/bin/sh
DISKS="$(lsblk -l|egrep -oe '(sd[a-z]|nvme[0-9])'|sed -e 's/^/ - \/dev\//'| uniq)"
echo "$DISKS" >> smartctl_exporter.yaml
/bin/smartctl_exporter -config=/smartctl_exporter.yaml

View file

@ -166,4 +166,48 @@ var (
},
nil,
)
metricCriticalWarning = prometheus.NewDesc(
"critical_warning",
"Critical warning counter",
[]string{
"device",
"model_family",
"model_name",
"serial_number",
},
nil,
)
metricAvailableSpare = prometheus.NewDesc(
"available_spare",
"Available spare",
[]string{
"device",
"model_family",
"model_name",
"serial_number",
},
nil,
)
metricMediaErrors = prometheus.NewDesc(
"media_errors",
"Media errors counter",
[]string{
"device",
"model_family",
"model_name",
"serial_number",
},
nil,
)
metricSmartStatus = prometheus.NewDesc(
"smart_status",
"Smart status",
[]string{
"device",
"model_family",
"model_name",
"serial_number",
},
nil,
)
)

View file

@ -50,6 +50,8 @@ func (smart *SMARTctl) Collect() {
smart.mineTemperatures()
smart.minePowerCycleCount()
smart.mineDeviceStatistics()
smart.mineNvmeSmartHealthInformationLog()
smart.mineNvmeSmartStatus()
}
func (smart *SMARTctl) mineExitStatus() {
@ -266,3 +268,47 @@ func (smart *SMARTctl) mineLongFlags(json gjson.Result, flags []string) string {
}
return strings.Join(result, ",")
}
func (smart *SMARTctl) mineNvmeSmartHealthInformationLog() {
iHealth := smart.json.Get("nvme_smart_health_information_log")
smart.ch <- prometheus.MustNewConstMetric(
metricCriticalWarning,
prometheus.GaugeValue,
iHealth.Get("critical_warning").Float(),
smart.device.device,
smart.device.family,
smart.device.model,
smart.device.serial,
)
smart.ch <- prometheus.MustNewConstMetric(
metricAvailableSpare,
prometheus.GaugeValue,
iHealth.Get("available_spare").Float(),
smart.device.device,
smart.device.family,
smart.device.model,
smart.device.serial,
)
smart.ch <- prometheus.MustNewConstMetric(
metricMediaErrors,
prometheus.GaugeValue,
iHealth.Get("media_errors").Float(),
smart.device.device,
smart.device.family,
smart.device.model,
smart.device.serial,
)
}
func (smart *SMARTctl) mineNvmeSmartStatus() {
iStatus := smart.json.Get("smart_status")
smart.ch <- prometheus.MustNewConstMetric(
metricSmartStatus,
prometheus.GaugeValue,
iStatus.Get("passed").Float(),
smart.device.device,
smart.device.family,
smart.device.model,
smart.device.serial,
)
}