[MM-57189] Ignore MaxUsersForStatistics when generating Support Packet (#26514)

This commit is contained in:
Ben Schumacher 2024-04-08 11:09:00 +02:00 committed by GitHub
parent 765593e89a
commit 5dbf874d1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 122 additions and 22 deletions

View File

@ -19,17 +19,27 @@ const (
) )
func (a *App) GetAnalytics(rctx request.CTX, name string, teamID string) (model.AnalyticsRows, *model.AppError) { func (a *App) GetAnalytics(rctx request.CTX, name string, teamID string) (model.AnalyticsRows, *model.AppError) {
skipIntensiveQueries := false return a.getAnalytics(rctx, name, teamID, false)
var systemUserCount int64 }
func (a *App) GetAnalyticsForSupportPacket(rctx request.CTX) (model.AnalyticsRows, *model.AppError) {
return a.getAnalytics(rctx, "standard", "", true)
}
func (a *App) getAnalytics(rctx request.CTX, name string, teamID string, forSupportPacket bool) (model.AnalyticsRows, *model.AppError) {
systemUserCount, err := a.Srv().Store().User().Count(model.UserCountOptions{}) systemUserCount, err := a.Srv().Store().User().Count(model.UserCountOptions{})
if err != nil { if err != nil {
return nil, model.NewAppError("GetAnalytics", "app.user.get_total_users_count.app_error", nil, "", http.StatusInternalServerError).Wrap(err) return nil, model.NewAppError("GetAnalytics", "app.user.get_total_users_count.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
} }
skipIntensiveQueries := false
// When generating a Support packet, always run intensive queries.
if !forSupportPacket {
if systemUserCount > int64(*a.Config().AnalyticsSettings.MaxUsersForStatistics) { if systemUserCount > int64(*a.Config().AnalyticsSettings.MaxUsersForStatistics) {
rctx.Logger().Debug("More than limit users are on the system, intensive queries skipped", mlog.Int("limit", *a.Config().AnalyticsSettings.MaxUsersForStatistics)) rctx.Logger().Debug("More than limit users are on the system, intensive queries skipped", mlog.Int("limit", *a.Config().AnalyticsSettings.MaxUsersForStatistics))
skipIntensiveQueries = true skipIntensiveQueries = true
} }
}
if name == "standard" { if name == "standard" {
var rows model.AnalyticsRows = make([]*model.AnalyticsRow, 11) var rows model.AnalyticsRows = make([]*model.AnalyticsRow, 11)

View File

@ -628,6 +628,7 @@ type AppIface interface {
GetAllTeamsPage(offset int, limit int, opts *model.TeamSearch) ([]*model.Team, *model.AppError) GetAllTeamsPage(offset int, limit int, opts *model.TeamSearch) ([]*model.Team, *model.AppError)
GetAllTeamsPageWithCount(offset int, limit int, opts *model.TeamSearch) (*model.TeamsWithCount, *model.AppError) GetAllTeamsPageWithCount(offset int, limit int, opts *model.TeamSearch) (*model.TeamsWithCount, *model.AppError)
GetAnalytics(rctx request.CTX, name string, teamID string) (model.AnalyticsRows, *model.AppError) GetAnalytics(rctx request.CTX, name string, teamID string) (model.AnalyticsRows, *model.AppError)
GetAnalyticsForSupportPacket(rctx request.CTX) (model.AnalyticsRows, *model.AppError)
GetAppliedSchemaMigrations() ([]model.AppliedMigration, *model.AppError) GetAppliedSchemaMigrations() ([]model.AppliedMigration, *model.AppError)
GetAudits(rctx request.CTX, userID string, limit int) (model.Audits, *model.AppError) GetAudits(rctx request.CTX, userID string, limit int) (model.Audits, *model.AppError)
GetAuditsPage(rctx request.CTX, userID string, page int, perPage int) (model.Audits, *model.AppError) GetAuditsPage(rctx request.CTX, userID string, page int, perPage int) (model.Audits, *model.AppError)

View File

@ -5089,6 +5089,28 @@ func (a *OpenTracingAppLayer) GetAnalytics(rctx request.CTX, name string, teamID
return resultVar0, resultVar1 return resultVar0, resultVar1
} }
func (a *OpenTracingAppLayer) GetAnalyticsForSupportPacket(rctx request.CTX) (model.AnalyticsRows, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetAnalyticsForSupportPacket")
a.ctx = newCtx
a.app.Srv().Store().SetContext(newCtx)
defer func() {
a.app.Srv().Store().SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.GetAnalyticsForSupportPacket(rctx)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetAppliedSchemaMigrations() ([]model.AppliedMigration, *model.AppError) { func (a *OpenTracingAppLayer) GetAppliedSchemaMigrations() ([]model.AppliedMigration, *model.AppError) {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetAppliedSchemaMigrations") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetAppliedSchemaMigrations")

View File

@ -70,7 +70,7 @@ func (a *App) GenerateSupportPacket(c request.CTX) []model.FileData {
} }
func (a *App) generateSupportPacketYaml(c request.CTX) (*model.FileData, error) { func (a *App) generateSupportPacketYaml(c request.CTX) (*model.FileData, error) {
var rErr error var rErr *multierror.Error
/* DB */ /* DB */
@ -143,7 +143,7 @@ func (a *App) generateSupportPacketYaml(c request.CTX) (*model.FileData, error)
monthlyActiveUsers int monthlyActiveUsers int
inactiveUserCount int inactiveUserCount int
) )
analytics, appErr := a.GetAnalytics(c, "standard", "") analytics, appErr := a.GetAnalyticsForSupportPacket(c)
if appErr != nil { if appErr != nil {
rErr = multierror.Append(errors.Wrap(appErr, "error while getting analytics")) rErr = multierror.Append(errors.Wrap(appErr, "error while getting analytics"))
} }
@ -257,7 +257,7 @@ func (a *App) generateSupportPacketYaml(c request.CTX) (*model.FileData, error)
Filename: "support_packet.yaml", Filename: "support_packet.yaml",
Body: supportPacketYaml, Body: supportPacketYaml,
} }
return fileData, rErr return fileData, rErr.ErrorOrNil()
} }
func (a *App) createPluginsFile(_ request.CTX) (*model.FileData, error) { func (a *App) createPluginsFile(_ request.CTX) (*model.FileData, error) {

View File

@ -50,23 +50,91 @@ func TestGenerateSupportPacketYaml(t *testing.T) {
license.Features.Users = model.NewInt(licenseUsers) license.Features.Users = model.NewInt(licenseUsers)
th.App.Srv().SetLicense(license) th.App.Srv().SetLicense(license)
t.Run("Happy path", func(t *testing.T) { generateSupportPacket := func(t *testing.T) *model.SupportPacket {
// Happy path where we have a support packet yaml file without any warnings t.Helper()
fileData, err := th.App.generateSupportPacketYaml(th.Context) fileData, err := th.App.generateSupportPacketYaml(th.Context)
require.NotNil(t, fileData) require.NotNil(t, fileData)
assert.Equal(t, "support_packet.yaml", fileData.Filename) assert.Equal(t, "support_packet.yaml", fileData.Filename)
assert.Positive(t, len(fileData.Body)) assert.Positive(t, len(fileData.Body))
assert.NoError(t, err) assert.NoError(t, err)
var packet model.SupportPacket var packet model.SupportPacket
require.NoError(t, yaml.Unmarshal(fileData.Body, &packet)) require.NoError(t, yaml.Unmarshal(fileData.Body, &packet))
require.NotNil(t, packet)
return &packet
}
assert.Equal(t, 3, packet.ActiveUsers) // from InitBasic. t.Run("Happy path", func(t *testing.T) {
assert.Equal(t, licenseUsers, packet.LicenseSupportedUsers) // Happy path where we have a support packet yaml file without any warnings
assert.Equal(t, false, packet.LicenseIsTrial) packet := generateSupportPacket(t)
/* Build information */
assert.NotEmpty(t, packet.ServerOS)
assert.NotEmpty(t, packet.ServerArchitecture)
assert.Equal(t, model.CurrentVersion, packet.ServerVersion)
// BuildHash is not present in tests
/* DB */
assert.NotEmpty(t, packet.DatabaseType)
assert.NotEmpty(t, packet.DatabaseVersion)
assert.NotEmpty(t, packet.DatabaseSchemaVersion)
assert.Zero(t, packet.WebsocketConnections)
assert.NotZero(t, packet.MasterDbConnections)
assert.Zero(t, packet.ReplicaDbConnections)
/* Cluster */
assert.Empty(t, packet.ClusterID) assert.Empty(t, packet.ClusterID)
/* File store */
assert.Equal(t, "local", packet.FileDriver) assert.Equal(t, "local", packet.FileDriver)
assert.Equal(t, "OK", packet.FileStatus) assert.Equal(t, "OK", packet.FileStatus)
/* LDAP */
assert.Empty(t, packet.LdapVendorName)
assert.Empty(t, packet.LdapVendorVersion)
/* Elastic Search */
assert.Empty(t, packet.ElasticServerVersion)
assert.Empty(t, packet.ElasticServerPlugins)
/* License */
assert.Equal(t, "My awesome Company", packet.LicenseTo)
assert.Equal(t, licenseUsers, packet.LicenseSupportedUsers)
assert.Equal(t, false, packet.LicenseIsTrial)
/* Server stats */
assert.Equal(t, 3, packet.ActiveUsers) // from InitBasic()
assert.Equal(t, 0, packet.DailyActiveUsers)
assert.Equal(t, 0, packet.MonthlyActiveUsers)
assert.Equal(t, 0, packet.InactiveUserCount)
assert.Equal(t, 5, packet.TotalPosts) // from InitBasic()
assert.Equal(t, 3, packet.TotalChannels) // from InitBasic()
assert.Equal(t, 1, packet.TotalTeams) // from InitBasic()
/* Jobs */
assert.Empty(t, packet.DataRetentionJobs)
assert.Empty(t, packet.MessageExportJobs)
assert.Empty(t, packet.ElasticPostIndexingJobs)
assert.Empty(t, packet.ElasticPostAggregationJobs)
assert.Empty(t, packet.BlevePostIndexingJobs)
assert.Empty(t, packet.LdapSyncJobs)
assert.Empty(t, packet.MigrationJobs)
})
t.Run("post count should be present if number of users extends AnalyticsSettings.MaxUsersForStatistics", func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.AnalyticsSettings.MaxUsersForStatistics = model.NewInt(1)
})
for i := 0; i < 5; i++ {
p := th.CreatePost(th.BasicChannel)
require.NotNil(t, p)
}
// InitBasic() already creats 5 posts
packet := generateSupportPacket(t)
assert.Equal(t, 10, packet.TotalPosts)
}) })
t.Run("filestore fails", func(t *testing.T) { t.Run("filestore fails", func(t *testing.T) {
@ -75,13 +143,7 @@ func TestGenerateSupportPacketYaml(t *testing.T) {
fb.On("DriverName").Return("mock") fb.On("DriverName").Return("mock")
fb.On("TestConnection").Return(errors.New("all broken")) fb.On("TestConnection").Return(errors.New("all broken"))
fileData, err := th.App.generateSupportPacketYaml(th.Context) packet := generateSupportPacket(t)
require.NotNil(t, fileData)
assert.Equal(t, "support_packet.yaml", fileData.Filename)
assert.Positive(t, len(fileData.Body))
assert.NoError(t, err)
var packet model.SupportPacket
require.NoError(t, yaml.Unmarshal(fileData.Body, &packet))
assert.Equal(t, "mock", packet.FileDriver) assert.Equal(t, "mock", packet.FileDriver)
assert.Equal(t, "FAIL: all broken", packet.FileStatus) assert.Equal(t, "FAIL: all broken", packet.FileStatus)

View File

@ -398,7 +398,12 @@ func (l *License) HasSharedChannels() bool {
func NewTestLicense(features ...string) *License { func NewTestLicense(features ...string) *License {
ret := &License{ ret := &License{
ExpiresAt: GetMillis() + 90*DayInMilliseconds, ExpiresAt: GetMillis() + 90*DayInMilliseconds,
Customer: &Customer{}, Customer: &Customer{
Id: "some ID",
Email: "admin@example.com",
Name: "Main Contact Person",
Company: "My awesome Company",
},
Features: &Features{}, Features: &Features{},
} }
ret.Features.SetDefaults() ret.Features.SetDefaults()