diff options
author | Christopher Speller <crspeller@gmail.com> | 2017-01-20 15:24:53 -0500 |
---|---|---|
committer | enahum <nahumhbl@gmail.com> | 2017-01-20 17:24:53 -0300 |
commit | 11a688d3813646aeb97f58b61c083b019da66cfc (patch) | |
tree | 2d1c7085837505fb49ecba4dd49c8a34b0a5888c | |
parent | 66dddbdb7895a87e858f9238e546cedc6e05e34e (diff) | |
download | chat-11a688d3813646aeb97f58b61c083b019da66cfc.tar.gz chat-11a688d3813646aeb97f58b61c083b019da66cfc.tar.bz2 chat-11a688d3813646aeb97f58b61c083b019da66cfc.zip |
Adding active users statistics to system console (#5141)
-rw-r--r-- | api/admin.go | 26 | ||||
-rw-r--r-- | store/sql_user_store.go | 25 | ||||
-rw-r--r-- | store/store.go | 1 | ||||
-rw-r--r-- | webapp/components/analytics/system_analytics.jsx | 34 | ||||
-rw-r--r-- | webapp/i18n/en.json | 2 | ||||
-rw-r--r-- | webapp/utils/async_client.jsx | 8 | ||||
-rw-r--r-- | webapp/utils/constants.jsx | 4 |
7 files changed, 98 insertions, 2 deletions
diff --git a/api/admin.go b/api/admin.go index 300796bad..4e4d21b0b 100644 --- a/api/admin.go +++ b/api/admin.go @@ -25,6 +25,11 @@ import ( "github.com/mssola/user_agent" ) +const ( + DAY_MILLISECONDS = 24 * 60 * 60 * 1000 + MONTH_MILLISECONDS = 31 * DAY_MILLISECONDS +) + func InitAdmin() { l4g.Debug(utils.T("api.admin.init.debug")) @@ -382,7 +387,7 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { } if name == "standard" { - var rows model.AnalyticsRows = make([]*model.AnalyticsRow, 8) + var rows model.AnalyticsRows = make([]*model.AnalyticsRow, 10) rows[0] = &model.AnalyticsRow{"channel_open_count", 0} rows[1] = &model.AnalyticsRow{"channel_private_count", 0} rows[2] = &model.AnalyticsRow{"post_count", 0} @@ -391,6 +396,8 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { rows[5] = &model.AnalyticsRow{"total_websocket_connections", 0} rows[6] = &model.AnalyticsRow{"total_master_db_connections", 0} rows[7] = &model.AnalyticsRow{"total_read_db_connections", 0} + rows[8] = &model.AnalyticsRow{"daily_active_users", 0} + rows[9] = &model.AnalyticsRow{"monthly_active_users", 0} openChan := app.Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_OPEN) privateChan := app.Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_PRIVATE) @@ -406,6 +413,9 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { postChan = app.Srv.Store.Post().AnalyticsPostCount(teamId, false, false) } + dailyActiveChan := app.Srv.Store.User().AnalyticsActiveCount(DAY_MILLISECONDS) + monthlyActiveChan := app.Srv.Store.User().AnalyticsActiveCount(MONTH_MILLISECONDS) + if r := <-openChan; r.Err != nil { c.Err = r.Err return @@ -477,6 +487,20 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { rows[7].Value = float64(app.Srv.Store.TotalReadDbConnections()) } + if r := <-dailyActiveChan; r.Err != nil { + c.Err = r.Err + return + } else { + rows[8].Value = float64(r.Data.(int64)) + } + + if r := <-monthlyActiveChan; r.Err != nil { + c.Err = r.Err + return + } else { + rows[9].Value = float64(r.Data.(int64)) + } + w.Write([]byte(rows.ToJson())) } else if name == "post_counts_day" { if skipIntensiveQueries { diff --git a/store/sql_user_store.go b/store/sql_user_store.go index 533757479..09742a4f4 100644 --- a/store/sql_user_store.go +++ b/store/sql_user_store.go @@ -1129,6 +1129,31 @@ func (us SqlUserStore) AnalyticsUniqueUserCount(teamId string) StoreChannel { return storeChannel } +func (us SqlUserStore) AnalyticsActiveCount(timePeriod int64) StoreChannel { + + storeChannel := make(StoreChannel, 1) + + go func() { + result := StoreResult{} + + time := model.GetMillis() - timePeriod + + query := "SELECT COUNT(*) FROM Status WHERE LastActivityAt > :Time" + + v, err := us.GetReplica().SelectInt(query, map[string]interface{}{"Time": time}) + if err != nil { + result.Err = model.NewLocAppError("SqlUserStore.AnalyticsDailyActiveUsers", "store.sql_user.analytics_daily_active_users.app_error", nil, err.Error()) + } else { + result.Data = v + } + + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + func (us SqlUserStore) GetUnreadCount(userId string) StoreChannel { storeChannel := make(StoreChannel, 1) diff --git a/store/store.go b/store/store.go index 88a553b7c..730a923c5 100644 --- a/store/store.go +++ b/store/store.go @@ -175,6 +175,7 @@ type UserStore interface { GetSystemAdminProfiles() StoreChannel PermanentDelete(userId string) StoreChannel AnalyticsUniqueUserCount(teamId string) StoreChannel + AnalyticsActiveCount(time int64) StoreChannel GetUnreadCount(userId string) StoreChannel GetUnreadCountForChannel(userId string, channelId string) StoreChannel GetRecentlyActiveUsersForTeam(teamId string) StoreChannel diff --git a/webapp/components/analytics/system_analytics.jsx b/webapp/components/analytics/system_analytics.jsx index dd7b90260..89cc98f0b 100644 --- a/webapp/components/analytics/system_analytics.jsx +++ b/webapp/components/analytics/system_analytics.jsx @@ -358,6 +358,32 @@ class SystemAnalytics extends React.Component { /> ); + const dailyActiveUsers = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.dailyActiveUsers' + defaultMessage='Daily Active Users' + /> + } + icon='fa-users' + count={stats[StatTypes.DAILY_ACTIVE_USERS]} + /> + ); + + const monthlyActiveUsers = ( + <StatisticCount + title={ + <FormattedMessage + id='analytics.system.monthlyActiveUsers' + defaultMessage='Monthly Active Users' + /> + } + icon='fa-users' + count={stats[StatTypes.MONTHLY_ACTIVE_USERS]} + /> + ); + let firstRow; let secondRow; if (isLicensed && skippedIntensiveQueries) { @@ -406,6 +432,13 @@ class SystemAnalytics extends React.Component { ); } + const thirdRow = ( + <div className='row'> + {dailyActiveUsers} + {monthlyActiveUsers} + </div> + ); + return ( <div className='wrapper--fixed team_statistics'> <h3> @@ -417,6 +450,7 @@ class SystemAnalytics extends React.Component { {banner} {firstRow} {secondRow} + {thirdRow} {advancedStats} {advancedGraphs} {postTotalGraph} diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index 1513a4afe..daa0434dc 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -945,6 +945,8 @@ "analytics.system.textPosts": "Posts with Text-only", "analytics.system.title": "System Statistics", "analytics.system.totalChannels": "Total Channels", + "analytics.system.dailyActiveUsers": "Daily Active Users", + "analytics.system.monthlyActiveUsers": "Monthly Active Users", "analytics.system.totalCommands": "Total Commands", "analytics.system.totalFilePosts": "Posts with Files", "analytics.system.totalHashtagPosts": "Posts with Hashtags", diff --git a/webapp/utils/async_client.jsx b/webapp/utils/async_client.jsx index 25724ec5e..cd38be811 100644 --- a/webapp/utils/async_client.jsx +++ b/webapp/utils/async_client.jsx @@ -1039,6 +1039,14 @@ export function getStandardAnalytics(teamId) { if (data[index].name === 'total_read_db_connections') { stats[StatTypes.TOTAL_READ_DB_CONNECTIONS] = data[index].value; } + + if (data[index].name === 'daily_active_users') { + stats[StatTypes.DAILY_ACTIVE_USERS] = data[index].value; + } + + if (data[index].name === 'monthly_active_users') { + stats[StatTypes.MONTHLY_ACTIVE_USERS] = data[index].value; + } } AppDispatcher.handleServerAction({ diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx index b1c188d89..86147ee8c 100644 --- a/webapp/utils/constants.jsx +++ b/webapp/utils/constants.jsx @@ -260,7 +260,9 @@ export const Constants = { NEWLY_CREATED_USERS: null, TOTAL_WEBSOCKET_CONNECTIONS: null, TOTAL_MASTER_DB_CONNECTIONS: null, - TOTAL_READ_DB_CONNECTIONS: null + TOTAL_READ_DB_CONNECTIONS: null, + DAILY_ACTIVE_USERS: null, + MONTHLY_ACTIVE_USERS: null }), STAT_MAX_ACTIVE_USERS: 20, STAT_MAX_NEW_USERS: 20, |