MM-23093 Implement Server Setup telemetry - server configuration (#14374)
* added advanced first day diagnostics reporting * typo * config corrected * defaults * moved from config to system db table * missing file * added error handling * tests * typos Co-authored-by: mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
278c295869
Коммит
7800116429
12
app/app.go
12
app/app.go
@@ -142,6 +142,18 @@ func (a *App) getSystemInstallDate() (int64, *model.AppError) {
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (a *App) getFirstServerRunTimestamp() (int64, *model.AppError) {
|
||||
systemData, appErr := a.Srv().Store.System().GetByName(model.SYSTEM_FIRST_SERVER_RUN_TIMESTAMP_KEY)
|
||||
if appErr != nil {
|
||||
return 0, appErr
|
||||
}
|
||||
value, err := strconv.ParseInt(systemData.Value, 10, 64)
|
||||
if err != nil {
|
||||
return 0, model.NewAppError("getFirstServerRunTimestamp", "app.system_install_date.parse_int.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (a *App) Srv() *Server {
|
||||
return a.srv
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ func TestUnitUpdateConfig(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
mockStore.On("Post").Return(&mockPostStore)
|
||||
mockStore.On("System").Return(&mockSystemStore)
|
||||
|
||||
@@ -265,6 +265,22 @@ func (a *App) ensureInstallationDate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) ensureFirstServerRunTimestamp() error {
|
||||
_, err := a.getFirstServerRunTimestamp()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = a.Srv().Store.System().SaveOrUpdate(&model.System{
|
||||
Name: model.SYSTEM_FIRST_SERVER_RUN_TIMESTAMP_KEY,
|
||||
Value: strconv.FormatInt(utils.MillisFromTime(time.Now()), 10),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AsymmetricSigningKey will return a private key that can be used for asymmetric signing.
|
||||
func (s *Server) AsymmetricSigningKey() *ecdsa.PrivateKey {
|
||||
return s.asymmetricSigningKey
|
||||
|
||||
@@ -105,6 +105,8 @@ func TestSAMLSettings(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := storemocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
mockStore.On("Post").Return(&mockPostStore)
|
||||
mockStore.On("System").Return(&mockSystemStore)
|
||||
|
||||
@@ -555,6 +555,8 @@ func TestGetPushNotificationMessage(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
mockStore.On("Post").Return(&mockPostStore)
|
||||
mockStore.On("System").Return(&mockSystemStore)
|
||||
@@ -1125,6 +1127,8 @@ func TestClearPushNotificationSync(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockSessionStore := mocks.SessionStore{}
|
||||
mockSessionStore.On("GetSessionsWithActiveDeviceIds", mock.AnythingOfType("string")).Return([]*model.Session{sess1, sess2}, nil)
|
||||
mockSessionStore.On("UpdateDeviceId", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("int64")).Return("testdeviceID", nil)
|
||||
@@ -1177,6 +1181,8 @@ func TestUpdateMobileAppBadgeSync(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockSessionStore := mocks.SessionStore{}
|
||||
mockSessionStore.On("GetSessionsWithActiveDeviceIds", mock.AnythingOfType("string")).Return([]*model.Session{sess1, sess2}, nil)
|
||||
mockSessionStore.On("UpdateDeviceId", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("int64")).Return("testdeviceID", nil)
|
||||
@@ -1217,6 +1223,8 @@ func TestSendAckToPushProxy(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
mockStore.On("Post").Return(&mockPostStore)
|
||||
mockStore.On("System").Return(&mockSystemStore)
|
||||
@@ -1371,6 +1379,8 @@ func BenchmarkPushNotificationThroughput(b *testing.B) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockSessionStore := mocks.SessionStore{}
|
||||
mockPreferenceStore := mocks.PreferenceStore{}
|
||||
mockPreferenceStore.On("Get", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(&model.Preference{Value: "test"}, nil)
|
||||
|
||||
@@ -27,6 +27,8 @@ func TestPluginPublicKeys(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
mockStore.On("Post").Return(&mockPostStore)
|
||||
mockStore.On("System").Return(&mockSystemStore)
|
||||
|
||||
@@ -460,6 +460,8 @@ func TestImageProxy(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := storemocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
mockStore.On("Post").Return(&mockPostStore)
|
||||
mockStore.On("System").Return(&mockSystemStore)
|
||||
|
||||
@@ -146,7 +146,8 @@ type Server struct {
|
||||
|
||||
CacheProvider cache.Provider
|
||||
|
||||
tracer *tracing.Tracer
|
||||
tracer *tracing.Tracer
|
||||
timestampLastDiagnosticSent time.Time
|
||||
}
|
||||
|
||||
func NewServer(options ...Option) (*Server, error) {
|
||||
@@ -727,11 +728,32 @@ func runSecurityJob(s *Server) {
|
||||
}, time.Hour*4)
|
||||
}
|
||||
|
||||
func runDiagnosticsJob(s *Server) {
|
||||
doDiagnostics(s)
|
||||
model.CreateRecurringTask("Diagnostics", func() {
|
||||
func doDiagnosticsIfNeeded(s *Server, firstRun time.Time) {
|
||||
hoursSinceFirstServerRun := time.Since(firstRun).Hours()
|
||||
// Send once every 10 minutes for the first hour
|
||||
// Send once every hour thereafter for the first 12 hours
|
||||
// Send at the 24 hour mark and every 24 hours after
|
||||
if hoursSinceFirstServerRun < 1 {
|
||||
doDiagnostics(s)
|
||||
}, time.Hour*24)
|
||||
} else if hoursSinceFirstServerRun <= 12 && time.Since(s.timestampLastDiagnosticSent) >= time.Hour {
|
||||
doDiagnostics(s)
|
||||
} else if hoursSinceFirstServerRun > 12 && time.Since(s.timestampLastDiagnosticSent) >= 24*time.Hour {
|
||||
doDiagnostics(s)
|
||||
}
|
||||
}
|
||||
|
||||
func runDiagnosticsJob(s *Server) {
|
||||
// Send on boot
|
||||
doDiagnostics(s)
|
||||
firstRun, err := s.FakeApp().getFirstServerRunTimestamp()
|
||||
if err != nil {
|
||||
mlog.Warn("Fetching time of first server run failed. Setting to 'now'.")
|
||||
s.FakeApp().ensureFirstServerRunTimestamp()
|
||||
firstRun = utils.MillisFromTime(time.Now())
|
||||
}
|
||||
model.CreateRecurringTask("Diagnostics", func() {
|
||||
doDiagnosticsIfNeeded(s, utils.TimeFromMillis(firstRun))
|
||||
}, time.Minute*10)
|
||||
}
|
||||
|
||||
func runTokenCleanupJob(s *Server) {
|
||||
@@ -761,6 +783,7 @@ func doSecurity(s *Server) {
|
||||
|
||||
func doDiagnostics(s *Server) {
|
||||
if *s.Config().LogSettings.EnableDiagnostics {
|
||||
s.timestampLastDiagnosticSent = time.Now()
|
||||
s.FakeApp().SendDailyDiagnostics()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,10 @@ func (s *Server) RunOldAppInitialization() error {
|
||||
return errors.Wrapf(err, "unable to ensure installation date")
|
||||
}
|
||||
|
||||
if err := s.FakeApp().ensureFirstServerRunTimestamp(); err != nil {
|
||||
return errors.Wrapf(err, "unable to ensure first run timestamp")
|
||||
}
|
||||
|
||||
s.ensureDiagnosticId()
|
||||
s.FakeApp().regenerateClientConfig()
|
||||
|
||||
|
||||
@@ -10,14 +10,15 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
SYSTEM_DIAGNOSTIC_ID = "DiagnosticId"
|
||||
SYSTEM_RAN_UNIT_TESTS = "RanUnitTests"
|
||||
SYSTEM_LAST_SECURITY_TIME = "LastSecurityTime"
|
||||
SYSTEM_ACTIVE_LICENSE_ID = "ActiveLicenseId"
|
||||
SYSTEM_LAST_COMPLIANCE_TIME = "LastComplianceTime"
|
||||
SYSTEM_ASYMMETRIC_SIGNING_KEY = "AsymmetricSigningKey"
|
||||
SYSTEM_POST_ACTION_COOKIE_SECRET = "PostActionCookieSecret"
|
||||
SYSTEM_INSTALLATION_DATE_KEY = "InstallationDate"
|
||||
SYSTEM_DIAGNOSTIC_ID = "DiagnosticId"
|
||||
SYSTEM_RAN_UNIT_TESTS = "RanUnitTests"
|
||||
SYSTEM_LAST_SECURITY_TIME = "LastSecurityTime"
|
||||
SYSTEM_ACTIVE_LICENSE_ID = "ActiveLicenseId"
|
||||
SYSTEM_LAST_COMPLIANCE_TIME = "LastComplianceTime"
|
||||
SYSTEM_ASYMMETRIC_SIGNING_KEY = "AsymmetricSigningKey"
|
||||
SYSTEM_POST_ACTION_COOKIE_SECRET = "PostActionCookieSecret"
|
||||
SYSTEM_INSTALLATION_DATE_KEY = "InstallationDate"
|
||||
SYSTEM_FIRST_SERVER_RUN_TIMESTAMP_KEY = "FirstServerRunTimestamp"
|
||||
)
|
||||
|
||||
type System struct {
|
||||
|
||||
@@ -27,6 +27,7 @@ func GetMockStoreForSetupFunctions() *mocks.Store {
|
||||
systemStore.On("GetByName", "AsymmetricSigningKey").Return(nil, model.NewAppError("FakeError", "store.sql_system.get_by_name.app_error", nil, "", http.StatusInternalServerError))
|
||||
systemStore.On("GetByName", "PostActionCookieSecret").Return(nil, model.NewAppError("FakeError", "store.sql_system.get_by_name.app_error", nil, "", http.StatusInternalServerError))
|
||||
systemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: strconv.FormatInt(model.GetMillis(), 10)}, nil)
|
||||
systemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
systemStore.On("GetByName", "AdvancedPermissionsMigrationComplete").Return(&model.System{Name: "AdvancedPermissionsMigrationComplete", Value: "true"}, nil)
|
||||
systemStore.On("GetByName", "EmojisPermissionsMigrationComplete").Return(&model.System{Name: "EmojisPermissionsMigrationComplete", Value: "true"}, nil)
|
||||
systemStore.On("GetByName", "GuestRolesCreationMigrationComplete").Return(&model.System{Name: "GuestRolesCreationMigrationComplete", Value: "true"}, nil)
|
||||
|
||||
@@ -71,6 +71,8 @@ func TestHandlerServeHTTPSecureTransport(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
mockStore.On("Post").Return(&mockPostStore)
|
||||
mockStore.On("System").Return(&mockSystemStore)
|
||||
@@ -310,6 +312,8 @@ func TestHandlerServeCSPHeader(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
mockStore.On("Post").Return(&mockPostStore)
|
||||
mockStore.On("System").Return(&mockSystemStore)
|
||||
@@ -474,6 +478,8 @@ func TestCheckCSRFToken(t *testing.T) {
|
||||
mockPostStore.On("GetMaxPostSize").Return(65535, nil)
|
||||
mockSystemStore := mocks.SystemStore{}
|
||||
mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
|
||||
mockSystemStore.On("GetByName", "FirstServerRunTimestamp").Return(&model.System{Name: "FirstServerRunTimestamp", Value: "10"}, nil)
|
||||
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
mockStore.On("Post").Return(&mockPostStore)
|
||||
mockStore.On("System").Return(&mockSystemStore)
|
||||
|
||||
Ссылка в новой задаче
Block a user