From 04fa599a8697562fcdf27a6fe458ac36f2e870cf Mon Sep 17 00:00:00 2001
From: Bradley Wilson-Hunt <bwilsonhunt@gmail.com>
Date: Tue, 3 Jun 2025 21:08:44 +0100
Subject: [PATCH] feat(metrics): adding prometheus metrics for dc power
 extension

---
 dc_metrics.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
 serial.go     |  4 ++++
 2 files changed, 57 insertions(+)
 create mode 100644 dc_metrics.go

diff --git a/dc_metrics.go b/dc_metrics.go
new file mode 100644
index 0000000..692a7b5
--- /dev/null
+++ b/dc_metrics.go
@@ -0,0 +1,53 @@
+package kvm
+
+import (
+	"sync"
+
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+	dcCurrentGauge = prometheus.NewGauge(prometheus.GaugeOpts{
+		Name: "jetkvm_dc_current_amperes",
+		Help: "Current DC power consumption in amperes",
+	})
+
+	dcPowerGauge = prometheus.NewGauge(prometheus.GaugeOpts{
+		Name: "jetkvm_dc_power_watts",
+		Help: "DC power consumption in watts",
+	})
+
+	dcVoltageGauge = prometheus.NewGauge(prometheus.GaugeOpts{
+		Name: "jetkvm_dc_voltage_volts",
+		Help: "DC voltage in volts",
+	})
+
+	dcStateGauge = prometheus.NewGauge(prometheus.GaugeOpts{
+		Name: "jetkvm_dc_power_state",
+		Help: "DC power state (1 = on, 0 = off)",
+	})
+
+	dcMetricsRegistered sync.Once
+)
+
+// registerDCMetrics registers the DC power metrics with Prometheus (called once when DC control is mounted)
+func registerDCMetrics() {
+	dcMetricsRegistered.Do(func() {
+		prometheus.MustRegister(dcCurrentGauge)
+		prometheus.MustRegister(dcPowerGauge)
+		prometheus.MustRegister(dcVoltageGauge)
+		prometheus.MustRegister(dcStateGauge)
+	})
+}
+
+// updateDCMetrics updates the Prometheus metrics with current DC power state values
+func updateDCMetrics(state DCPowerState) {
+	dcCurrentGauge.Set(state.Current)
+	dcPowerGauge.Set(state.Power)
+	dcVoltageGauge.Set(state.Voltage)
+	if state.IsOn {
+		dcStateGauge.Set(1)
+	} else {
+		dcStateGauge.Set(0)
+	}
+}
diff --git a/serial.go b/serial.go
index f4dd5b5..f730d4b 100644
--- a/serial.go
+++ b/serial.go
@@ -128,6 +128,7 @@ func pressATXResetButton(duration time.Duration) error {
 
 func mountDCControl() error {
 	_ = port.SetMode(defaultMode)
+	registerDCMetrics()
 	go runDCControl()
 	return nil
 }
@@ -188,6 +189,9 @@ func runDCControl() {
 		dcState.Current = amps
 		dcState.Power = watts
 
+		// Update Prometheus metrics
+		updateDCMetrics(dcState)
+
 		if currentSession != nil {
 			writeJSONRPCEvent("dcState", dcState, currentSession)
 		}