diff --git a/cmd/stcrashreceiver/sentry.go b/cmd/stcrashreceiver/sentry.go index 2480b3cf5..7affc1e5f 100644 --- a/cmd/stcrashreceiver/sentry.go +++ b/cmd/stcrashreceiver/sentry.go @@ -31,12 +31,14 @@ var ( clientsMut sync.Mutex ) -func sendReport(dsn, path string, report []byte) error { +func sendReport(dsn, path string, report []byte, userID string) error { pkt, err := parseReport(path, report) if err != nil { return err } + pkt.Interfaces = append(pkt.Interfaces, &raven.User{ID: userID}) + clientsMut.Lock() defer clientsMut.Unlock() diff --git a/cmd/stcrashreceiver/stcrashreceiver.go b/cmd/stcrashreceiver/stcrashreceiver.go index f28a28ee7..9088cbe2e 100644 --- a/cmd/stcrashreceiver/stcrashreceiver.go +++ b/cmd/stcrashreceiver/stcrashreceiver.go @@ -16,14 +16,19 @@ import ( "bytes" "compress/gzip" "flag" + "fmt" "io" "io/ioutil" "log" + "net" "net/http" "os" "path" "path/filepath" "strings" + "time" + + "github.com/syncthing/syncthing/lib/sha256" ) const maxRequestSize = 1 << 20 // 1 MiB @@ -145,9 +150,12 @@ func (r *crashReceiver) servePut(reportID, fullPath string, w http.ResponseWrite // Send the report to Sentry if r.dsn != "" { + // Remote ID + user := userIDFor(req) + go func() { // There's no need for the client to have to wait for this part. - if err := sendReport(r.dsn, reportID, bs); err != nil { + if err := sendReport(r.dsn, reportID, bs, user); err != nil { log.Println("Failed to send report:", err) } }() @@ -158,3 +166,20 @@ func (r *crashReceiver) servePut(reportID, fullPath string, w http.ResponseWrite func (r *crashReceiver) dirFor(base string) string { return filepath.Join(base[0:2], base[2:4]) } + +// userIDFor returns a string we can use as the user ID for the purpose of +// counting affected users. It's the truncated hash of a salt, the user +// remote IP, and the current month. +func userIDFor(req *http.Request) string { + addr := req.RemoteAddr + if fwd := req.Header.Get("x-forwarded-for"); fwd != "" { + addr = fwd + } + if host, _, err := net.SplitHostPort(addr); err == nil { + addr = host + } + now := time.Now().Format("200601") + salt := "stcrashreporter" + hash := sha256.Sum256([]byte(salt + addr + now)) + return fmt.Sprintf("%x", hash[:8]) +}