@@ -324,7 +324,7 @@ fetch.fetchDashboard = function(params) {
324
324
fetch . getTotalUsersObj ( "users" , params , function ( dbTotalUsersObj ) {
325
325
countlyCommon . setPeriod ( period . period ) ;
326
326
327
- countlySession . setTotalUsersObj ( fetch . formatTotalUsersObj ( dbTotalUsersObj ) ) ;
327
+ countlySession . setTotalUsersObj ( fetch . formatTotalUsersObj ( dbTotalUsersObj ) , fetch . formatTotalUsersObj ( dbTotalUsersObj , true ) ) ;
328
328
329
329
var data = {
330
330
out : period . out ,
@@ -440,7 +440,7 @@ fetch.fetchAllApps = function(params) {
440
440
441
441
fetch . getTotalUsersObj ( "users" , params , function ( dbTotalUsersObj ) {
442
442
countlySession . setDb ( usersDoc || { } ) ;
443
- countlySession . setTotalUsersObj ( fetch . formatTotalUsersObj ( dbTotalUsersObj ) ) ;
443
+ countlySession . setTotalUsersObj ( fetch . formatTotalUsersObj ( dbTotalUsersObj ) , fetch . formatTotalUsersObj ( dbTotalUsersObj , true ) ) ;
444
444
445
445
var sessionData = countlySession . getSessionData ( ) ;
446
446
var charts = {
@@ -553,7 +553,7 @@ fetch.fetchCountries = function(params) {
553
553
fetch . getTotalUsersObj ( "countries" , params , function ( dbTotalUsersObj ) {
554
554
countlyCommon . setPeriod ( period . period ) ;
555
555
556
- countlyLocation . setTotalUsersObj ( fetch . formatTotalUsersObj ( dbTotalUsersObj ) ) ;
556
+ countlyLocation . setTotalUsersObj ( fetch . formatTotalUsersObj ( dbTotalUsersObj ) , fetch . formatTotalUsersObj ( dbTotalUsersObj , true ) ) ;
557
557
558
558
var data = {
559
559
out : period . out ,
@@ -974,7 +974,7 @@ fetch.getTotalUsersObj = function(metric, params, callback) {
974
974
} ;
975
975
976
976
/**
977
- * Get data for estimating total users count if period contains today with options
977
+ * Get data for estimating total users count allowing plugins to add their own data
978
978
* @param {string } metric - name of the collection where to get data from
979
979
* @param {params } params - params object with app_id and date
980
980
* @param {object= } options - additional optional settings
@@ -998,7 +998,7 @@ fetch.getTotalUsersObjWithOptions = function(metric, params, options, callback)
998
998
999
999
/*
1000
1000
List of shortcodes in app_users document for different metrics
1001
- */
1001
+ */
1002
1002
var shortcodesForMetrics = {
1003
1003
"devices" : "d" ,
1004
1004
"app_versions" : "av" ,
@@ -1010,116 +1010,126 @@ fetch.getTotalUsersObjWithOptions = function(metric, params, options, callback)
1010
1010
"carriers" : "c"
1011
1011
} ;
1012
1012
1013
+ if ( ! params . time ) {
1014
+ params . time = common . initTimeObj ( params . appTimezone , params . qstring . timestamp ) ;
1015
+ }
1016
+
1013
1017
/*
1014
- This API endpoint /o?method=total_users should only be used if
1015
- selected period contains today
1016
- */
1017
- if ( periodObj . periodContainsToday ) {
1018
- /*
1019
- Aggregation query uses this variable for $match operation
1020
- We skip uid-sequence document and filter results by last session timestamp
1021
- */
1022
- var match = { ls : countlyCommon . getTimestampRangeQuery ( params , true ) } ;
1018
+ Aggregation query uses this variable for $match operation
1019
+ We skip uid-sequence document and filter results by last session timestamp
1020
+ */
1021
+ var match = { ls : countlyCommon . getTimestampRangeQuery ( params , true ) } ;
1023
1022
1024
- /*
1025
- Let plugins register their short codes and match queries
1026
- */
1027
- plugins . dispatch ( "/o/method/total_users" , {
1028
- shortcodesForMetrics : shortcodesForMetrics ,
1029
- match : match
1030
- } ) ;
1023
+ /*
1024
+ Let plugins register their short codes and match queries
1025
+ */
1026
+ plugins . dispatch ( "/o/method/total_users" , {
1027
+ shortcodesForMetrics : shortcodesForMetrics ,
1028
+ match : match
1029
+ } ) ;
1031
1030
1032
- /*
1033
- Aggregation query uses this variable for $group operation
1034
- If there is no corresponding shortcode default is to count all
1035
- users in this period
1036
- */
1037
- var groupBy = ( shortcodesForMetrics [ metric ] ) ? "$" + shortcodesForMetrics [ metric ] : "users" ;
1031
+ var ob = { params : params , period : periodObj , metric : metric , options : options , result : [ ] , shortcodesForMetrics : shortcodesForMetrics , match : match } ;
1038
1032
1033
+ plugins . dispatch ( "/estimation/correction" , ob , function ( ) {
1039
1034
/*
1040
- In app users we store city information even if user is not from
1041
- the selected timezone country of the app. We $match to get city
1042
- information only for users in app's configured country
1043
- */
1044
- if ( metric === "cities" ) {
1045
- match . cc = params . app_cc ;
1046
- }
1047
-
1048
- options . db . collection ( "app_users" + params . app_id ) . aggregate ( [
1049
- { $match : match } ,
1050
- {
1051
- $group : {
1052
- _id : groupBy ,
1053
- u : { $sum : 1 }
1054
- }
1035
+ If no plugin has returned any estimation corrections then
1036
+ this API endpoint /o?method=total_users should only be used if
1037
+ selected period contains today
1038
+ */
1039
+ if ( ob . result . length === 0 && periodObj . periodContainsToday ) {
1040
+
1041
+ /*
1042
+ Aggregation query uses this variable for $group operation
1043
+ If there is no corresponding shortcode default is to count all
1044
+ users in this period
1045
+ */
1046
+ var groupBy = ( shortcodesForMetrics [ metric ] ) ? "$" + shortcodesForMetrics [ metric ] : "users" ;
1047
+
1048
+ /*
1049
+ In app users we store city information even if user is not from
1050
+ the selected timezone country of the app. We $match to get city
1051
+ information only for users in app's configured country
1052
+ */
1053
+ if ( metric === "cities" ) {
1054
+ match . cc = params . app_cc ;
1055
1055
}
1056
- ] , { allowDiskUse : true } , function ( error , appUsersDbResult ) {
1057
-
1058
- if ( plugins . getConfig ( "api" , params . app && params . app . plugins , true ) . metric_changes && shortcodesForMetrics [ metric ] ) {
1059
1056
1060
- var metricChangesMatch = { ts : countlyCommon . getTimestampRangeQuery ( params , true ) } ;
1061
-
1062
- metricChangesMatch [ shortcodesForMetrics [ metric ] + ".o" ] = { "$exists" : true } ;
1063
-
1064
- /*
1065
- We track changes to metrics such as app version in metric_changesAPPID collection;
1066
- { "uid" : "2", "ts" : 1462028715, "av" : { "o" : "1:0:1", "n" : "1:1" } }
1067
-
1068
- While returning a total user result for any metric, we check metric_changes to see
1069
- if any metric change happened in the selected period and include this in the result
1070
- */
1071
- options . db . collection ( "metric_changes" + params . app_id ) . aggregate ( [
1072
- { $match : metricChangesMatch } ,
1073
- {
1074
- $group : {
1075
- _id : '$' + shortcodesForMetrics [ metric ] + ".o" ,
1076
- uniqDeviceIds : { $addToSet : '$uid' }
1077
- }
1078
- } ,
1079
- { $unwind : "$uniqDeviceIds" } ,
1080
- {
1081
- $group : {
1082
- _id : "$_id" ,
1083
- u : { $sum : 1 }
1084
- }
1057
+ options . db . collection ( "app_users" + params . app_id ) . aggregate ( [
1058
+ { $match : match } ,
1059
+ {
1060
+ $group : {
1061
+ _id : groupBy ,
1062
+ u : { $sum : 1 }
1085
1063
}
1086
- ] , { allowDiskUse : true } , function ( err , metricChangesDbResult ) {
1064
+ }
1065
+ ] , { allowDiskUse : true } , function ( error , appUsersDbResult ) {
1066
+
1067
+ if ( plugins . getConfig ( "api" , params . app && params . app . plugins , true ) . metric_changes && shortcodesForMetrics [ metric ] ) {
1068
+
1069
+ var metricChangesMatch = { ts : countlyCommon . getTimestampRangeQuery ( params , true ) } ;
1070
+
1071
+ metricChangesMatch [ shortcodesForMetrics [ metric ] + ".o" ] = { "$exists" : true } ;
1072
+
1073
+ /*
1074
+ We track changes to metrics such as app version in metric_changesAPPID collection;
1075
+ { "uid" : "2", "ts" : 1462028715, "av" : { "o" : "1:0:1", "n" : "1:1" } }
1076
+
1077
+ While returning a total user result for any metric, we check metric_changes to see
1078
+ if any metric change happened in the selected period and include this in the result
1079
+ */
1080
+ options . db . collection ( "metric_changes" + params . app_id ) . aggregate ( [
1081
+ { $match : metricChangesMatch } ,
1082
+ {
1083
+ $group : {
1084
+ _id : '$' + shortcodesForMetrics [ metric ] + ".o" ,
1085
+ uniqDeviceIds : { $addToSet : '$uid' }
1086
+ }
1087
+ } ,
1088
+ { $unwind : "$uniqDeviceIds" } ,
1089
+ {
1090
+ $group : {
1091
+ _id : "$_id" ,
1092
+ u : { $sum : 1 }
1093
+ }
1094
+ }
1095
+ ] , { allowDiskUse : true } , function ( err , metricChangesDbResult ) {
1087
1096
1088
- if ( metricChangesDbResult ) {
1089
- var appUsersDbResultIndex = _ . pluck ( appUsersDbResult , '_id' ) ;
1097
+ if ( metricChangesDbResult ) {
1098
+ var appUsersDbResultIndex = _ . pluck ( appUsersDbResult , '_id' ) ;
1090
1099
1091
- for ( let i = 0 ; i < metricChangesDbResult . length ; i ++ ) {
1092
- var itemIndex = appUsersDbResultIndex . indexOf ( metricChangesDbResult [ i ] . _id ) ;
1100
+ for ( let i = 0 ; i < metricChangesDbResult . length ; i ++ ) {
1101
+ var itemIndex = appUsersDbResultIndex . indexOf ( metricChangesDbResult [ i ] . _id ) ;
1093
1102
1094
- if ( itemIndex === - 1 ) {
1095
- appUsersDbResult . push ( metricChangesDbResult [ i ] ) ;
1096
- }
1097
- else {
1098
- appUsersDbResult [ itemIndex ] . u += metricChangesDbResult [ i ] . u ;
1103
+ if ( itemIndex === - 1 ) {
1104
+ appUsersDbResult . push ( metricChangesDbResult [ i ] ) ;
1105
+ }
1106
+ else {
1107
+ appUsersDbResult [ itemIndex ] . u += metricChangesDbResult [ i ] . u ;
1108
+ }
1099
1109
}
1100
1110
}
1101
- }
1102
-
1111
+ callback ( appUsersDbResult ) ;
1112
+ } ) ;
1113
+ }
1114
+ else {
1103
1115
callback ( appUsersDbResult ) ;
1104
- } ) ;
1105
- }
1106
- else {
1107
- callback ( appUsersDbResult ) ;
1108
- }
1109
- } ) ;
1110
- }
1111
- else {
1112
- callback ( [ ] ) ;
1113
- }
1116
+ }
1117
+ } ) ;
1118
+ }
1119
+ else {
1120
+ callback ( ob . result ) ;
1121
+ }
1122
+ } ) ;
1114
1123
} ;
1115
1124
1116
1125
/**
1117
1126
* Format total users object based on propeties it has (converting short metric values to long proper ones, etc)
1118
1127
* @param {object } obj - total users object
1119
1128
* @param {string } forMetric - for which metric to format result
1129
+ * @param {boolean } prev - get data for previous period, if available
1120
1130
* @returns {object } total users object with formated values
1121
1131
**/
1122
- fetch . formatTotalUsersObj = function ( obj , forMetric ) {
1132
+ fetch . formatTotalUsersObj = function ( obj , forMetric , prev ) {
1123
1133
var tmpObj = { } ,
1124
1134
processingFunction ;
1125
1135
@@ -1133,7 +1143,12 @@ fetch.formatTotalUsersObj = function(obj, forMetric) {
1133
1143
for ( let i = 0 ; i < obj . length ; i ++ ) {
1134
1144
var tmpKey = ( processingFunction ) ? processingFunction ( obj [ i ] . _id ) : obj [ i ] . _id ;
1135
1145
1136
- tmpObj [ tmpKey ] = obj [ i ] . u ;
1146
+ if ( prev ) {
1147
+ tmpObj [ tmpKey ] = obj [ i ] . pu || 0 ;
1148
+ }
1149
+ else {
1150
+ tmpObj [ tmpKey ] = obj [ i ] . u ;
1151
+ }
1137
1152
}
1138
1153
}
1139
1154
0 commit comments