mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-22 22:59:09 +02:00
Add opt-in local Prometheus metrics endpoint to the client
This commit is contained in:
+35
-1
@@ -23,6 +23,9 @@ import (
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/auth"
|
||||
"github.com/netbirdio/netbird/client/internal/expose"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/localmetrics"
|
||||
"github.com/netbirdio/netbird/client/internal/profilemanager"
|
||||
sleephandler "github.com/netbirdio/netbird/client/internal/sleep/handler"
|
||||
"github.com/netbirdio/netbird/client/mdm"
|
||||
@@ -99,6 +102,7 @@ type Server struct {
|
||||
|
||||
statusRecorder *peer.Status
|
||||
sessionWatcher *internal.SessionWatcher
|
||||
localMetrics *localmetrics.Manager
|
||||
|
||||
probeThrottle *probeThrottle
|
||||
persistSyncResponse bool
|
||||
@@ -155,9 +159,28 @@ func New(ctx context.Context, logFile string, configFile string, profilesDisable
|
||||
s.sleepHandler = sleephandler.New(agent)
|
||||
s.startSleepDetector()
|
||||
|
||||
s.localMetrics = localmetrics.NewManager(ctx, s.statusRecorder, s.clientMetricsGatherer)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// clientMetricsGatherer returns the Prometheus gatherer of the running
|
||||
// engine's client metrics, or nil when no engine is running.
|
||||
func (s *Server) clientMetricsGatherer() prometheus.Gatherer {
|
||||
s.mutex.Lock()
|
||||
connectClient := s.connectClient
|
||||
s.mutex.Unlock()
|
||||
|
||||
if connectClient == nil {
|
||||
return nil
|
||||
}
|
||||
engine := connectClient.Engine()
|
||||
if engine == nil {
|
||||
return nil
|
||||
}
|
||||
return engine.GetClientMetrics().PrometheusGatherer()
|
||||
}
|
||||
|
||||
func (s *Server) Start() error {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
@@ -238,6 +261,7 @@ func (s *Server) Start() error {
|
||||
|
||||
s.statusRecorder.UpdateManagementAddress(config.ManagementURL.String())
|
||||
s.statusRecorder.UpdateRosenpass(config.RosenpassEnabled, config.RosenpassPermissive)
|
||||
s.localMetrics.Reconcile(config.LocalMetricsEnabled, config.LocalMetricsAddress)
|
||||
|
||||
if s.sessionWatcher == nil {
|
||||
s.sessionWatcher = internal.NewSessionWatcher(s.rootCtx, s.statusRecorder)
|
||||
@@ -416,11 +440,18 @@ func (s *Server) SetConfig(callerCtx context.Context, msg *proto.SetConfigReques
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := profilemanager.UpdateConfig(config); err != nil {
|
||||
updatedConf, err := profilemanager.UpdateConfig(config)
|
||||
if err != nil {
|
||||
log.Errorf("failed to update profile config: %v", err)
|
||||
return nil, fmt.Errorf("failed to update profile config: %w", err)
|
||||
}
|
||||
|
||||
if activeProf, err := s.profileManager.GetActiveProfileState(); err == nil {
|
||||
if activePath, err := activeProf.FilePath(); err == nil && activePath == config.ConfigPath {
|
||||
s.localMetrics.Reconcile(updatedConf.LocalMetricsEnabled, updatedConf.LocalMetricsAddress)
|
||||
}
|
||||
}
|
||||
|
||||
return &proto.SetConfigResponse{}, nil
|
||||
}
|
||||
|
||||
@@ -490,6 +521,8 @@ func (s *Server) setConfigInputFromRequest(msg *proto.SetConfigRequest) (profile
|
||||
|
||||
config.RosenpassEnabled = msg.RosenpassEnabled
|
||||
config.RosenpassPermissive = msg.RosenpassPermissive
|
||||
config.LocalMetricsEnabled = msg.EnableLocalMetrics
|
||||
config.LocalMetricsAddress = msg.LocalMetricsAddress
|
||||
config.DisableAutoConnect = msg.DisableAutoConnect
|
||||
config.ServerSSHAllowed = msg.ServerSSHAllowed
|
||||
config.NetworkMonitor = msg.NetworkMonitor
|
||||
@@ -945,6 +978,7 @@ func (s *Server) Up(callerCtx context.Context, msg *proto.UpRequest) (*proto.UpR
|
||||
|
||||
s.statusRecorder.UpdateManagementAddress(s.config.ManagementURL.String())
|
||||
s.statusRecorder.UpdateRosenpass(s.config.RosenpassEnabled, s.config.RosenpassPermissive)
|
||||
s.localMetrics.Reconcile(s.config.LocalMetricsEnabled, s.config.LocalMetricsAddress)
|
||||
|
||||
s.clientRunning = true
|
||||
s.clientRunningChan = make(chan struct{})
|
||||
|
||||
@@ -73,6 +73,8 @@ func TestSetConfig_AllFieldsSaved(t *testing.T) {
|
||||
disableIPv6 := true
|
||||
mtu := int64(1280)
|
||||
sshJWTCacheTTL := int32(300)
|
||||
enableLocalMetrics := true
|
||||
localMetricsAddress := "127.0.0.1:9292"
|
||||
|
||||
req := &proto.SetConfigRequest{
|
||||
ProfileName: profName,
|
||||
@@ -104,6 +106,8 @@ func TestSetConfig_AllFieldsSaved(t *testing.T) {
|
||||
DnsRouteInterval: durationpb.New(2 * time.Minute),
|
||||
Mtu: &mtu,
|
||||
SshJWTCacheTTL: &sshJWTCacheTTL,
|
||||
EnableLocalMetrics: &enableLocalMetrics,
|
||||
LocalMetricsAddress: &localMetricsAddress,
|
||||
}
|
||||
|
||||
_, err = s.SetConfig(ctx, req)
|
||||
@@ -150,6 +154,8 @@ func TestSetConfig_AllFieldsSaved(t *testing.T) {
|
||||
require.Equal(t, uint16(mtu), cfg.MTU)
|
||||
require.NotNil(t, cfg.SSHJWTCacheTTL)
|
||||
require.Equal(t, int(sshJWTCacheTTL), *cfg.SSHJWTCacheTTL)
|
||||
require.Equal(t, enableLocalMetrics, cfg.LocalMetricsEnabled)
|
||||
require.Equal(t, localMetricsAddress, cfg.LocalMetricsAddress)
|
||||
|
||||
verifyAllFieldsCovered(t, req)
|
||||
}
|
||||
@@ -202,6 +208,8 @@ func verifyAllFieldsCovered(t *testing.T, req *proto.SetConfigRequest) {
|
||||
"EnableSSHRemotePortForwarding": true,
|
||||
"DisableSSHAuth": true,
|
||||
"SshJWTCacheTTL": true,
|
||||
"EnableLocalMetrics": true,
|
||||
"LocalMetricsAddress": true,
|
||||
}
|
||||
|
||||
val := reflect.ValueOf(req).Elem()
|
||||
@@ -261,6 +269,8 @@ func TestCLIFlags_MappedToSetConfig(t *testing.T) {
|
||||
"enable-ssh-remote-port-forwarding": "EnableSSHRemotePortForwarding",
|
||||
"disable-ssh-auth": "DisableSSHAuth",
|
||||
"ssh-jwt-cache-ttl": "SshJWTCacheTTL",
|
||||
"enable-local-metrics": "EnableLocalMetrics",
|
||||
"local-metrics-address": "LocalMetricsAddress",
|
||||
}
|
||||
|
||||
// SetConfigRequest fields that don't have CLI flags (settable only via UI or other means).
|
||||
|
||||
Reference in New Issue
Block a user