From 9d688821aa8bb8d766793aeaec6920f9985a30a3 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Thu, 1 Oct 2015 13:02:04 -0700 Subject: [PATCH 1/3] PLT-462 Adding diagnostic info --- config/config.json | 3 +- docker/dev/config_docker.json | 3 +- docker/local/config_docker.json | 3 +- mattermost.go | 51 +++++++++++++++++++ model/config.go | 1 + utils/diagnostic.go | 45 ++++++++++++++++ .../admin_console/privacy_settings.jsx | 34 +++++++++++++ 7 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 utils/diagnostic.go diff --git a/config/config.json b/config/config.json index 38acee85a7..48514e1a46 100644 --- a/config/config.json +++ b/config/config.json @@ -75,7 +75,8 @@ }, "PrivacySettings": { "ShowEmailAddress": true, - "ShowFullName": true + "ShowFullName": true, + "EnableDiagnostic": false }, "GitLabSettings": { "Enable": false, diff --git a/docker/dev/config_docker.json b/docker/dev/config_docker.json index 733267f748..2611a63ce5 100644 --- a/docker/dev/config_docker.json +++ b/docker/dev/config_docker.json @@ -75,7 +75,8 @@ }, "PrivacySettings": { "ShowEmailAddress": true, - "ShowFullName": true + "ShowFullName": true, + "EnableDiagnostic": false }, "GitLabSettings": { "Enable": false, diff --git a/docker/local/config_docker.json b/docker/local/config_docker.json index 733267f748..2611a63ce5 100644 --- a/docker/local/config_docker.json +++ b/docker/local/config_docker.json @@ -75,7 +75,8 @@ }, "PrivacySettings": { "ShowEmailAddress": true, - "ShowFullName": true + "ShowFullName": true, + "EnableDiagnostic": false }, "GitLabSettings": { "Enable": false, diff --git a/mattermost.go b/mattermost.go index ff7b0f3f3a..3e8b73e948 100644 --- a/mattermost.go +++ b/mattermost.go @@ -8,6 +8,8 @@ import ( "fmt" "os" "os/signal" + "runtime" + "strconv" "strings" "syscall" "time" @@ -61,6 +63,8 @@ func main() { manualtesting.InitManualTesting() } + diagnosticsJob() + // wait for kill signal before attempting to gracefully shutdown // the running service c := make(chan os.Signal) @@ -71,6 +75,53 @@ func main() { } } +func diagnosticsJob() { + go func() { + for { + if utils.Cfg.PrivacySettings.EnableDiagnostic && model.BuildNumber != "_BUILD_NUMBER_" { + if result := <-api.Srv.Store.System().Get(); result.Err == nil { + props := result.Data.(model.StringMap) + lastTime, _ := strconv.ParseInt(props["LastDiagnosticTime"], 10, 0) + currentTime := model.GetMillis() + + if (currentTime - lastTime) > 1000*60*60*24*7 { + l4g.Info("Sending error and diagnostic information to mattermost") + + id := props["DiagnosticId"] + if len(id) == 0 { + id = model.NewId() + systemId := &model.System{Name: "DiagnosticId", Value: id} + <-api.Srv.Store.System().Save(systemId) + } + + systemLastTime := &model.System{Name: "LastDiagnosticTime", Value: strconv.FormatInt(currentTime, 10)} + if lastTime == 0 { + <-api.Srv.Store.System().Save(systemLastTime) + } else { + <-api.Srv.Store.System().Update(systemLastTime) + } + + m := make(map[string]string) + m[utils.PROP_DIAGNOSTIC_ID] = id + m[utils.PROP_DIAGNOSTIC_BUILD] = model.CurrentVersion + "." + model.BuildNumber + m[utils.PROP_DIAGNOSTIC_DATABASE] = utils.Cfg.SqlSettings.DriverName + m[utils.PROP_DIAGNOSTIC_OS] = runtime.GOOS + m[utils.PROP_DIAGNOSTIC_CATEGORY] = utils.VAL_DIAGNOSTIC_CATEGORY_DEFALUT + + if ucr := <-api.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil { + m[utils.PROP_DIAGNOSTIC_USER_COUNT] = strconv.FormatInt(ucr.Data.(int64), 10) + } + + utils.SendDiagnostic(m) + } + } + } + + time.Sleep(time.Hour * 24) + } + }() +} + func parseCmds() { flag.Usage = func() { fmt.Fprintln(os.Stderr, usage) diff --git a/model/config.go b/model/config.go index 5d822e2631..35ceb7f4ab 100644 --- a/model/config.go +++ b/model/config.go @@ -110,6 +110,7 @@ type RateLimitSettings struct { type PrivacySettings struct { ShowEmailAddress bool ShowFullName bool + EnableDiagnostic bool } type TeamSettings struct { diff --git a/utils/diagnostic.go b/utils/diagnostic.go new file mode 100644 index 0000000000..2f3893cecf --- /dev/null +++ b/utils/diagnostic.go @@ -0,0 +1,45 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +package utils + +import ( + "net/http" + + l4g "code.google.com/p/log4go" + + "github.com/mattermost/platform/model" +) + +const ( + PROP_DIAGNOSTIC_ID = "id" + PROP_DIAGNOSTIC_CATEGORY = "c" + VAL_DIAGNOSTIC_CATEGORY_DEFALUT = "d" + PROP_DIAGNOSTIC_BUILD = "b" + PROP_DIAGNOSTIC_DATABASE = "db" + PROP_DIAGNOSTIC_OS = "os" + PROP_DIAGNOSTIC_USER_COUNT = "uc" +) + +func SendDiagnostic(data model.StringMap) *model.AppError { + if Cfg.PrivacySettings.EnableDiagnostic && model.BuildNumber != "_BUILD_NUMBER_" { + + query := "?" + for name, value := range data { + if len(query) > 1 { + query += "&" + } + + query += name + "=" + UrlEncode(value) + } + + res, err := http.Get("http://d7zmvsa9e04kk.cloudfront.net/i" + query) + if err != nil { + l4g.Error("Failed to send diagnostics %v", err.Error()) + } + + res.Body.Close() + } + + return nil +} diff --git a/web/react/components/admin_console/privacy_settings.jsx b/web/react/components/admin_console/privacy_settings.jsx index affd8ae116..c74d321e64 100644 --- a/web/react/components/admin_console/privacy_settings.jsx +++ b/web/react/components/admin_console/privacy_settings.jsx @@ -30,6 +30,7 @@ export default class PrivacySettings extends React.Component { var config = this.props.config; config.PrivacySettings.ShowEmailAddress = React.findDOMNode(this.refs.ShowEmailAddress).checked; config.PrivacySettings.ShowFullName = React.findDOMNode(this.refs.ShowFullName).checked; + config.PrivacySettings.EnableDiagnostic = React.findDOMNode(this.refs.EnableDiagnostic).checked; Client.saveConfig( config, @@ -136,6 +137,39 @@ export default class PrivacySettings extends React.Component { +
+ +
+ + +

{'When true, The server will periodically send error and diagnostic information to Mattermost.'}

+
+
+
{serverError} From 3863c3c15e72a278ed439c02b189eba6cccd94ac Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Fri, 2 Oct 2015 09:01:50 -0700 Subject: [PATCH 2/3] Adding offical build function --- mattermost.go | 2 +- model/version.go | 4 ++++ utils/diagnostic.go | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mattermost.go b/mattermost.go index de4c4b8831..e78e8d04a2 100644 --- a/mattermost.go +++ b/mattermost.go @@ -78,7 +78,7 @@ func main() { func diagnosticsJob() { go func() { for { - if utils.Cfg.PrivacySettings.EnableDiagnostic && model.BuildNumber != "_BUILD_NUMBER_" { + if utils.Cfg.PrivacySettings.EnableDiagnostic && !model.IsOfficalBuild() { if result := <-api.Srv.Store.System().Get(); result.Err == nil { props := result.Data.(model.StringMap) lastTime, _ := strconv.ParseInt(props["LastDiagnosticTime"], 10, 0) diff --git a/model/version.go b/model/version.go index 233fc37476..f4cd4387f2 100644 --- a/model/version.go +++ b/model/version.go @@ -67,6 +67,10 @@ func GetPreviousVersion(currentVersion string) (int64, int64) { return 0, 0 } +func IsOfficalBuild() bool { + return model.BuildNumber != "_BUILD_NUMBER_" +} + func IsCurrentVersion(versionToCheck string) bool { currentMajor, currentMinor, _ := SplitVersion(CurrentVersion) toCheckMajor, toCheckMinor, _ := SplitVersion(versionToCheck) diff --git a/utils/diagnostic.go b/utils/diagnostic.go index 2f3893cecf..9a61ae9340 100644 --- a/utils/diagnostic.go +++ b/utils/diagnostic.go @@ -22,7 +22,7 @@ const ( ) func SendDiagnostic(data model.StringMap) *model.AppError { - if Cfg.PrivacySettings.EnableDiagnostic && model.BuildNumber != "_BUILD_NUMBER_" { + if Cfg.PrivacySettings.EnableDiagnostic && !model.IsOfficalBuild() { query := "?" for name, value := range data { From e0743a6a2bee391efafa2b5c5c0fa3e8a3d2ee27 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Fri, 2 Oct 2015 09:16:03 -0700 Subject: [PATCH 3/3] Fixing break --- model/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/version.go b/model/version.go index f4cd4387f2..efa1697db6 100644 --- a/model/version.go +++ b/model/version.go @@ -68,7 +68,7 @@ func GetPreviousVersion(currentVersion string) (int64, int64) { } func IsOfficalBuild() bool { - return model.BuildNumber != "_BUILD_NUMBER_" + return BuildNumber != "_BUILD_NUMBER_" } func IsCurrentVersion(versionToCheck string) bool {