summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2017-01-20 15:24:53 -0500
committerenahum <nahumhbl@gmail.com>2017-01-20 17:24:53 -0300
commit11a688d3813646aeb97f58b61c083b019da66cfc (patch)
tree2d1c7085837505fb49ecba4dd49c8a34b0a5888c
parent66dddbdb7895a87e858f9238e546cedc6e05e34e (diff)
downloadchat-11a688d3813646aeb97f58b61c083b019da66cfc.tar.gz
chat-11a688d3813646aeb97f58b61c083b019da66cfc.tar.bz2
chat-11a688d3813646aeb97f58b61c083b019da66cfc.zip
Adding active users statistics to system console (#5141)
-rw-r--r--api/admin.go26
-rw-r--r--store/sql_user_store.go25
-rw-r--r--store/store.go1
-rw-r--r--webapp/components/analytics/system_analytics.jsx34
-rw-r--r--webapp/i18n/en.json2
-rw-r--r--webapp/utils/async_client.jsx8
-rw-r--r--webapp/utils/constants.jsx4
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,