mirror of
https://github.com/tailscale/tailscale.git
synced 2025-05-12 18:28:30 +00:00

updates tailscale/corp#28092 Adds metrics for various client events: * Enabling an exit node * Enabling a mullvad exit node * Enabling a preferred exit node * Setting WantRunning to true/false * Requesting a bug report ID * Profile counts * Profile deletions * Captive portal detection Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
101 lines
3.7 KiB
Go
101 lines
3.7 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package ipnlocal
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"tailscale.com/ipn"
|
|
"tailscale.com/tailcfg"
|
|
"tailscale.com/util/clientmetric"
|
|
)
|
|
|
|
// Counter metrics for edit/change events
|
|
var (
|
|
// metricExitNodeEnabled is incremented when the user enables an exit node independent of the node's characteristics.
|
|
metricExitNodeEnabled = clientmetric.NewCounter("prefs_exit_node_enabled")
|
|
// metricExitNodeEnabledSuggested is incremented when the user enables the suggested exit node.
|
|
metricExitNodeEnabledSuggested = clientmetric.NewCounter("prefs_exit_node_enabled_suggested")
|
|
// metricExitNodeEnabledMullvad is incremented when the user enables a Mullvad exit node.
|
|
metricExitNodeEnabledMullvad = clientmetric.NewCounter("prefs_exit_node_enabled_mullvad")
|
|
// metricWantRunningEnabled is incremented when WantRunning transitions from false to true.
|
|
metricWantRunningEnabled = clientmetric.NewCounter("prefs_want_running_enabled")
|
|
// metricWantRunningDisabled is incremented when WantRunning transitions from true to false.
|
|
metricWantRunningDisabled = clientmetric.NewCounter("prefs_want_running_disabled")
|
|
)
|
|
|
|
type exitNodeProperty string
|
|
|
|
const (
|
|
exitNodeTypePreferred exitNodeProperty = "suggested" // The exit node is the last suggested exit node
|
|
exitNodeTypeMullvad exitNodeProperty = "mullvad" // The exit node is a Mullvad exit node
|
|
)
|
|
|
|
// prefsMetricsEditEvent encapsulates information needed to record metrics related
|
|
// to any changes to preferences.
|
|
type prefsMetricsEditEvent struct {
|
|
change *ipn.MaskedPrefs // the preference mask used to update the preferences
|
|
pNew ipn.PrefsView // new preferences (after ApplyUpdates)
|
|
pOld ipn.PrefsView // old preferences (before ApplyUpdates)
|
|
node *nodeBackend // the node the event is associated with
|
|
lastSuggestedExitNode tailcfg.StableNodeID // the last suggested exit node
|
|
}
|
|
|
|
// record records changes to preferences as clientmetrics.
|
|
func (e *prefsMetricsEditEvent) record() error {
|
|
if e.change == nil || e.node == nil {
|
|
return errors.New("prefsMetricsEditEvent: missing required fields")
|
|
}
|
|
|
|
// Record up/down events.
|
|
if e.change.WantRunningSet && (e.pNew.WantRunning() != e.pOld.WantRunning()) {
|
|
if e.pNew.WantRunning() {
|
|
metricWantRunningEnabled.Add(1)
|
|
} else {
|
|
metricWantRunningDisabled.Add(1)
|
|
}
|
|
}
|
|
|
|
// Record any changes to exit node settings.
|
|
if e.change.ExitNodeIDSet || e.change.ExitNodeIPSet {
|
|
if exitNodeTypes, ok := e.exitNodeTypeLocked(e.pNew.ExitNodeID()); ok {
|
|
// We have switched to a valid exit node if ok is true.
|
|
metricExitNodeEnabled.Add(1)
|
|
|
|
// We may have some additional characteristics we should also record.
|
|
for _, t := range exitNodeTypes {
|
|
switch t {
|
|
case exitNodeTypePreferred:
|
|
metricExitNodeEnabledSuggested.Add(1)
|
|
case exitNodeTypeMullvad:
|
|
metricExitNodeEnabledMullvad.Add(1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// exitNodeTypesLocked returns type of exit node for the given stable ID.
|
|
// An exit node may have multiple type (can be both mullvad and preferred
|
|
// simultaneously for example).
|
|
//
|
|
// This will return ok as true if the supplied stable ID resolves to a known peer,
|
|
// false otherwise. The caller is responsible for ensuring that the id belongs to
|
|
// an exit node.
|
|
func (e *prefsMetricsEditEvent) exitNodeTypeLocked(id tailcfg.StableNodeID) (_ []exitNodeProperty, isNode bool) {
|
|
var peer tailcfg.NodeView
|
|
var t []exitNodeProperty
|
|
|
|
if peer, isNode = e.node.PeerByStableID(id); isNode {
|
|
if tailcfg.StableNodeID(id) == e.lastSuggestedExitNode {
|
|
t = append(t, exitNodeTypePreferred)
|
|
}
|
|
if peer.IsWireGuardOnly() {
|
|
t = append(t, exitNodeTypeMullvad)
|
|
}
|
|
}
|
|
return t, isNode
|
|
}
|