You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailscale/net/sockstats/sockstats.go

122 lines
4.3 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Package sockstats collects statistics about network sockets used by
// the Tailscale client. The context where sockets are used must be
// instrumented with the WithSockStats() function.
//
// Only available on POSIX platforms when built with Tailscale's fork of Go.
package sockstats
import (
"context"
"tailscale.com/net/interfaces"
"tailscale.com/types/logger"
)
// SockStats contains statistics for sockets instrumented with the
// WithSockStats() function
type SockStats struct {
Stats map[Label]SockStat
CurrentInterfaceCellular bool
}
// SockStat contains the sent and received bytes for a socket instrumented with
// the WithSockStats() function.
type SockStat struct {
TxBytes uint64
RxBytes uint64
}
// Label is an identifier for a socket that stats are collected for. A finite
// set of values that may be used to label a socket to encourage grouping and
// to make storage more efficient.
type Label uint8
//go:generate go run golang.org/x/tools/cmd/stringer -type Label -trimprefix Label
// Labels are named after the package and function/struct that uses the socket.
// Values may be persisted and thus existing entries should not be re-numbered.
const (
LabelControlClientAuto Label = 0 // control/controlclient/auto.go
LabelControlClientDialer Label = 1 // control/controlhttp/client.go
LabelDERPHTTPClient Label = 2 // derp/derphttp/derphttp_client.go
LabelLogtailLogger Label = 3 // logtail/logtail.go
LabelDNSForwarderDoH Label = 4 // net/dns/resolver/forwarder.go
LabelDNSForwarderUDP Label = 5 // net/dns/resolver/forwarder.go
LabelNetcheckClient Label = 6 // net/netcheck/netcheck.go
LabelPortmapperClient Label = 7 // net/portmapper/portmapper.go
LabelMagicsockConnUDP4 Label = 8 // wgengine/magicsock/magicsock.go
LabelMagicsockConnUDP6 Label = 9 // wgengine/magicsock/magicsock.go
LabelNetlogLogger Label = 10 // wgengine/netlog/logger.go
LabelSockstatlogLogger Label = 11 // log/sockstatlog/logger.go
)
// WithSockStats instruments a context so that sockets created with it will
// have their statistics collected.
func WithSockStats(ctx context.Context, label Label, logf logger.Logf) context.Context {
return withSockStats(ctx, label, logf)
}
// Get returns the current socket statistics.
func Get() *SockStats {
return get()
}
// InterfaceSockStats contains statistics for sockets instrumented with the
// WithSockStats() function, broken down by interface. The statistics may be a
// subset of the total if interfaces were added after the instrumented socket
// was created.
type InterfaceSockStats struct {
Stats map[Label]InterfaceSockStat
Interfaces []string
}
// InterfaceSockStat contains the per-interface sent and received bytes for a
// socket instrumented with the WithSockStats() function.
type InterfaceSockStat struct {
TxBytesByInterface map[string]uint64
RxBytesByInterface map[string]uint64
}
// GetWithInterfaces is a variant of Get that returns the current socket
// statistics broken down by interface. It is slightly more expensive than Get.
func GetInterfaces() *InterfaceSockStats {
return getInterfaces()
}
// ValidationSockStats contains external validation numbers for sockets
// instrumented with WithSockStats. It may be a subset of the all sockets,
// depending on what externa measurement mechanisms the platform supports.
type ValidationSockStats struct {
Stats map[Label]ValidationSockStat
}
// ValidationSockStat contains the validation bytes for a socket instrumented
// with WithSockStats.
type ValidationSockStat struct {
TxBytes uint64
RxBytes uint64
}
// GetValidation is a variant of Get that returns external validation numbers
// for stats. It is more expensive than Get and should be used in debug
// interfaces only.
func GetValidation() *ValidationSockStats {
return getValidation()
}
// LinkMonitor is the interface for the parts of wgengine/mointor's Mon that we
// need, to avoid the dependency.
type LinkMonitor interface {
InterfaceState() *interfaces.State
RegisterChangeCallback(interfaces.ChangeFunc) (unregister func())
}
// SetLinkMonitor configures the sockstats package to monitor the active
// interface, so that per-interface stats can be collected.
func SetLinkMonitor(lm LinkMonitor) {
setLinkMonitor(lm)
}