From 965204547a99b68cee31069066fc7040388f852d Mon Sep 17 00:00:00 2001 From: Zoltan Langi Date: Thu, 19 Dec 2019 11:17:35 +0100 Subject: [PATCH 1/3] 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 --- Dockerfile | 18 +++++++++++++++++ config.yaml | 8 ++++++++ docker-entrypoint.sh | 6 ++++++ metrics.go | 44 ++++++++++++++++++++++++++++++++++++++++++ smartctl.go | 46 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 122 insertions(+) create mode 100644 Dockerfile create mode 100644 config.yaml create mode 100755 docker-entrypoint.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..70a5312 --- /dev/null +++ b/Dockerfile @@ -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"] diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..b6b38d0 --- /dev/null +++ b/config.yaml @@ -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 diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 0000000..951db3e --- /dev/null +++ b/docker-entrypoint.sh @@ -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 diff --git a/metrics.go b/metrics.go index 1ee8708..78701e9 100644 --- a/metrics.go +++ b/metrics.go @@ -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, + ) ) diff --git a/smartctl.go b/smartctl.go index 5a5c073..50af602 100644 --- a/smartctl.go +++ b/smartctl.go @@ -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, + ) +} From a3ee4411939fa8125d9cb4cbafdeacc91d8bddb3 Mon Sep 17 00:00:00 2001 From: Zoltan Langi Date: Thu, 19 Dec 2019 11:22:14 +0100 Subject: [PATCH 2/3] fixed the config file --- config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/config.yaml b/config.yaml index b6b38d0..3792a24 100644 --- a/config.yaml +++ b/config.yaml @@ -5,4 +5,3 @@ smartctl_exporter: smartctl_location: /usr/sbin/smartctl collect_not_more_than_period: 120s devices: - - /dev/nvme0 From 9666ec9296b979d13de965ee441d86d14d6d545b Mon Sep 17 00:00:00 2001 From: Zoltan Langi Date: Thu, 19 Dec 2019 12:17:10 +0100 Subject: [PATCH 3/3] fixed format --- smartctl.go | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/smartctl.go b/smartctl.go index 50af602..24930ae 100644 --- a/smartctl.go +++ b/smartctl.go @@ -289,26 +289,26 @@ func (smart *SMARTctl) mineNvmeSmartHealthInformationLog() { 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, - ) + 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, - ) + 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, + ) }