|
|
@ -232,12 +232,16 @@ func (h *Handler) serveBugReport(w http.ResponseWriter, r *http.Request) {
|
|
|
|
return
|
|
|
|
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() {
|
|
|
|
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)
|
|
|
|
h.logf("user bugreport note: %s", note)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hi, _ := json.Marshal(hostinfo.New())
|
|
|
|
hi, _ := json.Marshal(hostinfo.New())
|
|
|
@ -247,11 +251,62 @@ func (h *Handler) serveBugReport(w http.ResponseWriter, r *http.Request) {
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
h.logf("user bugreport health: ok")
|
|
|
|
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: "))
|
|
|
|
h.b.Doctor(r.Context(), logger.WithPrefix(h.logf, "diag: "))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
|
|
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) {
|
|
|
|
func (h *Handler) serveWhoIs(w http.ResponseWriter, r *http.Request) {
|
|
|
|