diff --git a/client/tailscale/tailscale.go b/client/tailscale/tailscale.go index 458b8652f..80f41ac4d 100644 --- a/client/tailscale/tailscale.go +++ b/client/tailscale/tailscale.go @@ -196,6 +196,12 @@ func Goroutines(ctx context.Context) ([]byte, error) { return get200(ctx, "/localapi/v0/goroutines") } +// DaemonMetrics returns the Tailscale daemon's metrics in +// the Prometheus text exposition format. +func DaemonMetrics(ctx context.Context) ([]byte, error) { + return get200(ctx, "/localapi/v0/metrics") +} + // Profile returns a pprof profile of the Tailscale daemon. func Profile(ctx context.Context, pprofType string, sec int) ([]byte, error) { var secArg string diff --git a/cmd/tailscale/cli/debug.go b/cmd/tailscale/cli/debug.go index 92653bd54..44b0b18a5 100644 --- a/cmd/tailscale/cli/debug.go +++ b/cmd/tailscale/cli/debug.go @@ -46,17 +46,22 @@ var debugCmd = &ffcli.Command{ Exec: runDaemonGoroutines, ShortHelp: "print tailscaled's goroutines", }, - &ffcli.Command{ + { + Name: "metrics", + Exec: runDaemonMetrics, + ShortHelp: "print tailscaled's metrics", + }, + { Name: "env", Exec: runEnv, ShortHelp: "print cmd/tailscale environment", }, - &ffcli.Command{ + { Name: "local-creds", Exec: runLocalCreds, ShortHelp: "print how to access Tailscale local API", }, - &ffcli.Command{ + { Name: "prefs", Exec: runPrefs, ShortHelp: "print prefs", @@ -66,7 +71,7 @@ var debugCmd = &ffcli.Command{ return fs })(), }, - &ffcli.Command{ + { Name: "watch-ipn", Exec: runWatchIPN, ShortHelp: "subscribe to IPN message bus", @@ -245,3 +250,12 @@ func runDaemonGoroutines(ctx context.Context, args []string) error { Stdout.Write(goroutines) return nil } + +func runDaemonMetrics(ctx context.Context, args []string) error { + out, err := tailscale.DaemonMetrics(ctx) + if err != nil { + return err + } + Stdout.Write(out) + return nil +}