3
3
const job = require ( '../../../../api/parts/jobs/job.js' ) ,
4
4
tracker = require ( '../../../../api/parts/mgmt/tracker.js' ) ,
5
5
log = require ( '../../../../api/utils/log.js' ) ( 'job:stats' ) ,
6
- config = require ( " ../../../../frontend/express/config.js" ) ,
6
+ config = require ( ' ../../../../frontend/express/config.js' ) ,
7
7
pluginManager = require ( '../../../pluginManager.js' ) ,
8
+ serverStats = require ( '../parts/stats.js' ) ,
8
9
moment = require ( 'moment-timezone' ) ,
9
- request = require ( 'countly-request' ) ( pluginManager . getConfig ( "security" ) ) ;
10
+ request = require ( 'countly-request' ) ( pluginManager . getConfig ( 'security' ) ) ;
11
+
12
+ let drill ;
13
+ try {
14
+ drill = require ( '../../../drill/api/parts/data/drill.js' ) ;
15
+ }
16
+ catch ( ex ) {
17
+ log . e ( ex ) ;
18
+ drill = null ;
19
+ }
10
20
11
21
const promisedLoadConfigs = function ( db ) {
12
22
return new Promise ( ( resolve ) => {
@@ -27,146 +37,171 @@ class StatsJob extends job.Job {
27
37
super ( name , data ) ;
28
38
}
29
39
40
+ /**
41
+ * @param {Object } allData - All server stats data from the beginning of time
42
+ * @returns {Object } Sum of all data, average data per month, and last three month data
43
+ */
44
+ static generateDataSummary ( allData ) {
45
+ const data = { } ;
46
+ data . all = 0 ;
47
+ data . month3 = [ ] ;
48
+ const utcMoment = moment . utc ( ) ;
49
+ const months = { } ;
50
+ for ( let i = 0 ; i < 3 ; i ++ ) {
51
+ months [ utcMoment . format ( 'YYYY:M' ) ] = true ;
52
+ utcMoment . subtract ( 1 , 'months' ) ;
53
+ }
54
+ for ( const [ key , value ] of Object . entries ( allData ) ) {
55
+ data . all += value ;
56
+ if ( months [ key ] ) {
57
+ data . month3 . push ( key + ' - ' + ( value ) ) ;
58
+ }
59
+ }
60
+ data . avg = Math . round ( ( data . all / Object . keys ( allData ) . length ) * 100 ) / 100 ;
61
+
62
+ return data ;
63
+ }
64
+
65
+ /**
66
+ * @param {Object } allData - All server stats data from the beginning of time
67
+ * @returns {Object } Monthly data
68
+ */
69
+ static generateDataMonthly ( allData ) {
70
+ const data = { } ;
71
+ const utcMoment = moment . utc ( ) ;
72
+ const ids = { } ;
73
+ const ids6 = { } ;
74
+ const ids0 = { } ;
75
+ const order = [ ] ;
76
+
77
+ for ( let i = 0 ; i < 12 ; i ++ ) {
78
+ order . push ( utcMoment . format ( 'MMM YYYY' ) ) ;
79
+ ids [ utcMoment . format ( 'YYYY:M' ) ] = utcMoment . format ( 'MMM YYYY' ) ;
80
+ if ( i < 7 ) {
81
+ ids6 [ utcMoment . format ( 'YYYY:M' ) ] = utcMoment . format ( 'MMM YYYY' ) ;
82
+ }
83
+ if ( i === 0 ) {
84
+ ids0 [ utcMoment . format ( 'YYYY:M' ) ] = utcMoment . format ( 'MMM YYYY' ) ;
85
+ }
86
+ utcMoment . subtract ( 1 , 'months' ) ;
87
+ }
88
+
89
+ const DP = { } ;
90
+ data . DP = [ ] ;
91
+ let avg12monthDP = 0 ;
92
+ let avg6monthDP = 0 ;
93
+
94
+ let avg12 = 0 ;
95
+ let avg6 = 0 ;
96
+ for ( const [ key , value ] of Object . entries ( allData ) ) {
97
+ if ( ids [ key ] ) {
98
+ DP [ ids [ key ] ] = value ;
99
+
100
+ if ( ! ids0 [ key ] ) {
101
+ avg12monthDP += DP [ ids [ key ] ] ;
102
+ avg12 ++ ;
103
+ }
104
+ if ( ids6 [ key ] && ! ids0 [ key ] ) {
105
+ avg6monthDP += DP [ ids [ key ] ] ;
106
+ avg6 ++ ;
107
+ }
108
+ }
109
+ }
110
+
111
+ for ( let i = 0 ; i < order . length ; i ++ ) {
112
+ data . DP . push ( ( i < 9 ? '0' + ( i + 1 ) : i + 1 ) + '. ' + order [ i ] + ': ' + ( ( DP [ order [ i ] ] || 0 ) . toLocaleString ( ) ) ) ;
113
+ }
114
+ if ( avg12 ) {
115
+ data [ 'Last 12 months' ] = Math . round ( avg12monthDP / avg12 ) . toLocaleString ( ) ;
116
+ }
117
+ if ( avg6 ) {
118
+ data [ 'Last 6 months' ] = Math . round ( avg6monthDP / avg6 ) . toLocaleString ( ) ;
119
+ }
120
+
121
+ return data ;
122
+ }
123
+
30
124
/**
31
125
* Returns a human readable name given application id.
32
126
* @param {Object } db - Database object, used for querying
33
127
* @param {function } done - Completion callback
34
128
* @returns {undefined } Returns nothing, only callback
35
129
**/
36
130
run ( db , done ) {
37
- if ( config . web . track !== " none" ) {
38
- db . collection ( " members" ) . find ( { global_admin : true } ) . toArray ( function ( err , members ) {
131
+ if ( config . web . track !== ' none' ) {
132
+ db . collection ( ' members' ) . find ( { global_admin : true } ) . toArray ( async ( err , members ) => {
39
133
if ( ! err && members . length > 0 ) {
40
- db . collection ( "server_stats_data_points" ) . aggregate ( [
41
- {
42
- $group : {
43
- _id : "$m" ,
44
- e : { $sum : "$e" } ,
45
- s : { $sum : "$s" }
46
- }
134
+ let license = { } ;
135
+ if ( drill ) {
136
+ try {
137
+ license = await drill . loadLicense ( undefined , db ) ;
47
138
}
48
- ] , { allowDiskUse : true } , async function ( error , allData ) {
49
- if ( ! error ) {
50
- var data = { } ;
51
- data . all = 0 ;
52
- data . month3 = [ ] ;
53
- var utcMoment = moment . utc ( ) ;
54
- var months = { } ;
55
- for ( let i = 0 ; i < 3 ; i ++ ) {
56
- months [ utcMoment . format ( "YYYY:M" ) ] = true ;
57
- utcMoment . subtract ( 1 , 'months' ) ;
58
- }
59
- for ( let i = 0 ; i < allData . length ; i ++ ) {
60
- data . all += allData [ i ] . e + allData [ i ] . s ;
61
- if ( months [ allData [ i ] . _id ] ) {
62
- data . month3 . push ( allData [ i ] . _id + " - " + ( allData [ i ] . e + allData [ i ] . s ) ) ;
63
- }
64
- }
65
- data . avg = Math . round ( ( data . all / allData . length ) * 100 ) / 100 ;
66
- var date = new Date ( ) ;
67
- var usersData = [ ] ;
68
-
69
- await promisedLoadConfigs ( db ) ;
70
-
71
- let domain = '' ;
72
-
73
- try {
74
- // try to extract hostname from full domain url
75
- const urlObj = new URL ( pluginManager . getConfig ( 'api' ) . domain ) ;
76
- domain = urlObj . hostname ;
77
- }
78
- catch ( _ ) {
79
- // do nothing, domain from config will be used as is
80
- }
81
-
82
- usersData . push ( {
83
- device_id : domain ,
84
- timestamp : Math . floor ( date . getTime ( ) / 1000 ) ,
85
- hour : date . getHours ( ) ,
86
- dow : date . getDay ( ) ,
87
- user_details : JSON . stringify ( {
88
- custom : {
89
- dataPointsAll : data . all ,
90
- dataPointsMonthlyAvg : data . avg ,
91
- dataPointsLast3Months : data . month3
92
- }
93
- } )
94
- } ) ;
139
+ catch ( error ) {
140
+ log . e ( error ) ;
141
+ // do nothing, most likely there is no license
142
+ }
143
+ }
95
144
96
- var formData = {
97
- app_key : "e70ec21cbe19e799472dfaee0adb9223516d238f" ,
98
- requests : JSON . stringify ( usersData )
99
- } ;
100
-
101
- request . post ( {
102
- url : 'https://stats.count.ly/i/bulk' ,
103
- body : formData
104
- } , function ( a ) {
105
- log . d ( 'Done running stats job: %j' , a ) ;
106
- done ( ) ;
107
- } ) ;
145
+ const options = {
146
+ monthlyBreakdown : true ,
147
+ license_hosting : license . license_hosting ,
148
+ } ;
149
+
150
+ serverStats . fetchDatapoints ( db , { } , options , async ( allData ) => {
151
+ const dataSummary = StatsJob . generateDataSummary ( allData ) ;
108
152
109
- if ( tracker . isEnabled ( ) ) {
110
- utcMoment = moment . utc ( ) ;
111
- data = { } ;
112
- var ids = { } ;
113
- var ids6 = { } ;
114
- var ids0 = { } ;
115
- var order = [ ] ;
116
- var Countly = tracker . getSDK ( ) ;
117
- for ( let i = 0 ; i < 12 ; i ++ ) {
118
- order . push ( utcMoment . format ( "MMM YYYY" ) ) ;
119
- ids [ utcMoment . format ( "YYYY:M" ) ] = utcMoment . format ( "MMM YYYY" ) ;
120
- if ( i < 7 ) {
121
- ids6 [ utcMoment . format ( "YYYY:M" ) ] = utcMoment . format ( "MMM YYYY" ) ;
122
- }
123
- if ( i === 0 ) {
124
- ids0 [ utcMoment . format ( "YYYY:M" ) ] = utcMoment . format ( "MMM YYYY" ) ;
125
- }
126
- utcMoment . subtract ( 1 , 'months' ) ;
127
- }
128
-
129
- var DP = { } ;
130
- data . DP = [ ] ;
131
- var avg12monthDP = 0 ;
132
- var avg6monthDP = 0 ;
133
-
134
- var avg12 = 0 ;
135
- var avg6 = 0 ;
136
- for ( let i = 0 ; i < allData . length ; i ++ ) {
137
- if ( ids [ allData [ i ] . _id ] ) {
138
- var val = allData [ i ] . e + allData [ i ] . s ;
139
- DP [ ids [ allData [ i ] . _id ] ] = val ;
140
- if ( ! ids0 [ allData [ i ] . _id ] ) {
141
- avg12monthDP += DP [ ids [ allData [ i ] . _id ] ] ;
142
- avg12 ++ ;
143
- }
144
- if ( ids6 [ allData [ i ] . _id ] && ! ids0 [ allData [ i ] . _id ] ) {
145
- avg6monthDP += DP [ ids [ allData [ i ] . _id ] ] ;
146
- avg6 ++ ;
147
- }
148
- }
149
- }
150
-
151
- for ( let i = 0 ; i < order . length ; i ++ ) {
152
- data . DP . push ( ( i < 9 ? "0" + ( i + 1 ) : i + 1 ) + ". " + order [ i ] + ": " + ( ( DP [ order [ i ] ] || 0 ) . toLocaleString ( ) ) ) ;
153
- }
154
-
155
- if ( avg12 ) {
156
- data [ "Last 12 months" ] = Math . round ( avg12monthDP / avg12 ) . toLocaleString ( ) ;
157
- }
158
- if ( avg6 ) {
159
- data [ "Last 6 months" ] = Math . round ( avg6monthDP / avg6 ) . toLocaleString ( ) ;
160
- }
161
- Countly . user_details ( {
162
- "custom" : data
163
- } ) ;
164
-
165
- Countly . userData . save ( ) ;
166
- }
153
+ let date = new Date ( ) ;
154
+ const usersData = [ ] ;
155
+
156
+ await promisedLoadConfigs ( db ) ;
157
+
158
+ let domain = '' ;
159
+
160
+ try {
161
+ // try to extract hostname from full domain url
162
+ const urlObj = new URL ( pluginManager . getConfig ( 'api' ) . domain ) ;
163
+ domain = urlObj . hostname ;
167
164
}
168
- else {
165
+ catch ( _ ) {
166
+ // do nothing, domain from config will be used as is
167
+ }
168
+
169
+ usersData . push ( {
170
+ device_id : domain ,
171
+ timestamp : Math . floor ( date . getTime ( ) / 1000 ) ,
172
+ hour : date . getHours ( ) ,
173
+ dow : date . getDay ( ) ,
174
+ user_details : JSON . stringify ( {
175
+ custom : {
176
+ dataPointsAll : dataSummary . all ,
177
+ dataPointsMonthlyAvg : dataSummary . avg ,
178
+ dataPointsLast3Months : dataSummary . month3 ,
179
+ } ,
180
+ } ) ,
181
+ } ) ;
182
+
183
+ var formData = {
184
+ app_key : 'e70ec21cbe19e799472dfaee0adb9223516d238f' ,
185
+ requests : JSON . stringify ( usersData )
186
+ } ;
187
+
188
+ request . post ( {
189
+ url : 'https://stats.count.ly/i/bulk' ,
190
+ json : formData
191
+ } , function ( a ) {
192
+ log . d ( 'Done running stats job: %j' , a ) ;
169
193
done ( ) ;
194
+ } ) ;
195
+
196
+ if ( tracker . isEnabled ( ) ) {
197
+ const dataMonthly = StatsJob . generateDataMonthly ( allData ) ;
198
+
199
+ const Countly = tracker . getSDK ( ) ;
200
+ Countly . user_details ( {
201
+ 'custom' : dataMonthly ,
202
+ } ) ;
203
+
204
+ Countly . userData . save ( ) ;
170
205
}
171
206
} ) ;
172
207
}
@@ -184,4 +219,4 @@ class StatsJob extends job.Job {
184
219
}
185
220
}
186
221
187
- module . exports = StatsJob ;
222
+ module . exports = StatsJob ;
0 commit comments