Repository: syncthing/syncthing
File: cmd/syncthing/gui.go (Go)

Code before:
	}, "", "  ")
	arrayFile = append(arrayFile, fileEntry{name: "versionPlatform.json", data: versionPlatform})

	// Report Data as a JSON
	usageReportingData, _ := json.MarshalIndent(reportData(s.cfg, s.model, s.connectionsService, usageReportVersion, true), "", "  ")
	arrayFile = append(arrayFile, fileEntry{name: "usageReportingData.json", data: usageReportingData})

	// Heap and CPU Proofs as a pprof extension
	var heapBuffer, cpuBuffer bytes.Buffer
	filename := fmt.Sprintf("syncthing-heap-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, Version, time.Now().Format("150405")) // hhmmss
	runtime.GC()
	pprof.WriteHeapProfile(&heapBuffer)
	arrayFile = append(arrayFile, fileEntry{name: filename, data: heapBuffer.Bytes()})

	const duration = 4 * time.Second
	filename = fmt.Sprintf("syncthing-cpu-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, Version, time.Now().Format("150405")) // hhmmss
	pprof.StartCPUProfile(&cpuBuffer)
	time.Sleep(duration)
	pprof.StopCPUProfile()
	arrayFile = append(arrayFile, fileEntry{name: filename, data: cpuBuffer.Bytes()})

	output := fmt.Sprintf("support-bundle-%s.zip", time.Now().Format("2006-01-02T15.04.05"))
	newfilepath := filepath.Join(baseDirs["config"], output)
	newfile, err := os.Create(newfilepath)
	if err != nil {
		l.Warnf("Support bundle zip %s not created", output)
	}
	defer newfile.Close()

	// Add files to buffer zip
	var newfileBuffer bytes.Buffer
	zipBuffer(&newfileBuffer, arrayFile)

	// Write buffer zip to local zip file (back up)
	wr := bufio.NewWriter(newfile)
	newfileBufferS := newfileBuffer.String()
	wr.WriteString(newfileBufferS)
	wr.Flush()

	// Serve the buffer zip to client for download
	w.Header().Set("Content-Type", "application/zip")
	w.Header().Set("Content-Disposition", "attachment; filename="+output)
	io.Copy(w, strings.NewReader(newfileBufferS))
}

func (s *apiService) getSystemHTTPMetrics(w http.ResponseWriter, r *http.Request) {
	stats := make(map[string]interface{})
	metrics.Each(func(name string, intf interface{}) {
		if m, ok := intf.(*metrics.StandardTimer); ok {
			pct := m.Percentiles([]float64{0.50, 0.95, 0.99})
			for i := range pct {

Review comment (suggestion):
If we couldn't create the file we are in trouble, as the rest of the function won't work, the `newfile.Close()` will panic, etc.

I suggest changing the order a little bit. Create the zip file in memory as you do, and only after that attempt to write it to disk. You can use the convenience function `ioutil.WriteFile` for that. If that returns an error, no biggie - just log as you do now and proceed. The user will at least get the zip file in their browser.

Code after:
		for _, f := range panicFiles {
			if panicFile, err := ioutil.ReadFile(f); err != nil {
				l.Warnf("Support bundle: failed to load %s: %s", filepath.Base(f), err)
			} else {
				files = append(files, fileEntry{name: filepath.Base(f), data: panicFile})
			}
		}
	}

	// Version and platform information as a JSON
	if versionPlatform, err := json.MarshalIndent(map[string]string{
		"now":         time.Now().Format(time.RFC3339),
		"version":     Version,
		"codename":    Codename,
		"longVersion": LongVersion,
		"os":          runtime.GOOS,
		"arch":        runtime.GOARCH,
	}, "", "  "); err == nil {
		files = append(files, fileEntry{name: "version-platform.json.txt", data: versionPlatform})
	} else {
		l.Warnln("Failed to create versionPlatform.json: ", err)
	}

	// Report Data as a JSON
	if usageReportingData, err := json.MarshalIndent(reportData(s.cfg, s.model, s.connectionsService, usageReportVersion, true), "", "  "); err != nil {
		l.Warnln("Support bundle: failed to create versionPlatform.json:", err)
	} else {
		files = append(files, fileEntry{name: "usage-reporting.json.txt", data: usageReportingData})
	}

	// Heap and CPU Proofs as a pprof extension
	var heapBuffer, cpuBuffer bytes.Buffer
	filename := fmt.Sprintf("syncthing-heap-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, Version, time.Now().Format("150405")) // hhmmss
	runtime.GC()
	pprof.WriteHeapProfile(&heapBuffer)
	files = append(files, fileEntry{name: filename, data: heapBuffer.Bytes()})

	const duration = 4 * time.Second
	filename = fmt.Sprintf("syncthing-cpu-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, Version, time.Now().Format("150405")) // hhmmss
	pprof.StartCPUProfile(&cpuBuffer)
	time.Sleep(duration)
	pprof.StopCPUProfile()
	files = append(files, fileEntry{name: filename, data: cpuBuffer.Bytes()})

	// Add buffer files to buffer zip
	var zipFilesBuffer bytes.Buffer
	if err := writeZip(&zipFilesBuffer, files); err != nil {
		l.Warnln("Support bundle: failed to create support bundle zip:", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}