Adding active users statistics to system console (#5141)
Этот коммит содержится в:
коммит произвёл
enahum
родитель
66dddbdb78
Коммит
11a688d381
26
api/admin.go
26
api/admin.go
@@ -25,6 +25,11 @@ import (
|
|||||||
"github.com/mssola/user_agent"
|
"github.com/mssola/user_agent"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DAY_MILLISECONDS = 24 * 60 * 60 * 1000
|
||||||
|
MONTH_MILLISECONDS = 31 * DAY_MILLISECONDS
|
||||||
|
)
|
||||||
|
|
||||||
func InitAdmin() {
|
func InitAdmin() {
|
||||||
l4g.Debug(utils.T("api.admin.init.debug"))
|
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" {
|
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[0] = &model.AnalyticsRow{"channel_open_count", 0}
|
||||||
rows[1] = &model.AnalyticsRow{"channel_private_count", 0}
|
rows[1] = &model.AnalyticsRow{"channel_private_count", 0}
|
||||||
rows[2] = &model.AnalyticsRow{"post_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[5] = &model.AnalyticsRow{"total_websocket_connections", 0}
|
||||||
rows[6] = &model.AnalyticsRow{"total_master_db_connections", 0}
|
rows[6] = &model.AnalyticsRow{"total_master_db_connections", 0}
|
||||||
rows[7] = &model.AnalyticsRow{"total_read_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)
|
openChan := app.Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_OPEN)
|
||||||
privateChan := app.Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_PRIVATE)
|
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)
|
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 {
|
if r := <-openChan; r.Err != nil {
|
||||||
c.Err = r.Err
|
c.Err = r.Err
|
||||||
return
|
return
|
||||||
@@ -477,6 +487,20 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
rows[7].Value = float64(app.Srv.Store.TotalReadDbConnections())
|
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()))
|
w.Write([]byte(rows.ToJson()))
|
||||||
} else if name == "post_counts_day" {
|
} else if name == "post_counts_day" {
|
||||||
if skipIntensiveQueries {
|
if skipIntensiveQueries {
|
||||||
|
|||||||
@@ -1129,6 +1129,31 @@ func (us SqlUserStore) AnalyticsUniqueUserCount(teamId string) StoreChannel {
|
|||||||
return 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 {
|
func (us SqlUserStore) GetUnreadCount(userId string) StoreChannel {
|
||||||
storeChannel := make(StoreChannel, 1)
|
storeChannel := make(StoreChannel, 1)
|
||||||
|
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ type UserStore interface {
|
|||||||
GetSystemAdminProfiles() StoreChannel
|
GetSystemAdminProfiles() StoreChannel
|
||||||
PermanentDelete(userId string) StoreChannel
|
PermanentDelete(userId string) StoreChannel
|
||||||
AnalyticsUniqueUserCount(teamId string) StoreChannel
|
AnalyticsUniqueUserCount(teamId string) StoreChannel
|
||||||
|
AnalyticsActiveCount(time int64) StoreChannel
|
||||||
GetUnreadCount(userId string) StoreChannel
|
GetUnreadCount(userId string) StoreChannel
|
||||||
GetUnreadCountForChannel(userId string, channelId string) StoreChannel
|
GetUnreadCountForChannel(userId string, channelId string) StoreChannel
|
||||||
GetRecentlyActiveUsersForTeam(teamId string) StoreChannel
|
GetRecentlyActiveUsersForTeam(teamId string) StoreChannel
|
||||||
|
|||||||
@@ -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 firstRow;
|
||||||
let secondRow;
|
let secondRow;
|
||||||
if (isLicensed && skippedIntensiveQueries) {
|
if (isLicensed && skippedIntensiveQueries) {
|
||||||
@@ -406,6 +432,13 @@ class SystemAnalytics extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const thirdRow = (
|
||||||
|
<div className='row'>
|
||||||
|
{dailyActiveUsers}
|
||||||
|
{monthlyActiveUsers}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='wrapper--fixed team_statistics'>
|
<div className='wrapper--fixed team_statistics'>
|
||||||
<h3>
|
<h3>
|
||||||
@@ -417,6 +450,7 @@ class SystemAnalytics extends React.Component {
|
|||||||
{banner}
|
{banner}
|
||||||
{firstRow}
|
{firstRow}
|
||||||
{secondRow}
|
{secondRow}
|
||||||
|
{thirdRow}
|
||||||
{advancedStats}
|
{advancedStats}
|
||||||
{advancedGraphs}
|
{advancedGraphs}
|
||||||
{postTotalGraph}
|
{postTotalGraph}
|
||||||
|
|||||||
@@ -945,6 +945,8 @@
|
|||||||
"analytics.system.textPosts": "Posts with Text-only",
|
"analytics.system.textPosts": "Posts with Text-only",
|
||||||
"analytics.system.title": "System Statistics",
|
"analytics.system.title": "System Statistics",
|
||||||
"analytics.system.totalChannels": "Total Channels",
|
"analytics.system.totalChannels": "Total Channels",
|
||||||
|
"analytics.system.dailyActiveUsers": "Daily Active Users",
|
||||||
|
"analytics.system.monthlyActiveUsers": "Monthly Active Users",
|
||||||
"analytics.system.totalCommands": "Total Commands",
|
"analytics.system.totalCommands": "Total Commands",
|
||||||
"analytics.system.totalFilePosts": "Posts with Files",
|
"analytics.system.totalFilePosts": "Posts with Files",
|
||||||
"analytics.system.totalHashtagPosts": "Posts with Hashtags",
|
"analytics.system.totalHashtagPosts": "Posts with Hashtags",
|
||||||
|
|||||||
@@ -1039,6 +1039,14 @@ export function getStandardAnalytics(teamId) {
|
|||||||
if (data[index].name === 'total_read_db_connections') {
|
if (data[index].name === 'total_read_db_connections') {
|
||||||
stats[StatTypes.TOTAL_READ_DB_CONNECTIONS] = data[index].value;
|
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({
|
AppDispatcher.handleServerAction({
|
||||||
|
|||||||
@@ -260,7 +260,9 @@ export const Constants = {
|
|||||||
NEWLY_CREATED_USERS: null,
|
NEWLY_CREATED_USERS: null,
|
||||||
TOTAL_WEBSOCKET_CONNECTIONS: null,
|
TOTAL_WEBSOCKET_CONNECTIONS: null,
|
||||||
TOTAL_MASTER_DB_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_ACTIVE_USERS: 20,
|
||||||
STAT_MAX_NEW_USERS: 20,
|
STAT_MAX_NEW_USERS: 20,
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user