mirror of https://github.com/tailscale/tailscale/
health, ipn/ipnlocal: add metrics for various client events (#15828)
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>pull/15934/head
parent
b1c2860485
commit
7d6d2b4c50
@ -0,0 +1,99 @@
|
||||
// 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.exitNodeType(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) exitNodeType(id tailcfg.StableNodeID) (props []exitNodeProperty, isNode bool) {
|
||||
var peer tailcfg.NodeView
|
||||
|
||||
if peer, isNode = e.node.PeerByStableID(id); isNode {
|
||||
if tailcfg.StableNodeID(id) == e.lastSuggestedExitNode {
|
||||
props = append(props, exitNodeTypePreferred)
|
||||
}
|
||||
if peer.IsWireGuardOnly() {
|
||||
props = append(props, exitNodeTypeMullvad)
|
||||
}
|
||||
}
|
||||
return props, isNode
|
||||
}
|
||||
Loading…
Reference in New Issue