33const job = require ( '../../../../api/parts/jobs/job.js' ) ,
44 tracker = require ( '../../../../api/parts/mgmt/tracker.js' ) ,
55 log = require ( '../../../../api/utils/log.js' ) ( 'job:stats' ) ,
6- config = require ( " ../../../../frontend/express/config.js" ) ,
6+ config = require ( ' ../../../../frontend/express/config.js' ) ,
77 pluginManager = require ( '../../../pluginManager.js' ) ,
8+ serverStats = require ( '../parts/stats.js' ) ,
89 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+ }
1020
1121const promisedLoadConfigs = function ( db ) {
1222 return new Promise ( ( resolve ) => {
@@ -27,146 +37,171 @@ class StatsJob extends job.Job {
2737 super ( name , data ) ;
2838 }
2939
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+
30124 /**
31125 * Returns a human readable name given application id.
32126 * @param {Object } db - Database object, used for querying
33127 * @param {function } done - Completion callback
34128 * @returns {undefined } Returns nothing, only callback
35129 **/
36130 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 ) => {
39133 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 ) ;
47138 }
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+ }
95144
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 ) ;
108152
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 ;
167164 }
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 ) ;
169193 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 ( ) ;
170205 }
171206 } ) ;
172207 }
@@ -184,4 +219,4 @@ class StatsJob extends job.Job {
184219 }
185220}
186221
187- module . exports = StatsJob ;
222+ module . exports = StatsJob ;
0 commit comments