Add single-channel guest count to support packet stats (#35846)

Single-channel guests are excluded from billable seat counts for
licensing. Include this metric in the support packet so support
engineers can understand seat calculation discrepancies.

Made-with: Cursor

Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
Maria A Nunez 2026-03-30 11:13:09 -04:00 committed by GitHub
parent 0278ad4d1a
commit ece6b956fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 33 additions and 13 deletions

View file

@ -173,6 +173,11 @@ func (a *App) getSupportPacketStats(rctx request.CTX) (*model.FileData, error) {
rErr = multierror.Append(errors.Wrap(err, "failed to get guest count"))
}
stats.SingleChannelGuests, err = a.Srv().Store().User().AnalyticsGetSingleChannelGuestCount()
if err != nil {
rErr = multierror.Append(errors.Wrap(err, "failed to get single channel guest count"))
}
stats.BotAccounts, err = a.Srv().Store().User().Count(model.UserCountOptions{IncludeBotAccounts: true, ExcludeRegularUsers: true})
if err != nil {
rErr = multierror.Append(errors.Wrap(err, "failed to get bot acount count"))

View file

@ -368,6 +368,7 @@ func TestGetSupportPacketStats(t *testing.T) {
assert.Equal(t, int64(0), sp.MonthlyActiveUsers)
assert.Equal(t, int64(0), sp.DeactivatedUsers)
assert.Equal(t, int64(0), sp.Guests)
assert.Equal(t, int64(0), sp.SingleChannelGuests)
assert.Equal(t, int64(0), sp.BotAccounts)
assert.Equal(t, int64(0), sp.Posts)
assert.Equal(t, int64(0), sp.Channels)
@ -437,6 +438,7 @@ func TestGetSupportPacketStats(t *testing.T) {
assert.Equal(t, int64(0), sp.MonthlyActiveUsers)
assert.Equal(t, int64(3), sp.DeactivatedUsers)
assert.Equal(t, int64(2), sp.Guests)
assert.Equal(t, int64(0), sp.SingleChannelGuests)
assert.Equal(t, int64(1), sp.BotAccounts)
assert.Equal(t, int64(4), sp.Posts) // 1 from the bot creation and 3 created directly
assert.Equal(t, int64(3), sp.Channels) // 2 from the team creation and 1 created directly
@ -446,6 +448,18 @@ func TestGetSupportPacketStats(t *testing.T) {
assert.Equal(t, int64(1), sp.OutgoingWebhooks)
})
t.Run("single channel guests are counted when a guest is in exactly one channel", func(t *testing.T) {
th := Setup(t).InitBasic(t)
channel := th.CreateChannel(t, th.BasicTeam)
guest := th.CreateGuest(t)
th.LinkUserToTeam(t, guest, th.BasicTeam)
th.AddUserToChannel(t, guest, channel)
sp := generateStats(t, th.Context, th.App)
assert.Equal(t, int64(1), sp.SingleChannelGuests)
})
t.Run("post count should be present if number of users extends AnalyticsSettings.MaxUsersForStatistics", func(t *testing.T) {
// Setup a new test helper
th := Setup(t).InitBasic(t)

View file

@ -83,19 +83,20 @@ type SupportPacketDiagnostics struct {
}
type SupportPacketStats struct {
RegisteredUsers int64 `yaml:"registered_users"`
ActiveUsers int64 `yaml:"active_users"`
DailyActiveUsers int64 `yaml:"daily_active_users"`
MonthlyActiveUsers int64 `yaml:"monthly_active_users"`
DeactivatedUsers int64 `yaml:"deactivated_users"`
Guests int64 `yaml:"guests"`
BotAccounts int64 `yaml:"bot_accounts"`
Posts int64 `yaml:"posts"`
Channels int64 `yaml:"channels"`
Teams int64 `yaml:"teams"`
SlashCommands int64 `yaml:"slash_commands"`
IncomingWebhooks int64 `yaml:"incoming_webhooks"`
OutgoingWebhooks int64 `yaml:"outgoing_webhooks"`
RegisteredUsers int64 `yaml:"registered_users"`
ActiveUsers int64 `yaml:"active_users"`
DailyActiveUsers int64 `yaml:"daily_active_users"`
MonthlyActiveUsers int64 `yaml:"monthly_active_users"`
DeactivatedUsers int64 `yaml:"deactivated_users"`
Guests int64 `yaml:"guests"`
SingleChannelGuests int64 `yaml:"single_channel_guests"`
BotAccounts int64 `yaml:"bot_accounts"`
Posts int64 `yaml:"posts"`
Channels int64 `yaml:"channels"`
Teams int64 `yaml:"teams"`
SlashCommands int64 `yaml:"slash_commands"`
IncomingWebhooks int64 `yaml:"incoming_webhooks"`
OutgoingWebhooks int64 `yaml:"outgoing_webhooks"`
}
// SupportPacketJobList contains the list of latest run enterprise job runs.