From 458a8bad52357302d3121e1b1f1b0ac5fff9dd85 Mon Sep 17 00:00:00 2001 From: Melvin Hulsmans Date: Wed, 2 Jul 2025 10:35:26 +0200 Subject: [PATCH] feat: add proxy_status metric We want to be able to tell when a proxy goes offline. Added a proxy_status metric that is either 1 (online) or 0 (offline). --- pkg/metrics/aggregate/server.go | 6 ++++++ pkg/metrics/mem/server.go | 16 ++++++++++++++++ pkg/metrics/mem/types.go | 2 ++ pkg/metrics/prometheus/server.go | 14 ++++++++++++++ server/dashboard_api.go | 3 +++ server/metrics/metrics.go | 2 ++ 6 files changed, 43 insertions(+) diff --git a/pkg/metrics/aggregate/server.go b/pkg/metrics/aggregate/server.go index 354d85c2..add91472 100644 --- a/pkg/metrics/aggregate/server.go +++ b/pkg/metrics/aggregate/server.go @@ -68,6 +68,12 @@ func (m *serverMetrics) CloseProxy(name string, proxyType string) { } } +func (m *serverMetrics) ProxyStatus(name string, proxyType string, online bool) { + for _, v := range m.ms { + v.ProxyStatus(name, proxyType, online) + } +} + func (m *serverMetrics) OpenConnection(name string, proxyType string) { for _, v := range m.ms { v.OpenConnection(name, proxyType) diff --git a/pkg/metrics/mem/server.go b/pkg/metrics/mem/server.go index 70cfc1c1..1a80023d 100644 --- a/pkg/metrics/mem/server.go +++ b/pkg/metrics/mem/server.go @@ -133,6 +133,20 @@ func (m *serverMetrics) CloseProxy(name string, proxyType string) { } } +func (m *serverMetrics) ProxyStatus(name string, proxyType string, online bool) { + m.mu.Lock() + defer m.mu.Unlock() + proxyStats, ok := m.info.ProxyStatistics[name] + if ok { + if online { + proxyStats.Status = "online" + } else { + proxyStats.Status = "offline" + } + m.info.ProxyStatistics[name] = proxyStats + } +} + func (m *serverMetrics) OpenConnection(name string, _ string) { m.info.CurConns.Inc(1) @@ -217,6 +231,7 @@ func (m *serverMetrics) GetProxiesByType(proxyType string) []*ProxyStats { TodayTrafficIn: proxyStats.TrafficIn.TodayCount(), TodayTrafficOut: proxyStats.TrafficOut.TodayCount(), CurConns: int64(proxyStats.CurConns.Count()), + Status: proxyStats.Status, } if !proxyStats.LastStartTime.IsZero() { ps.LastStartTime = proxyStats.LastStartTime.Format("01-02 15:04:05") @@ -248,6 +263,7 @@ func (m *serverMetrics) GetProxiesByTypeAndName(proxyType string, proxyName stri TodayTrafficIn: proxyStats.TrafficIn.TodayCount(), TodayTrafficOut: proxyStats.TrafficOut.TodayCount(), CurConns: int64(proxyStats.CurConns.Count()), + Status: proxyStats.Status, } if !proxyStats.LastStartTime.IsZero() { res.LastStartTime = proxyStats.LastStartTime.Format("01-02 15:04:05") diff --git a/pkg/metrics/mem/types.go b/pkg/metrics/mem/types.go index a6f276ce..d9e6b027 100644 --- a/pkg/metrics/mem/types.go +++ b/pkg/metrics/mem/types.go @@ -40,6 +40,7 @@ type ProxyStats struct { LastStartTime string LastCloseTime string CurConns int64 + Status string } type ProxyTrafficInfo struct { @@ -56,6 +57,7 @@ type ProxyStatistics struct { CurConns metric.Counter LastStartTime time.Time LastCloseTime time.Time + Status string } type ServerStatistics struct { diff --git a/pkg/metrics/prometheus/server.go b/pkg/metrics/prometheus/server.go index 56dea6e8..df78e46b 100644 --- a/pkg/metrics/prometheus/server.go +++ b/pkg/metrics/prometheus/server.go @@ -16,6 +16,7 @@ var ServerMetrics metrics.ServerMetrics = newServerMetrics() type serverMetrics struct { clientCount prometheus.Gauge proxyCount *prometheus.GaugeVec + proxyStatus *prometheus.GaugeVec connectionCount *prometheus.GaugeVec trafficIn *prometheus.CounterVec trafficOut *prometheus.CounterVec @@ -37,6 +38,13 @@ func (m *serverMetrics) CloseProxy(_ string, proxyType string) { m.proxyCount.WithLabelValues(proxyType).Dec() } +func (m *serverMetrics) ProxyStatus(name string, proxyType string, online bool) { + if online { + m.proxyStatus.WithLabelValues(name, proxyType).Set(1) + } + m.proxyStatus.WithLabelValues(name, proxyType).Set(0) +} + func (m *serverMetrics) OpenConnection(name string, proxyType string) { m.connectionCount.WithLabelValues(name, proxyType).Inc() } @@ -67,6 +75,12 @@ func newServerMetrics() *serverMetrics { Name: "proxy_counts", Help: "The current proxy counts", }, []string{"type"}), + proxyStatus: prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: serverSubsystem, + Name: "proxy_status", + Help: "The current proxy status", + }, []string{"name", "type"}), connectionCount: prometheus.NewGaugeVec(prometheus.GaugeOpts{ Namespace: namespace, Subsystem: serverSubsystem, diff --git a/server/dashboard_api.go b/server/dashboard_api.go index 54e5d9e9..5066508a 100644 --- a/server/dashboard_api.go +++ b/server/dashboard_api.go @@ -17,6 +17,7 @@ package server import ( "cmp" "encoding/json" + "github.com/fatedier/frp/server/metrics" "net/http" "slices" @@ -253,11 +254,13 @@ func (svr *Service) getProxyStatsByType(proxyType string) (proxyInfos []*ProxySt continue } proxyInfo.Status = "online" + metrics.Server.ProxyStatus(pxy.GetName(), pxy.GetConfigurer().GetBaseConfig().Type, true) if pxy.GetLoginMsg() != nil { proxyInfo.ClientVersion = pxy.GetLoginMsg().Version } } else { proxyInfo.Status = "offline" + metrics.Server.ProxyStatus(pxy.GetName(), pxy.GetConfigurer().GetBaseConfig().Type, false) } proxyInfo.Name = ps.Name proxyInfo.TodayTrafficIn = ps.TodayTrafficIn diff --git a/server/metrics/metrics.go b/server/metrics/metrics.go index 5064a238..259ddd68 100644 --- a/server/metrics/metrics.go +++ b/server/metrics/metrics.go @@ -9,6 +9,7 @@ type ServerMetrics interface { CloseClient() NewProxy(name string, proxyType string) CloseProxy(name string, proxyType string) + ProxyStatus(name string, proxyType string, online bool) OpenConnection(name string, proxyType string) CloseConnection(name string, proxyType string) AddTrafficIn(name string, proxyType string, trafficBytes int64) @@ -31,6 +32,7 @@ func (noopServerMetrics) NewClient() {} func (noopServerMetrics) CloseClient() {} func (noopServerMetrics) NewProxy(string, string) {} func (noopServerMetrics) CloseProxy(string, string) {} +func (noopServerMetrics) ProxyStatus(string, string, bool) {} func (noopServerMetrics) OpenConnection(string, string) {} func (noopServerMetrics) CloseConnection(string, string) {} func (noopServerMetrics) AddTrafficIn(string, string, int64) {}