summaryrefslogtreecommitdiffhomepage
path: root/tsweb
diff options
context:
space:
mode:
authorkari-ts <kari@tailscale.com>2025-03-19 11:28:04 -0700
committerkari-ts <kari@tailscale.com>2025-04-04 14:24:56 -0700
commit6d5c7b11913e09b061e863411ad488dc44a13870 (patch)
tree9e1789b5080ae4a92523611e49920dcb1102604b /tsweb
parentca50599c95e0a4cb7b4aab179e866e202f10c0c4 (diff)
parent3a2c92f08eac8cd8f50356ff288e40a28636ee42 (diff)
downloadtailscale-kari/taildropsaf.tar.xz
tailscale-kari/taildropsaf.zip
-check if Context.getExternalFilesDirs works as is for private dir
Diffstat (limited to 'tsweb')
-rw-r--r--tsweb/debug.go44
-rw-r--r--tsweb/promvarz/promvarz.go13
-rw-r--r--tsweb/promvarz/promvarz_test.go2
3 files changed, 49 insertions, 10 deletions
diff --git a/tsweb/debug.go b/tsweb/debug.go
index 9e6ce4df4..ac1981999 100644
--- a/tsweb/debug.go
+++ b/tsweb/debug.go
@@ -14,7 +14,7 @@ import (
"os"
"runtime"
- "tailscale.com/tsweb/promvarz"
+ "tailscale.com/feature"
"tailscale.com/tsweb/varz"
"tailscale.com/version"
)
@@ -34,8 +34,14 @@ type DebugHandler struct {
kvs []func(io.Writer) // output one <li>...</li> each, see KV()
urls []string // one <li>...</li> block with link each
sections []func(io.Writer, *http.Request) // invoked in registration order prior to outputting </body>
+ title string // title displayed on index page
}
+// PrometheusHandler is an optional hook to enable native Prometheus
+// support in the debug handler. It is disabled by default. Import the
+// tailscale.com/tsweb/promvarz package to enable this feature.
+var PrometheusHandler feature.Hook[func(*DebugHandler)]
+
// Debugger returns the DebugHandler registered on mux at /debug/,
// creating it if necessary.
func Debugger(mux *http.ServeMux) *DebugHandler {
@@ -44,14 +50,19 @@ func Debugger(mux *http.ServeMux) *DebugHandler {
return d
}
ret := &DebugHandler{
- mux: mux,
+ mux: mux,
+ title: fmt.Sprintf("%s debug", version.CmdName()),
}
mux.Handle("/debug/", ret)
ret.KVFunc("Uptime", func() any { return varz.Uptime() })
ret.KV("Version", version.Long())
ret.Handle("vars", "Metrics (Go)", expvar.Handler())
- ret.Handle("varz", "Metrics (Prometheus)", http.HandlerFunc(promvarz.Handler))
+ if PrometheusHandler.IsSet() {
+ PrometheusHandler.Get()(ret)
+ } else {
+ ret.Handle("varz", "Metrics (Prometheus)", http.HandlerFunc(varz.Handler))
+ }
// pprof.Index serves everything that runtime/pprof.Lookup finds:
// goroutine, threadcreate, heap, allocs, block, mutex
@@ -85,7 +96,7 @@ func (d *DebugHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
AddBrowserHeaders(w)
f := func(format string, args ...any) { fmt.Fprintf(w, format, args...) }
- f("<html><body><h1>%s debug</h1><ul>", version.CmdName())
+ f("<html><body><h1>%s</h1><ul>", html.EscapeString(d.title))
for _, kv := range d.kvs {
kv(w)
}
@@ -103,14 +114,20 @@ func (d *DebugHandler) handle(slug string, handler http.Handler) string {
return href
}
-// Handle registers handler at /debug/<slug> and creates a descriptive
-// entry in /debug/ for it.
+// Handle registers handler at /debug/<slug> and adds a link to it
+// on /debug/ with the provided description.
func (d *DebugHandler) Handle(slug, desc string, handler http.Handler) {
href := d.handle(slug, handler)
d.URL(href, desc)
}
-// HandleSilent registers handler at /debug/<slug>. It does not create
+// Handle registers handler at /debug/<slug> and adds a link to it
+// on /debug/ with the provided description.
+func (d *DebugHandler) HandleFunc(slug, desc string, handler http.HandlerFunc) {
+ d.Handle(slug, desc, handler)
+}
+
+// HandleSilent registers handler at /debug/<slug>. It does not add
// a descriptive entry in /debug/ for it. This should be used
// sparingly, for things that need to be registered but would pollute
// the list of debug links.
@@ -118,6 +135,14 @@ func (d *DebugHandler) HandleSilent(slug string, handler http.Handler) {
d.handle(slug, handler)
}
+// HandleSilent registers handler at /debug/<slug>. It does not add
+// a descriptive entry in /debug/ for it. This should be used
+// sparingly, for things that need to be registered but would pollute
+// the list of debug links.
+func (d *DebugHandler) HandleSilentFunc(slug string, handler http.HandlerFunc) {
+ d.HandleSilent(slug, handler)
+}
+
// KV adds a key/value list item to /debug/.
func (d *DebugHandler) KV(k string, v any) {
val := html.EscapeString(fmt.Sprintf("%v", v))
@@ -149,6 +174,11 @@ func (d *DebugHandler) Section(f func(w io.Writer, r *http.Request)) {
d.sections = append(d.sections, f)
}
+// Title sets the title at the top of the debug page.
+func (d *DebugHandler) Title(title string) {
+ d.title = title
+}
+
func gcHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("running GC...\n"))
if f, ok := w.(http.Flusher); ok {
diff --git a/tsweb/promvarz/promvarz.go b/tsweb/promvarz/promvarz.go
index d0e1e52ba..1d978c767 100644
--- a/tsweb/promvarz/promvarz.go
+++ b/tsweb/promvarz/promvarz.go
@@ -11,12 +11,21 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/expfmt"
+ "tailscale.com/tsweb"
"tailscale.com/tsweb/varz"
)
-// Handler returns Prometheus metrics exported by our expvar converter
+func init() {
+ tsweb.PrometheusHandler.Set(registerVarz)
+}
+
+func registerVarz(debug *tsweb.DebugHandler) {
+ debug.Handle("varz", "Metrics (Prometheus)", http.HandlerFunc(handler))
+}
+
+// handler returns Prometheus metrics exported by our expvar converter
// and the official Prometheus client.
-func Handler(w http.ResponseWriter, r *http.Request) {
+func handler(w http.ResponseWriter, r *http.Request) {
if err := gatherNativePrometheusMetrics(w); err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
diff --git a/tsweb/promvarz/promvarz_test.go b/tsweb/promvarz/promvarz_test.go
index a3f4e66f1..9f91b5d12 100644
--- a/tsweb/promvarz/promvarz_test.go
+++ b/tsweb/promvarz/promvarz_test.go
@@ -23,7 +23,7 @@ func TestHandler(t *testing.T) {
testVar1.Set(42)
testVar2.Set(4242)
- svr := httptest.NewServer(http.HandlerFunc(Handler))
+ svr := httptest.NewServer(http.HandlerFunc(handler))
defer svr.Close()
want := `