diff --git a/cmd/syncthing/usage_report.go b/cmd/syncthing/usage_report.go index 3b6219a8e..13e6f992b 100644 --- a/cmd/syncthing/usage_report.go +++ b/cmd/syncthing/usage_report.go @@ -12,6 +12,7 @@ import ( "crypto/rand" "crypto/tls" "encoding/json" + "net" "net/http" "runtime" "sort" @@ -183,6 +184,124 @@ func reportData(cfg configIntf, m modelIntf, connectionsService connectionsIntf, if version >= 3 { res["uptime"] = int(time.Now().Sub(startTime).Seconds()) res["natType"] = connectionsService.NATType() + res["alwaysLocalNets"] = len(opts.AlwaysLocalNets) > 0 + res["cacheIgnoredFiles"] = opts.CacheIgnoredFiles + res["overwriteRemoteDeviceNames"] = opts.OverwriteRemoteDevNames + res["progressEmitterEnabled"] = opts.ProgressUpdateIntervalS > -1 + res["customDefaultFolderPath"] = opts.DefaultFolderPath != "~" + res["weakHashSelection"] = opts.WeakHashSelectionMethod.String() + res["customTrafficClass"] = opts.TrafficClass != 0 + res["customTempIndexMinBlocks"] = opts.TempIndexMinBlocks != 10 + res["temporariesDisabled"] = opts.KeepTemporariesH == 0 + res["temporariesCustom"] = opts.KeepTemporariesH != 24 + res["limitBandwidthInLan"] = opts.LimitBandwidthInLan + res["customReleaseURL"] = opts.ReleasesURL != "https://upgrades.syncthing.net/meta.json" + res["restartOnWakeup"] = opts.RestartOnWakeup + res["customStunServers"] = len(opts.StunServers) == 0 || opts.StunServers[0] != "default" || len(opts.StunServers) > 1 + + folderUsesV3 := map[string]int{ + "scanProgressDisabled": 0, + "conflictsDisabled": 0, + "conflictsUnlimited": 0, + "conflictsOther": 0, + "disableSparseFiles": 0, + "disableTempIndexes": 0, + "alwaysWeakHash": 0, + "customWeakHashThreshold": 0, + } + pullOrder := make(map[string]int) + filesystemType := make(map[string]int) + for _, cfg := range cfg.Folders() { + if cfg.ScanProgressIntervalS < 0 { + folderUsesV3["scanProgressDisabled"]++ + } + if cfg.MaxConflicts == 0 { + folderUsesV3["conflictsDisabled"]++ + } else if cfg.MaxConflicts < 0 { + folderUsesV3["conflictsUnlimited"]++ + } else { + folderUsesV3["conflictsOther"]++ + } + if cfg.DisableSparseFiles { + folderUsesV3["disableSparseFiles"]++ + } + if cfg.DisableTempIndexes { + folderUsesV3["disableTempIndexes"]++ + } + if cfg.WeakHashThresholdPct < 0 { + folderUsesV3["alwaysWeakHash"]++ + } else if cfg.WeakHashThresholdPct != 25 { + folderUsesV3["customWeakHashThreshold"]++ + } + pullOrder[cfg.Order.String()]++ + filesystemType[cfg.FilesystemType.String()]++ + } + folderUsesV3Interface := map[string]interface{}{ + "pullOrder": pullOrder, + "filesystemType": filesystemType, + } + for key, value := range folderUsesV3 { + folderUsesV3Interface[key] = value + } + res["folderUsesV3"] = folderUsesV3Interface + + guiCfg := cfg.GUI() + // Anticipate multiple GUI configs in the future, hence store counts. + guiStats := map[string]int{ + "enabled": 0, + "useTLS": 0, + "useAuth": 0, + "useAPIKey": 0, + "insecureAdminAccess": 0, + "debugging": 0, + "insecureSkipHostCheck": 0, + "insecureAllowFrameLoading": 0, + "listenLocal": 0, + "listenUnspecified": 0, + } + theme := make(map[string]int) + if guiCfg.Enabled { + guiStats["enabled"]++ + if guiCfg.UseTLS() { + guiStats["useTLS"]++ + } + if len(guiCfg.User) > 0 && len(guiCfg.Password) > 0 { + guiStats["useAuth"]++ + } + if len(guiCfg.APIKey) > 0 { + guiStats["useAPIKey"]++ + } + if guiCfg.InsecureAdminAccess { + guiStats["insecureAdminAccess"]++ + } + if guiCfg.Debugging { + guiStats["debugging"]++ + } + if guiCfg.InsecureSkipHostCheck { + guiStats["insecureSkipHostCheck"]++ + } + if guiCfg.InsecureAllowFrameLoading { + guiStats["insecureAllowFrameLoading"]++ + } + + addr, err := net.ResolveTCPAddr("tcp", guiCfg.Address()) + if err == nil { + if addr.IP.IsLoopback() { + guiStats["listenLocal"]++ + } else if addr.IP.IsUnspecified() { + guiStats["listenUnspecified"]++ + } + } + + theme[guiCfg.Theme]++ + } + guiStatsInterface := map[string]interface{}{ + "theme": theme, + } + for key, value := range guiStats { + guiStatsInterface[key] = value + } + res["guiStats"] = guiStatsInterface } for key, value := range m.UsageReportingStats(version) { diff --git a/gui/default/syncthing/core/syncthingController.js b/gui/default/syncthing/core/syncthingController.js index 710131ef8..c833415cd 100755 --- a/gui/default/syncthing/core/syncthingController.js +++ b/gui/default/syncthing/core/syncthingController.js @@ -2,7 +2,7 @@ angular.module('syncthing.core') .config(function($locationProvider) { $locationProvider.html5Mode({enabled: true, requireBase: false}).hashPrefix('!'); }) - .controller('SyncthingController', function ($scope, $http, $location, LocaleService, Events, $filter) { + .controller('SyncthingController', function ($scope, $http, $location, LocaleService, Events, $filter, $q) { 'use strict'; // private/helper definitions @@ -33,8 +33,9 @@ angular.module('syncthing.core') $scope.folderRejections = {}; $scope.protocolChanged = false; $scope.reportData = {}; - $scope.reportDataPreview = {}; + $scope.reportDataPreview = ''; $scope.reportDataPreviewVersion = ''; + $scope.reportDataPreviewDiff = false; $scope.reportPreview = false; $scope.folders = {}; $scope.seenError = ''; @@ -135,7 +136,7 @@ angular.module('syncthing.core') }).error($scope.emitHTTPError); $http.get(urlbase + '/svc/report').success(function (data) { - $scope.reportDataPreview = $scope.reportData = data; + $scope.reportData = data; if ($scope.system && $scope.config.options.urSeen < $scope.system.urVersionMax) { // Usage reporting format has changed, prompt the user to re-accept. $('#ur').modal(); @@ -1769,9 +1770,27 @@ angular.module('syncthing.core') $scope.refreshReportDataPreview = function () { $scope.reportDataPreview = ''; - $http.get(urlbase + '/svc/report?version=' + $scope.reportDataPreviewVersion).success(function (data) { - $scope.reportDataPreview = data; - }).error($scope.emitHTTPError); + if (!$scope.reportDataPreviewVersion) { + return; + } + var version = parseInt($scope.reportDataPreviewVersion); + if ($scope.reportDataPreviewDiff && version > 2) { + $q.all([ + $http.get(urlbase + '/svc/report?version=' + version), + $http.get(urlbase + '/svc/report?version=' + (version-1)), + ]).then(function (responses) { + var newReport = responses[0].data; + var oldReport = responses[1].data; + angular.forEach(oldReport, function(_, key) { + delete newReport[key]; + }); + $scope.reportDataPreview = newReport; + }); + } else { + $http.get(urlbase + '/svc/report?version=' + version).success(function (data) { + $scope.reportDataPreview = data; + }).error($scope.emitHTTPError); + } }; $scope.rescanAllFolders = function () { diff --git a/gui/default/syncthing/usagereport/usageReportPreviewModalView.html b/gui/default/syncthing/usagereport/usageReportPreviewModalView.html index 5a2217cc5..95f4036cb 100644 --- a/gui/default/syncthing/usagereport/usageReportPreviewModalView.html +++ b/gui/default/syncthing/usagereport/usageReportPreviewModalView.html @@ -7,8 +7,15 @@

https://data.syncthing.net/

+
+ +