github.com/crspeller/mattermost-server@v0.0.0-20190328001957-a200beb3d111/app/analytics.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "fmt" 8 9 "github.com/crspeller/mattermost-server/mlog" 10 "github.com/crspeller/mattermost-server/model" 11 "github.com/crspeller/mattermost-server/store" 12 ) 13 14 const ( 15 DAY_MILLISECONDS = 24 * 60 * 60 * 1000 16 MONTH_MILLISECONDS = 31 * DAY_MILLISECONDS 17 ) 18 19 func (a *App) GetAnalytics(name string, teamId string) (model.AnalyticsRows, *model.AppError) { 20 skipIntensiveQueries := false 21 var systemUserCount int64 22 r := <-a.Srv.Store.User().Count(model.UserCountOptions{}) 23 if r.Err != nil { 24 return nil, r.Err 25 } 26 27 systemUserCount = r.Data.(int64) 28 if systemUserCount > int64(*a.Config().AnalyticsSettings.MaxUsersForStatistics) { 29 mlog.Debug(fmt.Sprintf("More than %v users on the system, intensive queries skipped", *a.Config().AnalyticsSettings.MaxUsersForStatistics)) 30 skipIntensiveQueries = true 31 } 32 33 if name == "standard" { 34 var rows model.AnalyticsRows = make([]*model.AnalyticsRow, 11) 35 rows[0] = &model.AnalyticsRow{Name: "channel_open_count", Value: 0} 36 rows[1] = &model.AnalyticsRow{Name: "channel_private_count", Value: 0} 37 rows[2] = &model.AnalyticsRow{Name: "post_count", Value: 0} 38 rows[3] = &model.AnalyticsRow{Name: "unique_user_count", Value: 0} 39 rows[4] = &model.AnalyticsRow{Name: "team_count", Value: 0} 40 rows[5] = &model.AnalyticsRow{Name: "total_websocket_connections", Value: 0} 41 rows[6] = &model.AnalyticsRow{Name: "total_master_db_connections", Value: 0} 42 rows[7] = &model.AnalyticsRow{Name: "total_read_db_connections", Value: 0} 43 rows[8] = &model.AnalyticsRow{Name: "daily_active_users", Value: 0} 44 rows[9] = &model.AnalyticsRow{Name: "monthly_active_users", Value: 0} 45 rows[10] = &model.AnalyticsRow{Name: "inactive_user_count", Value: 0} 46 47 openChan := a.Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_OPEN) 48 privateChan := a.Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_PRIVATE) 49 teamChan := a.Srv.Store.Team().AnalyticsTeamCount() 50 51 var userChan store.StoreChannel 52 var userInactiveChan store.StoreChannel 53 if teamId == "" { 54 userInactiveChan = a.Srv.Store.User().AnalyticsGetInactiveUsersCount() 55 } else { 56 userChan = a.Srv.Store.User().Count(model.UserCountOptions{ 57 TeamId: teamId, 58 }) 59 } 60 61 var postChan store.StoreChannel 62 if !skipIntensiveQueries { 63 postChan = a.Srv.Store.Post().AnalyticsPostCount(teamId, false, false) 64 } 65 66 dailyActiveChan := a.Srv.Store.User().AnalyticsActiveCount(DAY_MILLISECONDS) 67 monthlyActiveChan := a.Srv.Store.User().AnalyticsActiveCount(MONTH_MILLISECONDS) 68 69 r := <-openChan 70 if r.Err != nil { 71 return nil, r.Err 72 } 73 rows[0].Value = float64(r.Data.(int64)) 74 75 r = <-privateChan 76 if r.Err != nil { 77 return nil, r.Err 78 } 79 rows[1].Value = float64(r.Data.(int64)) 80 81 if postChan == nil { 82 rows[2].Value = -1 83 } else { 84 r = <-postChan 85 if r.Err != nil { 86 return nil, r.Err 87 } 88 rows[2].Value = float64(r.Data.(int64)) 89 } 90 91 if userChan == nil { 92 rows[3].Value = float64(systemUserCount) 93 } else { 94 r = <-userChan 95 if r.Err != nil { 96 return nil, r.Err 97 } 98 rows[3].Value = float64(r.Data.(int64)) 99 } 100 101 if userInactiveChan == nil { 102 rows[10].Value = -1 103 } else { 104 r = <-userInactiveChan 105 if r.Err != nil { 106 return nil, r.Err 107 } 108 rows[10].Value = float64(r.Data.(int64)) 109 } 110 111 r = <-teamChan 112 if r.Err != nil { 113 return nil, r.Err 114 } 115 rows[4].Value = float64(r.Data.(int64)) 116 117 // If in HA mode then aggregrate all the stats 118 if a.Cluster != nil && *a.Config().ClusterSettings.Enable { 119 stats, err := a.Cluster.GetClusterStats() 120 if err != nil { 121 return nil, err 122 } 123 124 totalSockets := a.TotalWebsocketConnections() 125 totalMasterDb := a.Srv.Store.TotalMasterDbConnections() 126 totalReadDb := a.Srv.Store.TotalReadDbConnections() 127 128 for _, stat := range stats { 129 totalSockets = totalSockets + stat.TotalWebsocketConnections 130 totalMasterDb = totalMasterDb + stat.TotalMasterDbConnections 131 totalReadDb = totalReadDb + stat.TotalReadDbConnections 132 } 133 134 rows[5].Value = float64(totalSockets) 135 rows[6].Value = float64(totalMasterDb) 136 rows[7].Value = float64(totalReadDb) 137 138 } else { 139 rows[5].Value = float64(a.TotalWebsocketConnections()) 140 rows[6].Value = float64(a.Srv.Store.TotalMasterDbConnections()) 141 rows[7].Value = float64(a.Srv.Store.TotalReadDbConnections()) 142 } 143 144 r = <-dailyActiveChan 145 if r.Err != nil { 146 return nil, r.Err 147 } 148 rows[8].Value = float64(r.Data.(int64)) 149 150 r = <-monthlyActiveChan 151 if r.Err != nil { 152 return nil, r.Err 153 } 154 rows[9].Value = float64(r.Data.(int64)) 155 156 return rows, nil 157 } else if name == "post_counts_day" { 158 if skipIntensiveQueries { 159 rows := model.AnalyticsRows{&model.AnalyticsRow{Name: "", Value: -1}} 160 return rows, nil 161 } 162 163 r := <-a.Srv.Store.Post().AnalyticsPostCountsByDay(teamId) 164 if r.Err != nil { 165 return nil, r.Err 166 } 167 return r.Data.(model.AnalyticsRows), nil 168 } else if name == "user_counts_with_posts_day" { 169 if skipIntensiveQueries { 170 rows := model.AnalyticsRows{&model.AnalyticsRow{Name: "", Value: -1}} 171 return rows, nil 172 } 173 174 r := <-a.Srv.Store.Post().AnalyticsUserCountsWithPostsByDay(teamId) 175 if r.Err != nil { 176 return nil, r.Err 177 } 178 return r.Data.(model.AnalyticsRows), nil 179 } else if name == "extra_counts" { 180 var rows model.AnalyticsRows = make([]*model.AnalyticsRow, 6) 181 rows[0] = &model.AnalyticsRow{Name: "file_post_count", Value: 0} 182 rows[1] = &model.AnalyticsRow{Name: "hashtag_post_count", Value: 0} 183 rows[2] = &model.AnalyticsRow{Name: "incoming_webhook_count", Value: 0} 184 rows[3] = &model.AnalyticsRow{Name: "outgoing_webhook_count", Value: 0} 185 rows[4] = &model.AnalyticsRow{Name: "command_count", Value: 0} 186 rows[5] = &model.AnalyticsRow{Name: "session_count", Value: 0} 187 188 iHookChan := a.Srv.Store.Webhook().AnalyticsIncomingCount(teamId) 189 oHookChan := a.Srv.Store.Webhook().AnalyticsOutgoingCount(teamId) 190 commandChan := a.Srv.Store.Command().AnalyticsCommandCount(teamId) 191 sessionChan := a.Srv.Store.Session().AnalyticsSessionCount() 192 193 var fileChan store.StoreChannel 194 var hashtagChan store.StoreChannel 195 if !skipIntensiveQueries { 196 fileChan = a.Srv.Store.Post().AnalyticsPostCount(teamId, true, false) 197 hashtagChan = a.Srv.Store.Post().AnalyticsPostCount(teamId, false, true) 198 } 199 200 if fileChan == nil { 201 rows[0].Value = -1 202 } else { 203 r := <-fileChan 204 if r.Err != nil { 205 return nil, r.Err 206 } 207 rows[0].Value = float64(r.Data.(int64)) 208 } 209 210 if hashtagChan == nil { 211 rows[1].Value = -1 212 } else { 213 r := <-hashtagChan 214 if r.Err != nil { 215 return nil, r.Err 216 } 217 rows[1].Value = float64(r.Data.(int64)) 218 } 219 220 r := <-iHookChan 221 if r.Err != nil { 222 return nil, r.Err 223 } 224 rows[2].Value = float64(r.Data.(int64)) 225 226 r = <-oHookChan 227 if r.Err != nil { 228 return nil, r.Err 229 } 230 rows[3].Value = float64(r.Data.(int64)) 231 232 r = <-commandChan 233 if r.Err != nil { 234 return nil, r.Err 235 } 236 rows[4].Value = float64(r.Data.(int64)) 237 238 r = <-sessionChan 239 if r.Err != nil { 240 return nil, r.Err 241 } 242 rows[5].Value = float64(r.Data.(int64)) 243 244 return rows, nil 245 } 246 247 return nil, nil 248 } 249 250 func (a *App) GetRecentlyActiveUsersForTeam(teamId string) (map[string]*model.User, *model.AppError) { 251 result := <-a.Srv.Store.User().GetRecentlyActiveUsersForTeam(teamId, 0, 100) 252 if result.Err != nil { 253 return nil, result.Err 254 } 255 256 users := result.Data.([]*model.User) 257 userMap := make(map[string]*model.User) 258 259 for _, user := range users { 260 userMap[user.Id] = user 261 } 262 263 return userMap, nil 264 } 265 266 func (a *App) GetRecentlyActiveUsersForTeamPage(teamId string, page, perPage int, asAdmin bool) ([]*model.User, *model.AppError) { 267 var users []*model.User 268 result := <-a.Srv.Store.User().GetRecentlyActiveUsersForTeam(teamId, page*perPage, perPage) 269 if result.Err != nil { 270 return nil, result.Err 271 } 272 users = result.Data.([]*model.User) 273 274 return a.sanitizeProfiles(users, asAdmin), nil 275 } 276 277 func (a *App) GetNewUsersForTeamPage(teamId string, page, perPage int, asAdmin bool) ([]*model.User, *model.AppError) { 278 var users []*model.User 279 result := <-a.Srv.Store.User().GetNewUsersForTeam(teamId, page*perPage, perPage) 280 if result.Err != nil { 281 return nil, result.Err 282 } 283 users = result.Data.([]*model.User) 284 285 return a.sanitizeProfiles(users, asAdmin), nil 286 }