Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Fixes:
- [core] Fix user analytics widget chart
- [core] Fix mongo connection url parsing
- [crashes] Fix free session and free user calculation

## Version 25.03.10
Enterprise Fixes:
Expand Down
101 changes: 90 additions & 11 deletions plugins/crashes/frontend/public/javascripts/countly.models.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ function transformAppVersion(inpVersion) {
var realSession = state.realSession;
var realTotalSession = (realSession.usage && realSession.usage['total-sessions'].total) || 0;
var dashboard = {};
var wholeUsers = {};

if ("data" in state.rawData) {
dashboard = countlyCommon.getDashboardData(state.filteredData.data, ["cr", "crnf", "crf", "cru", "cruf", "crunf", "crru", "crau", "crauf", "craunf", "crses", "crfses", "crnfses", "cr_s", "cr_u"], ["cru", "crau", "cruf", "crunf", "crauf", "craunf", "cr_u"], null, countlyCrashes.clearObject);
Expand All @@ -139,6 +140,12 @@ function transformAppVersion(inpVersion) {
return dashboard;
}

if ('users' in state.rawData) {
wholeUsers.total = state.rawData.users.total;
wholeUsers.fatal = state.rawData.users.fatal;
wholeUsers.nonfatal = state.rawData.users.nonfatal;
}

/**
* Populates the metric's change and trend properties according to its total and prev-total.
* @param {string} metric - A metric name e.g. "cr"
Expand Down Expand Up @@ -173,7 +180,7 @@ function transformAppVersion(inpVersion) {
});
}

if (isPercent && ["crses", "crnfses", "crfses", "crau", "craunf", "crauf"].includes(metric)) {
if (isPercent && ["crses", "crnfses", "crfses", "crau", "craunf", "crauf", 'crinv', 'crfinv', 'crnfinv', 'crauinv', 'craufinv', 'craunfinv'].includes(metric)) {
["total", "prev-total"].forEach(function(prop) {
dashboard[metric][prop] = dashboard[metric][prop].toFixed(2) + '%';
});
Expand All @@ -195,7 +202,7 @@ function transformAppVersion(inpVersion) {
});
});

["cr-session", "crtf", "crtnf", "crau", "crses"].forEach(function(metric) {
["cr-session", "crtf", "crtnf", "crau", "crses", 'crinv', 'crfinv', 'crnfinv', 'crauinv', 'craufinv', 'craunfinv'].forEach(function(metric) {
dashboard[metric] = {};
});

Expand All @@ -211,9 +218,16 @@ function transformAppVersion(inpVersion) {
dashboard.cr_s[prop] += dashboard.crfses[prop] + dashboard.crnfses[prop];
}

if (dashboard.cr_u[prop] < (dashboard.crauf[prop] + dashboard.craunf[prop])) {
dashboard.cr_u[prop] += dashboard.crauf[prop] + dashboard.craunf[prop];
// derive user count from whole users
if (dashboard.crau[prop] > dashboard.cr_u[prop] && 'users' in state.rawData) {
dashboard.crauf[prop] = dashboard.cr_u[prop] * ((wholeUsers.fatal / wholeUsers.total) - (dashboard.crf[prop] / dashboard.cr_s[prop]));
dashboard.craunf[prop] = dashboard.cr_u[prop] * ((wholeUsers.nonfatal / wholeUsers.total) - (dashboard.crnf[prop] / dashboard.cr_s[prop]));
dashboard.crau[prop] = dashboard.crauf[prop] + dashboard.craunf[prop];
}

dashboard.crinv[prop] = Math.max(0, dashboard.cr_s[prop] - dashboard.cr[prop]);
dashboard.crfinv[prop] = Math.max(0, dashboard.cr_s[prop] - dashboard.crf[prop]);
dashboard.crnfinv[prop] = Math.max(0, dashboard.cr_s[prop] - dashboard.crnf[prop]);
});

["cr-session", "crtf", "crtnf"].forEach(function(metric) {
Expand All @@ -222,7 +236,7 @@ function transformAppVersion(inpVersion) {

["crau", "craunf", "crauf"].forEach(function(name) {
["total", "prev-total"].forEach(function(prop) {
dashboard[name][prop] = Math.min(100, (dashboard.cr_u[prop] === 0 || dashboard[name][prop] === 0) ? 100 : ((dashboard.cr_u[prop] - dashboard[name][prop]) / dashboard.cr_u[prop] * 100));
dashboard[name][prop] = Math.min(100, (dashboard.cr_u[prop] === 0 || dashboard[name][prop] === 0) ? 100 : (Math.abs(dashboard.cr_u[prop] - dashboard[name][prop]) / dashboard.cr_u[prop] * 100));
});
populateMetric(name, true);
});
Expand All @@ -249,6 +263,22 @@ function transformAppVersion(inpVersion) {
populateMetric(name, true);
});

['crinv', 'crfinv', 'crnfinv'].forEach(function(name) {
["total", "prev-total"].forEach(function(prop) {
var propValue = 0;

if (dashboard.cr_s[prop] === 0) {
propValue = 100;
}
else {
propValue = dashboard[name][prop] / dashboard.cr_s[prop] * 100;
}

dashboard[name][prop] = Math.min(100, propValue);
});
populateMetric(name, true);
});

return dashboard;
};

Expand All @@ -270,14 +300,22 @@ function transformAppVersion(inpVersion) {
return {};
}

var wholeUsers = {};
if ('users' in state.rawData) {
wholeUsers.total = state.rawData.users.total;
wholeUsers.fatal = state.rawData.users.fatal;
wholeUsers.nonfatal = state.rawData.users.nonfatal;
}

var chartData, dataProps;

var metricChartConfig = {
"cr-session": {labelKey: "crashes.total-per-session", colorIndex: 1},
"crses": {labelKey: "crashes.free-sessions", colorIndex: 1},
"crau": {labelKey: "crashes.free-users", colorIndex: 1},
"cr": {labelKey: "crashes.total", colorIndex: 1},
"cru": {labelKey: "crashes.unique", colorIndex: 1}
"cru": {labelKey: "crashes.unique", colorIndex: 1},
"crinv": {labelKey: "crashes.free-sessions", colorIndex: 1},
}[metric];

if (typeof metricChartConfig !== "undefined") {
Expand All @@ -298,7 +336,8 @@ function transformAppVersion(inpVersion) {
"crses": {"fatal": "crfses", "nonfatal": "crnfses"},
"crau": {"fatal": "crauf", "nonfatal": "craunf"},
"cr": {"fatal": "crf", "nonfatal": "crnf"},
"cru": {"fatal": "cruf", "nonfatal": "crunf"}
"cru": {"fatal": "cruf", "nonfatal": "crunf"},
"crinv": {"fatal": "crfinv", "nonfatal": "crnfinv"},
};

name = name || ((metric in metricNames && state.activeFilter.fatality !== "both") ? metricNames[metric][state.activeFilter.fatality] : metric);
Expand All @@ -311,7 +350,15 @@ function transformAppVersion(inpVersion) {
return (obj.cr_s === 0 || obj.crfses + obj.crnfses === 0) ? 100 : Math.round(Math.min(Math.max((obj.crfses + obj.crnfses - obj.cr_s) / obj.cr_s, 0), 1) * 10000) / 100;
},
"^crau$": function(obj) {
return (obj.cr_u === 0 || obj.crauf + obj.craunf === 0) ? 100 : Math.round(Math.min(Math.max((obj.crauf + obj.craunf - obj.cr_u) / obj.cr_u, 0), 1) * 10000) / 100;
if (obj.cr_u === 0 || obj.crauf + obj.craunf === 0) {
return 100;
}
else if (obj.crauf + obj.craunf > obj.cr_u && obj.cr_s !== 0 && 'users' in state.rawData) {
var value = (obj.cr_u - (obj.cr_u * ((wholeUsers.fatal / wholeUsers.total) - (obj.crf / obj.cr_s))) - (obj.cr_u * ((wholeUsers.nonfatal / wholeUsers.total) - (obj.crnf / obj.cr_s)))) / obj.cr_u * 100;
return Math.round(value * 100) / 100;
}

return Math.round(Math.min(Math.max((obj.crauf + obj.craunf - obj.cr_u) / obj.cr_u, 0), 1) * 10000) / 100;
},
"^cr$": function(obj) {
return obj.crf + obj.crnf;
Expand All @@ -325,9 +372,40 @@ function transformAppVersion(inpVersion) {
"^crn?fses$": function(obj) {
return (obj.cr_s === 0 || obj[name] === 0) ? 100 : Math.round(Math.min(obj[name] / obj.cr_s, 1) * 10000) / 100;
},
"^craun?f$": function(obj) {
return (obj.cr_s === 0 || obj[name] === 0) ? 100 : Math.round(Math.min(obj[name] / obj.cr_u, 1) * 10000) / 100;
}
"^crauf$": function(obj) {
if (obj.cr_u === 0 || obj[name] === 0) {
return 100;
}
else if (obj.crauf + obj.craunf > obj.cr_u && obj.cr_s !== 0 && 'users' in state.rawData) {
var value = (obj.cr_u - (obj.cr_u * ((wholeUsers.fatal / wholeUsers.total) - (obj.crf / obj.cr_s)))) / obj.cr_u * 100;
return Math.round(value * 100) / 100;
}

return Math.round(Math.min(obj[name] / obj.cr_u, 1) * 10000) / 100;
},
"^craunf$": function(obj) {
if (obj.cr_u === 0 || obj[name] === 0) {
return 100;
}
else if (obj.crauf + obj.craunf > obj.cr_u && obj.cr_s !== 0 && 'users' in state.rawData) {
var value = (obj.cr_u - (obj.cr_u * ((wholeUsers.nonfatal / wholeUsers.total) - (obj.crnf / obj.cr_s)))) / obj.cr_u * 100;
return Math.round(value * 100) / 100;
}

return Math.round(Math.min(obj[name] / obj.cr_u, 1) * 10000) / 100;
},
'^crinv$': function(obj) {
var value = (obj.cr_s === 0) ? 100 : (obj.cr_s - (obj.crf + obj.crnf)) / obj.cr_s * 100;
return Math.round(value * 100) / 100;
},
'^crfinv$': function(obj) {
var value = (obj.cr_s === 0) ? 100 : (obj.cr_s - obj.crf) / obj.cr_s * 100;
return Math.round(value * 100) / 100;
},
'^crnfinv$': function(obj) {
var value = (obj.cr_s === 0) ? 100 : (obj.cr_s - obj.crnf) / obj.cr_s * 100;
return Math.round(value * 100) / 100;
},
};

dataProps = [
Expand Down Expand Up @@ -370,6 +448,7 @@ function transformAppVersion(inpVersion) {
state.isLoading = false;
return chartOptions;
};

};

_overviewSubmodule.getters.statistics = function(state) {
Expand Down
6 changes: 3 additions & 3 deletions plugins/crashes/frontend/public/templates/overview.html
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,14 @@
</el-tab-pane>
<el-tab-pane name="crashfree-sessions" style="border-top-right-radius: 4px;" data-test-id="crashfree-sessions-graph">
<div class="bu-p-5" slot="label">
<crash-tab-label :title="i18n('crashes.free-sessions')" :tooltip="i18n('crashes.help-free-sessions')" :data="dashboardData[{'both': 'crses', 'fatal': 'crfses', 'nonfatal': 'crnfses'}[activeFilter.fatality]]">
<crash-tab-label :title="i18n('crashes.free-sessions')" :tooltip="i18n('crashes.help-free-sessions')" :data="dashboardData[{'both': 'crinv', 'fatal': 'crfinv', 'nonfatal': 'crnfinv'}[activeFilter.fatality]]">
</crash-tab-label>
</div>
<cly-chart-line xAxisLabelOverflow="unset" :option="chartData('crses')" category="crashes"></cly-chart-line>
<cly-chart-line xAxisLabelOverflow="unset" :option="chartData('crinv')" category="crashes"></cly-chart-line>
</el-tab-pane>
</el-tabs>
</div>
</cly-main>
</el-tab-pane>
</cly-tabs>
</div>
</div>
Loading