From b91900848ba0af9119ed9484ba6c8114f70b125c Mon Sep 17 00:00:00 2001
From: Micah Anderson <micah@riseup.net>
Date: Wed, 11 Jan 2023 07:27:08 -0800
Subject: [PATCH] Replace openvpn-exporter with textfile exporter.

The upstream openvpn-exporter was emitting high cardinality metrics, because of
the CN being an unique identifier based off of the certificate. This would cause
the tsdb to fill with unnecessary, and unrelated metrics.

This removes that exporter (which has not seen commits for years) and replaces
it with the prometheus-node-exporter textfile collector, which will emit metrics
produced by the shell script that is run every 10 seconds. It will only emit
these metrics:

openvpn_server_connected_clients{status_path="/tmp/openvpn-status-tcp"}
openvpn_server_connected_clients{status_path="/tmp/openvpn-status-udp"}
openvpn_up{status_path="/tmp/openvpn-status-tcp"}
openvpn_up{status_path="/tmp/openvpn-status-udp"}
---
 Dockerfile                                    |  8 ++--
 conf/services.d/openvpn-exporter/run          |  3 +-
 .../prometheus-node-exporter/finish           |  4 ++
 conf/services.d/prometheus-node-exporter/run  |  4 ++
 openvpn-metrics.sh                            | 43 +++++++++++++++++++
 5 files changed, 57 insertions(+), 5 deletions(-)
 create mode 100755 conf/services.d/prometheus-node-exporter/finish
 create mode 100755 conf/services.d/prometheus-node-exporter/run
 create mode 100755 openvpn-metrics.sh

diff --git a/Dockerfile b/Dockerfile
index 89340ed..699a269 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,8 +12,6 @@ ENV GOPATH=/go
 WORKDIR $GOPATH
 RUN git clone https://github.com/OperatorFoundation/shapeshifter-dispatcher /shapeshifter-dispatcher && cd /shapeshifter-dispatcher && git reset --hard 34bd4b3fe24537a8a7a827825a1a19f2ad13adae && /usr/lib/go-1.19/bin/go build
 RUN strip /shapeshifter-dispatcher/shapeshifter-dispatcher
-RUN /usr/lib/go-1.19/bin/go install github.com/kumina/openvpn_exporter@latest
-RUN strip $GOPATH/bin/openvpn_exporter
 
 FROM registry.git.autistici.org/ai3/docker/s6-base
 
@@ -32,10 +30,13 @@ RUN apt-get -q update \
   socat \
   lua-socket \
   lua-sec \
+  prometheus-node-exporter \
   && rm -rf /var/lib/apt/lists/*
 
+# Remove unwanted prometheus-node-exporter scripts installed by the package
+RUN rm -f /var/lib/prometheus-node-exporter/*
+
 COPY --from=build /shapeshifter-dispatcher/shapeshifter-dispatcher /usr/local/bin/shapeshifter-dispatcher
-COPY --from=build /go/bin/openvpn_exporter /usr/local/bin/openvpn_exporter
 
 RUN setcap cap_net_admin,cap_net_bind_service+ep /usr/sbin/openvpn
 RUN setcap cap_net_admin+ep /bin/ip
@@ -44,3 +45,4 @@ RUN update-alternatives --set iptables /usr/sbin/iptables-legacy
 
 # S6 configuration
 COPY conf/ /etc/
+COPY openvpn-metrics.sh /usr/local/sbin/openvpn-metrics.sh
diff --git a/conf/services.d/openvpn-exporter/run b/conf/services.d/openvpn-exporter/run
index 1349930..b9431ae 100755
--- a/conf/services.d/openvpn-exporter/run
+++ b/conf/services.d/openvpn-exporter/run
@@ -1,4 +1,3 @@
 #!/bin/sh
 
-echo "Starting openvpn-exporter"
-exec /usr/local/bin/openvpn_exporter -openvpn.status_paths "/tmp/openvpn-status-tcp,/tmp/openvpn-status-udp" -ignore.individuals true
+every 10 /usr/local/sbin/openvpn-metrics.sh
diff --git a/conf/services.d/prometheus-node-exporter/finish b/conf/services.d/prometheus-node-exporter/finish
new file mode 100755
index 0000000..f7d228a
--- /dev/null
+++ b/conf/services.d/prometheus-node-exporter/finish
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+echo "Exiting prometheus-node-exporter"
+s6-svscanctl -t /var/run/s6/services
diff --git a/conf/services.d/prometheus-node-exporter/run b/conf/services.d/prometheus-node-exporter/run
new file mode 100755
index 0000000..c74f3b7
--- /dev/null
+++ b/conf/services.d/prometheus-node-exporter/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+echo "Starting prometheus-node-exporter"
+exec /usr/bin/prometheus-node-exporter --collector.disable-defaults --collector.textfile --collector.textfile.directory /tmp/prometheus --web.listen-address=":9176"
diff --git a/openvpn-metrics.sh b/openvpn-metrics.sh
new file mode 100755
index 0000000..82250a5
--- /dev/null
+++ b/openvpn-metrics.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# Execute a metrics-generating script and safely write its
+# output to /tmp/prometheus
+#
+#
+output_dir="/tmp/prometheus"
+output_file="${output_dir}/openvpn.prom"
+umask 022
+tmp_file="${output_file}.$$"
+trap "rm -f $tmp_file 2>/dev/null" EXIT INT TERM
+
+mkdir -p $output_dir
+
+echo "# HELP openvpn_up Whether scraping OpenVPN's metrics was successful." > $tmp_file
+echo '# TYPE openvpn_up gauge' >> $tmp_file
+echo -n 'openvpn_up{status_path="/tmp/openvpn-status-tcp"} ' >> $tmp_file
+if [ -r /tmp/openvpn-status-tcp ];
+then
+    echo "1" >> $tmp_file
+    echo "# HELP openvpn_server_connected_clients Number Of Connected Clients" >> $tmp_file
+    echo "# TYPE openvpn_server_connected_clients gauge" >> $tmp_file
+    tcp_connected=$(cat /tmp/openvpn-status-tcp |grep CLIENT_LIST|wc -l)
+    echo -n 'openvpn_server_connected_clients{status_path="/tmp/openvpn-status-tcp"} ' >> $tmp_file
+    echo $tcp_connected >> $tmp_file
+else
+    echo "0" >> $tmp_file
+fi
+
+echo -n 'openvpn_up{status_path="/tmp/openvpn-status-udp"} ' >> $tmp_file
+if [ -r /tmp/openvpn-status-udp ];
+then
+    echo "1" >> $tmp_file
+    udp_connected=$(cat /tmp/openvpn-status-udp |grep CLIENT_LIST|wc -l)
+    echo -n 'openvpn_server_connected_clients{status_path="/tmp/openvpn-status-udp"} ' >> $tmp_file
+    echo $udp_connected >> $tmp_file
+else
+    echo "0" >> $tmp_file
+fi
+
+mv -f "$tmp_file" "$output_file"
+
+exit $?
-- 
GitLab