Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions client/internal/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ func (c *ConnectClient) run(mobileDependency MobileDependency, runningChan chan
c.clientMetrics.RecordLoginDuration(engineCtx, time.Since(loginStarted), true)
c.statusRecorder.MarkManagementConnected()

if metricsConfig := loginResp.GetNetbirdConfig().GetMetrics(); metricsConfig != nil {
c.clientMetrics.UpdatePushFromMgm(c.ctx, metricsConfig.GetEnabled())
}

localPeerState := peer.LocalPeerState{
IP: loginResp.GetPeerConfig().GetAddress(),
PubKey: myPrivateKey.PublicKey().String(),
Expand Down
10 changes: 10 additions & 0 deletions client/internal/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,8 @@ func (e *Engine) handleSync(update *mgmProto.SyncResponse) error {
return fmt.Errorf("handle the flow configuration: %w", err)
}

e.handleMetricsUpdate(wCfg.GetMetrics())

if err := e.PopulateNetbirdConfig(wCfg, nil); err != nil {
log.Warnf("Failed to update DNS server config: %v", err)
}
Expand Down Expand Up @@ -964,6 +966,14 @@ func (e *Engine) handleFlowUpdate(config *mgmProto.FlowConfig) error {
return e.flowManager.Update(flowConfig)
}

func (e *Engine) handleMetricsUpdate(config *mgmProto.MetricsConfig) {
if config == nil {
return
}
log.Infof("received metrics configuration from management: enabled=%v", config.GetEnabled())
e.clientMetrics.UpdatePushFromMgm(e.ctx, config.GetEnabled())
}

func toFlowLoggerConfig(config *mgmProto.FlowConfig) (*nftypes.FlowConfig, error) {
if config.GetInterval() == nil {
return nil, errors.New("flow interval is nil")
Expand Down
7 changes: 7 additions & 0 deletions client/internal/metrics/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ func getMetricsInterval() time.Duration {
return interval
}

// isMetricsPushEnvSet returns true if NB_METRICS_PUSH_ENABLED is explicitly set (to any value).
// When set, the env var takes full precedence over management server configuration.
func isMetricsPushEnvSet() bool {
_, set := os.LookupEnv(EnvMetricsPushEnabled)
return set
}

func isForceSending() bool {
force, _ := strconv.ParseBool(os.Getenv(EnvMetricsForceSending))
return force
Expand Down
57 changes: 50 additions & 7 deletions client/internal/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func (c *ClientMetrics) Export(w io.Writer) error {
return c.impl.Export(w)
}

// StartPush starts periodic pushing of metrics with the given configuration
// StartPush starts periodic pushing of metrics with the given configuration.
// Precedence: PushConfig.ServerAddress > remote config server_url
func (c *ClientMetrics) StartPush(ctx context.Context, config PushConfig) {
if c == nil {
Expand All @@ -184,6 +184,53 @@ func (c *ClientMetrics) StartPush(ctx context.Context, config PushConfig) {
return
}

c.startPushLocked(ctx, config)
}

// StopPush stops the periodic metrics push.
func (c *ClientMetrics) StopPush() {
if c == nil {
return
}
c.pushMu.Lock()
defer c.pushMu.Unlock()

c.stopPushLocked()
}

// UpdatePushFromMgm updates metrics push based on management server configuration.
// If NB_METRICS_PUSH_ENABLED is explicitly set (true or false), management config is ignored.
// When unset, management controls whether push is enabled.
func (c *ClientMetrics) UpdatePushFromMgm(ctx context.Context, enabled bool) {
if c == nil {
return
}

if isMetricsPushEnvSet() {
log.Debugf("ignoring management config, env var is explicitly set: %s", EnvMetricsPushEnabled)
return
}

c.pushMu.Lock()
defer c.pushMu.Unlock()

if enabled {
if c.push != nil {
return
}
log.Infof("enabled metrics push by management")
c.startPushLocked(ctx, PushConfigFromEnv())
} else {
if c.push == nil {
return
}
log.Infof("disabled metrics push by management")
c.stopPushLocked()
}
}

// startPushLocked starts push. Caller must hold pushMu.
func (c *ClientMetrics) startPushLocked(ctx context.Context, config PushConfig) {
c.mu.RLock()
agentVersion := c.agentInfo.Version
peerID := c.agentInfo.peerID
Expand All @@ -208,12 +255,8 @@ func (c *ClientMetrics) StartPush(ctx context.Context, config PushConfig) {
c.push = push
}

func (c *ClientMetrics) StopPush() {
if c == nil {
return
}
c.pushMu.Lock()
defer c.pushMu.Unlock()
// stopPushLocked stops push. Caller must hold pushMu.
func (c *ClientMetrics) stopPushLocked() {
if c.push == nil {
return
}
Expand Down
19 changes: 16 additions & 3 deletions management/internals/shared/grpc/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ import (
"github.com/netbirdio/netbird/shared/sshauth"
)

func toNetbirdConfig(config *nbconfig.Config, turnCredentials *Token, relayToken *Token, extraSettings *types.ExtraSettings) *proto.NetbirdConfig {
func toNetbirdConfig(config *nbconfig.Config, turnCredentials *Token, relayToken *Token, extraSettings *types.ExtraSettings, settings *types.Settings) *proto.NetbirdConfig {
if config == nil {
return nil
if settings == nil {
return nil
}
return &proto.NetbirdConfig{
Metrics: &proto.MetricsConfig{
Enabled: settings.MetricsPushEnabled,
},
}
}

var stuns []*proto.HostConfig
Expand Down Expand Up @@ -85,6 +92,12 @@ func toNetbirdConfig(config *nbconfig.Config, turnCredentials *Token, relayToken
Relay: relayCfg,
}

if settings != nil {
nbConfig.Metrics = &proto.MetricsConfig{
Enabled: settings.MetricsPushEnabled,
}
}

return nbConfig
}

Expand Down Expand Up @@ -125,7 +138,7 @@ func ToSyncResponse(ctx context.Context, config *nbconfig.Config, httpConfig *nb
Checks: toProtocolChecks(ctx, checks),
}

nbConfig := toNetbirdConfig(config, turnCredentials, relayCredentials, extraSettings)
nbConfig := toNetbirdConfig(config, turnCredentials, relayCredentials, extraSettings, settings)
extendedConfig := integrationsConfig.ExtendNetBirdConfig(peer.ID, peerGroups, nbConfig, extraSettings)
response.NetbirdConfig = extendedConfig

Expand Down
2 changes: 1 addition & 1 deletion management/internals/shared/grpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ func (s *Server) prepareLoginResponse(ctx context.Context, peer *nbpeer.Peer, ne

// if peer has reached this point then it has logged in
loginResp := &proto.LoginResponse{
NetbirdConfig: toNetbirdConfig(s.config, nil, relayToken, nil),
NetbirdConfig: toNetbirdConfig(s.config, nil, relayToken, nil, settings),
PeerConfig: toPeerConfig(peer, netMap.Network, s.networkMapController.GetDNSDomain(settings), settings, s.config.HttpConfig, s.config.DeviceAuthorizationFlow, netMap.EnableSSH),
Checks: toProtocolChecks(ctx, postureChecks),
}
Expand Down
14 changes: 13 additions & 1 deletion management/server/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,8 @@ func (am *DefaultAccountManager) UpdateAccountSettings(ctx context.Context, acco
oldSettings.LazyConnectionEnabled != newSettings.LazyConnectionEnabled ||
oldSettings.DNSDomain != newSettings.DNSDomain ||
oldSettings.AutoUpdateVersion != newSettings.AutoUpdateVersion ||
oldSettings.AutoUpdateAlways != newSettings.AutoUpdateAlways {
oldSettings.AutoUpdateAlways != newSettings.AutoUpdateAlways ||
oldSettings.MetricsPushEnabled != newSettings.MetricsPushEnabled {
updateAccountPeers = true
}

Expand Down Expand Up @@ -379,6 +380,7 @@ func (am *DefaultAccountManager) UpdateAccountSettings(ctx context.Context, acco
am.handleAutoUpdateVersionSettings(ctx, oldSettings, newSettings, userID, accountID)
am.handleAutoUpdateAlwaysSettings(ctx, oldSettings, newSettings, userID, accountID)
am.handlePeerExposeSettings(ctx, oldSettings, newSettings, userID, accountID)
am.handleMetricsPushSettings(ctx, oldSettings, newSettings, userID, accountID)
if err = am.handleInactivityExpirationSettings(ctx, oldSettings, newSettings, userID, accountID); err != nil {
return nil, err
}
Expand Down Expand Up @@ -458,6 +460,16 @@ func (am *DefaultAccountManager) handleLazyConnectionSettings(ctx context.Contex
}
}

func (am *DefaultAccountManager) handleMetricsPushSettings(ctx context.Context, oldSettings, newSettings *types.Settings, userID, accountID string) {
if oldSettings.MetricsPushEnabled != newSettings.MetricsPushEnabled {
if newSettings.MetricsPushEnabled {
am.StoreEvent(ctx, userID, accountID, accountID, activity.AccountMetricsPushEnabled, nil)
} else {
am.StoreEvent(ctx, userID, accountID, accountID, activity.AccountMetricsPushDisabled, nil)
}
}
}

func (am *DefaultAccountManager) handlePeerLoginExpirationSettings(ctx context.Context, oldSettings, newSettings *types.Settings, userID, accountID string) {
if oldSettings.PeerLoginExpirationEnabled != newSettings.PeerLoginExpirationEnabled {
event := activity.AccountPeerLoginExpirationEnabled
Expand Down
8 changes: 8 additions & 0 deletions management/server/activity/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ const (
// AccountAutoUpdateAlwaysDisabled indicates that a user disabled always auto-update for the account
AccountAutoUpdateAlwaysDisabled Activity = 117

// AccountMetricsPushEnabled indicates that a user enabled metrics push for the account
AccountMetricsPushEnabled Activity = 121
// AccountMetricsPushDisabled indicates that a user disabled metrics push for the account
AccountMetricsPushDisabled Activity = 122

// DomainAdded indicates that a user added a custom domain
DomainAdded Activity = 118
// DomainDeleted indicates that a user deleted a custom domain
Expand Down Expand Up @@ -379,6 +384,9 @@ var activityMap = map[Activity]Code{
AccountPeerExposeEnabled: {"Account peer expose enabled", "account.setting.peer.expose.enable"},
AccountPeerExposeDisabled: {"Account peer expose disabled", "account.setting.peer.expose.disable"},

AccountMetricsPushEnabled: {"Account metrics push enabled", "account.setting.metrics.push.enable"},
AccountMetricsPushDisabled: {"Account metrics push disabled", "account.setting.metrics.push.disable"},

DomainAdded: {"Domain added", "domain.add"},
DomainDeleted: {"Domain deleted", "domain.delete"},
DomainValidated: {"Domain validated", "domain.validate"},
Expand Down
4 changes: 4 additions & 0 deletions management/server/http/handlers/accounts/accounts_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ func (h *handler) updateAccountRequestSettings(req api.PutApiAccountsAccountIdJS
if req.Settings.AutoUpdateAlways != nil {
returnSettings.AutoUpdateAlways = *req.Settings.AutoUpdateAlways
}
if req.Settings.MetricsPushEnabled != nil {
returnSettings.MetricsPushEnabled = *req.Settings.MetricsPushEnabled
}

return returnSettings, nil
}
Expand Down Expand Up @@ -352,6 +355,7 @@ func toAccountResponse(accountID string, settings *types.Settings, meta *types.A
DnsDomain: &settings.DNSDomain,
AutoUpdateVersion: &settings.AutoUpdateVersion,
AutoUpdateAlways: &settings.AutoUpdateAlways,
MetricsPushEnabled: &settings.MetricsPushEnabled,
EmbeddedIdpEnabled: &settings.EmbeddedIdpEnabled,
LocalAuthDisabled: &settings.LocalAuthDisabled,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func TestAccounts_AccountsHandler(t *testing.T) {
DnsDomain: sr(""),
AutoUpdateAlways: br(false),
AutoUpdateVersion: sr(""),
MetricsPushEnabled: br(false),
EmbeddedIdpEnabled: br(false),
LocalAuthDisabled: br(false),
},
Expand All @@ -149,6 +150,7 @@ func TestAccounts_AccountsHandler(t *testing.T) {
DnsDomain: sr(""),
AutoUpdateAlways: br(false),
AutoUpdateVersion: sr(""),
MetricsPushEnabled: br(false),
EmbeddedIdpEnabled: br(false),
LocalAuthDisabled: br(false),
},
Expand All @@ -175,6 +177,7 @@ func TestAccounts_AccountsHandler(t *testing.T) {
DnsDomain: sr(""),
AutoUpdateAlways: br(false),
AutoUpdateVersion: sr("latest"),
MetricsPushEnabled: br(false),
EmbeddedIdpEnabled: br(false),
LocalAuthDisabled: br(false),
},
Expand All @@ -201,6 +204,7 @@ func TestAccounts_AccountsHandler(t *testing.T) {
DnsDomain: sr(""),
AutoUpdateAlways: br(false),
AutoUpdateVersion: sr(""),
MetricsPushEnabled: br(false),
EmbeddedIdpEnabled: br(false),
LocalAuthDisabled: br(false),
},
Expand All @@ -227,6 +231,7 @@ func TestAccounts_AccountsHandler(t *testing.T) {
DnsDomain: sr(""),
AutoUpdateAlways: br(false),
AutoUpdateVersion: sr(""),
MetricsPushEnabled: br(false),
EmbeddedIdpEnabled: br(false),
LocalAuthDisabled: br(false),
},
Expand All @@ -253,6 +258,7 @@ func TestAccounts_AccountsHandler(t *testing.T) {
DnsDomain: sr(""),
AutoUpdateAlways: br(false),
AutoUpdateVersion: sr(""),
MetricsPushEnabled: br(false),
EmbeddedIdpEnabled: br(false),
LocalAuthDisabled: br(false),
},
Expand Down
6 changes: 5 additions & 1 deletion management/server/peer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,11 @@ func testUpdateAccountPeers(t *testing.T) {

for _, channel := range peerChannels {
update := <-channel
assert.Nil(t, update.Update.NetbirdConfig)
assert.NotNil(t, update.Update.NetbirdConfig)
assert.Nil(t, update.Update.NetbirdConfig.Stuns)
assert.Nil(t, update.Update.NetbirdConfig.Turns)
assert.Nil(t, update.Update.NetbirdConfig.Signal)
assert.Nil(t, update.Update.NetbirdConfig.Relay)
assert.Equal(t, tc.peers, len(update.Update.NetworkMap.RemotePeers))
assert.Equal(t, tc.peers*2, len(update.Update.NetworkMap.FirewallRules))
}
Expand Down
4 changes: 4 additions & 0 deletions management/server/types/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ type Settings struct {
// when false, updates require user interaction from the UI
AutoUpdateAlways bool `gorm:"default:false"`

// MetricsPushEnabled globally enables or disables client metrics push for the account
MetricsPushEnabled bool `gorm:"default:false"`

// EmbeddedIdpEnabled indicates if the embedded identity provider is enabled.
// This is a runtime-only field, not stored in the database.
EmbeddedIdpEnabled bool `gorm:"-"`
Expand Down Expand Up @@ -96,6 +99,7 @@ func (s *Settings) Copy() *Settings {
NetworkRange: s.NetworkRange,
AutoUpdateVersion: s.AutoUpdateVersion,
AutoUpdateAlways: s.AutoUpdateAlways,
MetricsPushEnabled: s.MetricsPushEnabled,
EmbeddedIdpEnabled: s.EmbeddedIdpEnabled,
LocalAuthDisabled: s.LocalAuthDisabled,
}
Expand Down
4 changes: 4 additions & 0 deletions shared/management/http/api/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ components:
description: When true, updates are installed automatically in the background. When false, updates require user interaction from the UI.
type: boolean
example: false
metrics_push_enabled:
description: Enables or disables client metrics push for all peers in the account
type: boolean
example: false
embedded_idp_enabled:
description: Indicates whether the embedded identity provider (Dex) is enabled for this account. This is a read-only field.
type: boolean
Expand Down
3 changes: 3 additions & 0 deletions shared/management/http/api/types.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading