mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 21:27:31 +00:00
cmd/tailscale, logtail: add 'tailscale debug daemon-logs' logtail mechanism
Fixes #6836 Change-Id: Ia6eb39ff8972e1aa149aeeb63844a97497c2cf04 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
5f96d6211a
commit
b657187a69
@@ -34,6 +34,7 @@ import (
|
||||
"tailscale.com/ipn"
|
||||
"tailscale.com/ipn/ipnlocal"
|
||||
"tailscale.com/ipn/ipnstate"
|
||||
"tailscale.com/logtail"
|
||||
"tailscale.com/net/netutil"
|
||||
"tailscale.com/safesocket"
|
||||
"tailscale.com/tailcfg"
|
||||
@@ -77,6 +78,7 @@ var handler = map[string]localAPIHandler{
|
||||
"id-token": (*Handler).serveIDToken,
|
||||
"login-interactive": (*Handler).serveLoginInteractive,
|
||||
"logout": (*Handler).serveLogout,
|
||||
"logtap": (*Handler).serveLogTap,
|
||||
"metrics": (*Handler).serveMetrics,
|
||||
"ping": (*Handler).servePing,
|
||||
"prefs": (*Handler).servePrefs,
|
||||
@@ -421,6 +423,45 @@ func (h *Handler) serveGoroutines(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(buf)
|
||||
}
|
||||
|
||||
// serveLogTap taps into the tailscaled/logtail server output and streams
|
||||
// it to the client.
|
||||
func (h *Handler) serveLogTap(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
// Require write access (~root) as the logs could contain something
|
||||
// sensitive.
|
||||
if !h.PermitWrite {
|
||||
http.Error(w, "logtap access denied", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "GET required", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
f, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
http.Error(w, "streaming unsupported", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
io.WriteString(w, `{"text":"[logtap connected]\n"}`+"\n")
|
||||
f.Flush()
|
||||
|
||||
msgc := make(chan string, 16)
|
||||
unreg := logtail.RegisterLogTap(msgc)
|
||||
defer unreg()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case msg := <-msgc:
|
||||
io.WriteString(w, msg)
|
||||
f.Flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) serveMetrics(w http.ResponseWriter, r *http.Request) {
|
||||
// Require write access out of paranoia that the metrics
|
||||
// might contain something sensitive.
|
||||
|
Reference in New Issue
Block a user