|
|
|
|
@ -232,12 +232,16 @@ func (h *Handler) serveBugReport(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
logMarker := fmt.Sprintf("BUG-%v-%v-%v", h.backendLogID, time.Now().UTC().Format("20060102150405Z"), randHex(8)) |
|
|
|
|
logMarker := func() string { |
|
|
|
|
return fmt.Sprintf("BUG-%v-%v-%v", h.backendLogID, time.Now().UTC().Format("20060102150405Z"), randHex(8)) |
|
|
|
|
} |
|
|
|
|
if envknob.NoLogsNoSupport() { |
|
|
|
|
logMarker = "BUG-NO-LOGS-NO-SUPPORT-this-node-has-had-its-logging-disabled" |
|
|
|
|
logMarker = func() string { return "BUG-NO-LOGS-NO-SUPPORT-this-node-has-had-its-logging-disabled" } |
|
|
|
|
} |
|
|
|
|
h.logf("user bugreport: %s", logMarker) |
|
|
|
|
if note := r.FormValue("note"); len(note) > 0 { |
|
|
|
|
|
|
|
|
|
startMarker := logMarker() |
|
|
|
|
h.logf("user bugreport: %s", startMarker) |
|
|
|
|
if note := r.URL.Query().Get("note"); len(note) > 0 { |
|
|
|
|
h.logf("user bugreport note: %s", note) |
|
|
|
|
} |
|
|
|
|
hi, _ := json.Marshal(hostinfo.New()) |
|
|
|
|
@ -247,11 +251,62 @@ func (h *Handler) serveBugReport(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
} else { |
|
|
|
|
h.logf("user bugreport health: ok") |
|
|
|
|
} |
|
|
|
|
if defBool(r.FormValue("diagnose"), false) { |
|
|
|
|
if defBool(r.URL.Query().Get("diagnose"), false) { |
|
|
|
|
h.b.Doctor(r.Context(), logger.WithPrefix(h.logf, "diag: ")) |
|
|
|
|
} |
|
|
|
|
w.Header().Set("Content-Type", "text/plain") |
|
|
|
|
fmt.Fprintln(w, logMarker) |
|
|
|
|
fmt.Fprintln(w, startMarker) |
|
|
|
|
|
|
|
|
|
// Nothing else to do if we're not in record mode; we wrote the marker
|
|
|
|
|
// above, so we can just finish our response now.
|
|
|
|
|
if !defBool(r.URL.Query().Get("record"), false) { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
until := time.Now().Add(12 * time.Hour) |
|
|
|
|
|
|
|
|
|
var changed map[string]bool |
|
|
|
|
for _, component := range []string{"magicsock"} { |
|
|
|
|
if h.b.GetComponentDebugLogging(component).IsZero() { |
|
|
|
|
if err := h.b.SetComponentDebugLogging(component, until); err != nil { |
|
|
|
|
h.logf("bugreport: error setting component %q logging: %v", component, err) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
mak.Set(&changed, component, true) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
defer func() { |
|
|
|
|
for component := range changed { |
|
|
|
|
h.b.SetComponentDebugLogging(component, time.Time{}) |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
// NOTE(andrew): if we have anything else we want to do while recording
|
|
|
|
|
// a bugreport, we can add it here.
|
|
|
|
|
|
|
|
|
|
// Read from the client; this will also return when the client closes
|
|
|
|
|
// the connection.
|
|
|
|
|
var buf [1]byte |
|
|
|
|
_, err := r.Body.Read(buf[:]) |
|
|
|
|
|
|
|
|
|
switch { |
|
|
|
|
case err == nil: |
|
|
|
|
// good
|
|
|
|
|
case errors.Is(err, io.EOF): |
|
|
|
|
// good
|
|
|
|
|
case errors.Is(err, io.ErrUnexpectedEOF): |
|
|
|
|
// this happens when Ctrl-C'ing the tailscale client; don't
|
|
|
|
|
// bother logging an error
|
|
|
|
|
default: |
|
|
|
|
// Log but continue anyway.
|
|
|
|
|
h.logf("user bugreport: error reading body: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Generate another log marker and return it to the client.
|
|
|
|
|
endMarker := logMarker() |
|
|
|
|
h.logf("user bugreport end: %s", endMarker) |
|
|
|
|
fmt.Fprintln(w, endMarker) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (h *Handler) serveWhoIs(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
|