Skip to content

Commit 9545e36

Browse files
committed
cmd/tailscale/cli: add 'tailscale metrics' command
- `tailscale metrics print`: to show metric values in console - `tailscale metrics write`: to write metrics to a file (with a tempfile & rename dance, which is atomic on Unix). Also, remove the `TS_DEBUG_USER_METRICS` envknob as we are getting more confident in these metrics. Updates tailscale/corp#22075 Signed-off-by: Anton Tolchanov <[email protected]>
1 parent 38af62c commit 9545e36

File tree

3 files changed

+91
-9
lines changed

3 files changed

+91
-9
lines changed

cmd/tailscale/cli/cli.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ change in the future.
189189
ipCmd,
190190
dnsCmd,
191191
statusCmd,
192+
metricsCmd,
192193
pingCmd,
193194
ncCmd,
194195
sshCmd,

cmd/tailscale/cli/metrics.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright (c) Tailscale Inc & AUTHORS
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
package cli
5+
6+
import (
7+
"context"
8+
"errors"
9+
"fmt"
10+
"strings"
11+
12+
"github.com/peterbourgon/ff/v3/ffcli"
13+
"tailscale.com/atomicfile"
14+
)
15+
16+
var metricsCmd = &ffcli.Command{
17+
Name: "metrics",
18+
ShortHelp: "Show Tailscale metrics",
19+
LongHelp: strings.TrimSpace(`
20+
21+
The 'tailscale metrics' command shows Tailscale user-facing metrics (as opposed
22+
to internal metrics printed by 'tailscale debug metrics').
23+
24+
For more information about Tailscale metrics, refer to
25+
https://tailscale.com/s/client-metrics
26+
27+
`),
28+
ShortUsage: "tailscale metrics <subcommand> [flags]",
29+
UsageFunc: usageFuncNoDefaultValues,
30+
Exec: runMetricsNoSubcommand,
31+
Subcommands: []*ffcli.Command{
32+
{
33+
Name: "print",
34+
ShortUsage: "tailscale metrics print",
35+
Exec: runMetricsPrint,
36+
ShortHelp: "Prints current metric values in the Prometheus text exposition format",
37+
},
38+
{
39+
Name: "write",
40+
ShortUsage: "tailscale metrics write <path>",
41+
Exec: runMetricsWrite,
42+
ShortHelp: "Writes metric values to a file",
43+
LongHelp: strings.TrimSpace(`
44+
45+
The 'tailscale metrics write' command writes metric values to a text file provided as its
46+
only argument. It's meant to be used alongside Prometheus node exporter, allowing Tailscale
47+
metrics to be consumed and exported by the textfile collector.
48+
49+
As an example, to export Tailscale metrics on an Ubuntu system running node exporter, you
50+
can regularly run 'tailscale metrics write /var/lib/prometheus/node-exporter/tailscaled.prom'
51+
using cron or a systemd timer.
52+
53+
`),
54+
},
55+
},
56+
}
57+
58+
// runMetricsNoSubcommand prints metric values if no subcommand is specified.
59+
func runMetricsNoSubcommand(ctx context.Context, args []string) error {
60+
if len(args) > 0 {
61+
return fmt.Errorf("tailscale metrics: unknown subcommand: %s", args[0])
62+
}
63+
64+
return runMetricsPrint(ctx, args)
65+
}
66+
67+
// runMetricsPrint prints metric values to stdout.
68+
func runMetricsPrint(ctx context.Context, args []string) error {
69+
out, err := localClient.UserMetrics(ctx)
70+
if err != nil {
71+
return err
72+
}
73+
Stdout.Write(out)
74+
return nil
75+
}
76+
77+
// runMetricsWrite writes metric values to a file.
78+
func runMetricsWrite(ctx context.Context, args []string) error {
79+
if len(args) != 1 {
80+
return errors.New("usage: tailscale metrics write <path>")
81+
}
82+
path := args[0]
83+
out, err := localClient.UserMetrics(ctx)
84+
if err != nil {
85+
return err
86+
}
87+
return atomicfile.WriteFile(path, out, 0644)
88+
}

ipn/localapi/localapi.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ import (
6262
"tailscale.com/util/osdiag"
6363
"tailscale.com/util/progresstracking"
6464
"tailscale.com/util/rands"
65-
"tailscale.com/util/testenv"
6665
"tailscale.com/version"
6766
"tailscale.com/wgengine/magicsock"
6867
)
@@ -570,15 +569,9 @@ func (h *Handler) serveMetrics(w http.ResponseWriter, r *http.Request) {
570569
clientmetric.WritePrometheusExpositionFormat(w)
571570
}
572571

573-
// TODO(kradalby): Remove this once we have landed on a final set of
574-
// metrics to export to clients and consider the metrics stable.
575-
var debugUsermetricsEndpoint = envknob.RegisterBool("TS_DEBUG_USER_METRICS")
576-
572+
// serveUserMetrics returns user-facing metrics in Prometheus text
573+
// exposition format.
577574
func (h *Handler) serveUserMetrics(w http.ResponseWriter, r *http.Request) {
578-
if !testenv.InTest() && !debugUsermetricsEndpoint() {
579-
http.Error(w, "usermetrics debug flag not enabled", http.StatusForbidden)
580-
return
581-
}
582575
h.b.UserMetricsRegistry().Handler(w, r)
583576
}
584577

0 commit comments

Comments
 (0)