github.com/kayoticsully/syncthing@v0.8.9-0.20140724133906-c45a2fdc03f8/cmd/syncthing/usage_report.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "crypto/sha256" 7 "encoding/json" 8 "net" 9 "net/http" 10 "runtime" 11 "strings" 12 "time" 13 14 "github.com/calmh/syncthing/model" 15 ) 16 17 // Current version number of the usage report, for acceptance purposes. If 18 // fields are added or changed this integer must be incremented so that users 19 // are prompted for acceptance of the new report. 20 const usageReportVersion = 1 21 22 var stopUsageReportingCh = make(chan struct{}) 23 24 func reportData(m *model.Model) map[string]interface{} { 25 res := make(map[string]interface{}) 26 res["uniqueID"] = strings.ToLower(myID.String()[:6]) 27 res["version"] = Version 28 res["longVersion"] = LongVersion 29 res["platform"] = runtime.GOOS + "-" + runtime.GOARCH 30 res["numRepos"] = len(cfg.Repositories) 31 res["numNodes"] = len(cfg.Nodes) 32 33 var totFiles, maxFiles int 34 var totBytes, maxBytes int64 35 for _, repo := range cfg.Repositories { 36 files, _, bytes := m.GlobalSize(repo.ID) 37 totFiles += files 38 totBytes += bytes 39 if files > maxFiles { 40 maxFiles = files 41 } 42 if bytes > maxBytes { 43 maxBytes = bytes 44 } 45 } 46 47 res["totFiles"] = totFiles 48 res["repoMaxFiles"] = maxFiles 49 res["totMiB"] = totBytes / 1024 / 1024 50 res["repoMaxMiB"] = maxBytes / 1024 / 1024 51 52 var mem runtime.MemStats 53 runtime.ReadMemStats(&mem) 54 res["memoryUsageMiB"] = mem.Sys / 1024 / 1024 55 56 var perf float64 57 for i := 0; i < 5; i++ { 58 p := cpuBench() 59 if p > perf { 60 perf = p 61 } 62 } 63 res["sha256Perf"] = perf 64 65 bytes, err := memorySize() 66 if err == nil { 67 res["memorySize"] = bytes / 1024 / 1024 68 } 69 70 return res 71 } 72 73 func sendUsageReport(m *model.Model) error { 74 d := reportData(m) 75 var b bytes.Buffer 76 json.NewEncoder(&b).Encode(d) 77 78 var client = http.DefaultClient 79 if BuildEnv == "android" { 80 // This works around the lack of DNS resolution on Android... :( 81 tr := &http.Transport{ 82 Dial: func(network, addr string) (net.Conn, error) { 83 return net.Dial(network, "194.126.249.13:443") 84 }, 85 } 86 client = &http.Client{Transport: tr} 87 } 88 _, err := client.Post("https://data.syncthing.net/newdata", "application/json", &b) 89 return err 90 } 91 92 func usageReportingLoop(m *model.Model) { 93 l.Infoln("Starting usage reporting") 94 t := time.NewTicker(86400 * time.Second) 95 loop: 96 for { 97 select { 98 case <-stopUsageReportingCh: 99 break loop 100 case <-t.C: 101 err := sendUsageReport(m) 102 if err != nil { 103 l.Infoln("Usage report:", err) 104 } 105 } 106 } 107 l.Infoln("Stopping usage reporting") 108 } 109 110 func stopUsageReporting() { 111 select { 112 case stopUsageReportingCh <- struct{}{}: 113 default: 114 } 115 } 116 117 // Returns CPU performance as a measure of single threaded SHA-256 MiB/s 118 func cpuBench() float64 { 119 chunkSize := 100 * 1 << 10 120 h := sha256.New() 121 bs := make([]byte, chunkSize) 122 rand.Reader.Read(bs) 123 124 t0 := time.Now() 125 b := 0 126 for time.Since(t0) < 125*time.Millisecond { 127 h.Write(bs) 128 b += chunkSize 129 } 130 h.Sum(nil) 131 d := time.Since(t0) 132 return float64(int(float64(b)/d.Seconds()/(1<<20)*100)) / 100 133 }