diff --git a/_attachments/partials/bug-details.html b/_attachments/partials/bug-details.html index c42a5d3..a94db5c 100644 --- a/_attachments/partials/bug-details.html +++ b/_attachments/partials/bug-details.html @@ -5,15 +5,15 @@

Bug Summary

- + - + - + diff --git a/_attachments/partials/bugs-table.html b/_attachments/partials/bugs-table.html index b97b69b..0341040 100644 --- a/_attachments/partials/bugs-table.html +++ b/_attachments/partials/bugs-table.html @@ -16,10 +16,10 @@
- + - - + +
@@ -40,10 +40,10 @@
{{bug.value.count}}
{{bug.latest}}
-
{{bug.key[0]}}
+
{{bug.value.appVersion}}
- {{bug.key[1]}}
- Caused by: {{bug.key[2]}} + {{bug.value.exception}}
+ Caused by: {{bug.value.rootCause}}
diff --git a/_attachments/partials/reports-table.html b/_attachments/partials/reports-table.html index 81c7f51..e3b4cf7 100644 --- a/_attachments/partials/reports-table.html +++ b/_attachments/partials/reports-table.html @@ -18,14 +18,14 @@ - + {{report.displayDate}} - {{report.value.application_version_name}} - {{report.value.android_version}} - {{report.value.device}} + {{report.doc.APP_VERSION_NAME}} + {{report.doc.ANDROID_VERSION}} + {{getDevice(report.doc)}}
- {{report.value.signature.digest}} - Caused by: {{report.value.signature.rootCause}} + {{report.doc.SIGNATURE.full}} + Caused by: {{report.doc.SIGNATURE.rootCause}}
\ No newline at end of file diff --git a/_attachments/script/DashboardControllers.js b/_attachments/script/DashboardControllers.js index 497f57e..4e8a850 100644 --- a/_attachments/script/DashboardControllers.js +++ b/_attachments/script/DashboardControllers.js @@ -58,6 +58,29 @@ }); }; + $scope.getDevice = function(doc) { + if(doc.BUILD) { + if(doc.BUILD.MANUFACTURER) { + return doc.BUILD.MANUFACTURER + " " + doc.BUILD.BRAND + " " + doc.BUILD.MODEL; + } else { + return doc.BUILD.BRAND + " " + doc.BUILD.MODEL; + } + } else { + var value = ""; + if(doc.BRAND) { + value = doc.BRAND; + } + if(doc.PRODUCT) { + value += " " + doc.PRODUCT; + } + if(doc.PHONE_MODEL) { + value += " " + doc.MODEL; + } + + return value; + } + }; + $scope.loadReport = function(report) { $scope.selectedReport = ReportsStore.reportDetails(report.id, function(data) { data.readableUptime = moment.duration(data.uptime, 'seconds').humanize(); @@ -121,7 +144,8 @@ }; $scope.getData = function() { - ReportsStore.bugsList(function(data) { + ReportsStore.recentBugsList( + function(data) { console.log("Refresh data for latest bugs"); mergeBugsLists($scope.bugs, data.rows); $scope.totalBugs = data.total_rows; @@ -373,11 +397,11 @@ /* Pie charts */ function PieChartsCtrl($scope, ReportsStore, $user) { $scope.fieldNames = [ - {name: "android-version", label: "Android version"}, - {name: "android-sdk-version", label: "Android SDK version"}, - {name: "app-version-name", label: "Application version name"}, - {name: "app-version-code", label: "Application version code"}, - {name: "device", label: "Device"} + {name: "recent-items-by-androidver", label: "Android version"}, + {name: "reports-per-android-sdk-version", label: "Android SDK version"}, + {name: "recent-items-by-appver", label: "Application version name"}, + {name: "recent-items-by-appvercode", label: "Application version code"}, + {name: "reports-per-device", label: "Device"} ]; $scope.fieldName = $scope.fieldNames[0]; diff --git a/_attachments/script/ReportsBrowserControllers.js b/_attachments/script/ReportsBrowserControllers.js index 3cb2c23..b818eb9 100644 --- a/_attachments/script/ReportsBrowserControllers.js +++ b/_attachments/script/ReportsBrowserControllers.js @@ -96,6 +96,29 @@ } }); + $scope.getDevice = function(doc) { + if(doc.BUILD) { + if(doc.BUILD.MANUFACTURER) { + return doc.BUILD.MANUFACTURER + " " + doc.BUILD.BRAND + " " + doc.BUILD.MODEL; + } else { + return doc.BUILD.BRAND + " " + doc.BUILD.MODEL; + } + } else { + var value = ""; + if(doc.BRAND) { + value = doc.BRAND; + } + if(doc.PRODUCT) { + value += " " + doc.PRODUCT; + } + if(doc.PHONE_MODEL) { + value += " " + doc.MODEL; + } + + return value; + } + }; + $scope.getData = function() { $scope.loading = true; var successHandler = function(data) { @@ -118,22 +141,22 @@ }; if(($scope.filterName === $scope.noFilter || $scope.filterValue === $scope.noFilterValue) && !$scope.bug && !$scope.selectedUser) { - ReportsStore.reportsList($scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler); + ReportsStore.reportsList($scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler); } else if($scope.filterName !== $scope.noFilter && $scope.filterValue !== $scope.noFilterValue){ - ReportsStore.filteredReportsList($scope.filterName.value, $scope.filterValue.value,$scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler); + ReportsStore.filteredReportsList($scope.filterName.value, $scope.filterValue.value,$scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler); } else if($scope.bug) { if($scope.selectedUser) { // Filter by bug AND user - var filterKey = $scope.bug.key.slice(0); + var filterKey = [$scope.bug.key]; filterKey.push($scope.selectedUser.installationId); - ReportsStore.filteredReportsList("bug-by-installation-id", filterKey, $scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler); + ReportsStore.filteredReportsList("bug-by-installation-id", filterKey, $scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler); } else { // Filter by bug only - ReportsStore.filteredReportsList("bug", $scope.bug.key, $scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler); + ReportsStore.filteredReportsList("bug-by-installation-id", $scope.bug.key, $scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler, 1); } } else if($scope.selectedUser) { // Filter by user only - ReportsStore.filteredReportsList("installation-id", $scope.selectedUser.installationId, $scope.startKey, $scope.paginator.pageSize, $scope.fullSearch, successHandler, errorHandler); + ReportsStore.filteredReportsList("installation-id", $scope.selectedUser.installationId, $scope.startKey, $scope.paginator.pageSize, true, successHandler, errorHandler); } }; diff --git a/_attachments/script/config.js b/_attachments/script/config.js index c6692d0..f8abb77 100644 --- a/_attachments/script/config.js +++ b/_attachments/script/config.js @@ -1,7 +1,7 @@ (function(acralyzerConfig, undefined ) { "use strict"; // Update this variable with the name of your app: - acralyzerConfig.defaultApp = ""; + acralyzerConfig.defaultApp = "test"; acralyzerConfig.backgroundPollingOnStartup = true; acralyzerConfig.appDBPrefix = "acra-"; diff --git a/_attachments/script/service.reportsstore.js b/_attachments/script/service.reportsstore.js index fa172d5..5a95fcf 100644 --- a/_attachments/script/service.reportsstore.js +++ b/_attachments/script/service.reportsstore.js @@ -26,7 +26,7 @@ * @singleton * @static */ - acralyzer.factory('ReportsStore', ['$rootScope', '$http', '$resource', function($rootScope, $http, $resource) { + acralyzer.factory('ReportsStore', ['$rootScope', '$http', '$resource', '$location', function($rootScope, $http, $resource, $location) { // ReportsStore service instance var ReportsStore = { lastseq : -1, @@ -45,9 +45,17 @@ * @param {function} cb Callback to be executed after database changed. */ ReportsStore.setApp = function (newAppName, cb) { + var addLogcatLink = function(data, headersGetter) { + var report = JSON.parse(data); + if (report._attachments['logcat.txt'].stub) { + var link = $location.protocol() + '://' + $location.host() + ':' + $location.port() + '/' + ReportsStore.dbName + '/' + report._id + '/logcat.txt'; + report._attachments['logcat.txt'].link = link; + } + return report; + }; ReportsStore.dbName = acralyzerConfig.appDBPrefix + newAppName; ReportsStore.views = $resource('/' + ReportsStore.dbName + '/_design/acra-storage/_view/:view'); - ReportsStore.details = $resource('/' + ReportsStore.dbName + '/:reportid'); + ReportsStore.details = $resource('/' + ReportsStore.dbName + '/:reportid', null, {'get': {method:'GET', transformResponse: addLogcatLink}}); ReportsStore.bug = $resource('/' + ReportsStore.dbName + '/:bugid', { bugid: '@_id' }, { save: {method: 'PUT'}}); ReportsStore.dbstate = $resource('/' + ReportsStore.dbName + '/'); ReportsStore.changes = $resource('/' + ReportsStore.dbName + '/_changes'); @@ -82,13 +90,13 @@ * @return Key: date/time, Value: quantity */ ReportsStore.reportsPerDay = function(grouplvl, cb, errorHandler) { - return ReportsStore.views.get({view: 'reports-per-day', group_level: grouplvl}, cb, errorHandler); + return ReportsStore.views.get({view: 'reports-per-day', group_level: grouplvl, stale: 'update_after'}, cb, errorHandler); }; // 10 latest reports - Key: date/time Value: report digest ReportsStore.recentReports = function(cb, errorHandler) { - return ReportsStore.views.get({view: 'recent-items', limit: 10, descending: true}, cb, errorHandler); + return ReportsStore.views.get({view: 'recent-items', limit: 10, descending: true, stale: 'update_after', include_docs: true}, cb, errorHandler); }; // Key: report ID Value: report digest @@ -97,6 +105,7 @@ view: 'recent-items', descending: true, limit: reportsCount + 1, + stale: 'update_after', include_docs: includeDocs }; if(startKey !== null) { @@ -121,20 +130,13 @@ view: 'recent-items-by-' + filterName, descending: true, limit: reportsCount + 1, + stale: 'update_after', include_docs: includeDocs, reduce: false }; - if(filterName.indexOf("bug") === 0) { - // Bugs have composite keys, already an array. - viewParams.endkey = JSON.stringify(filterValue); - var startKeyValue = filterValue.slice(0); - startKeyValue.push({}); - viewParams.startkey = JSON.stringify(startKeyValue); - } else { - viewParams.endkey = JSON.stringify([filterValue]); - viewParams.startkey = JSON.stringify([filterValue,{}]); - } + viewParams.endkey = JSON.stringify([].concat(filterValue)); + viewParams.startkey = JSON.stringify([].concat(filterValue,{})); if(pageStartKey !== null) { viewParams.startkey = JSON.stringify(pageStartKey); @@ -146,10 +148,8 @@ } for(var row = 0; row < data.rows.length; row++) { - if(filterName === "bug") { - data.rows[row].displayDate = moment(data.rows[row].key[3]).fromNow(); - } else if(filterName === "bug-by-installation-id") { - data.rows[row].displayDate = moment(data.rows[row].key[4]).fromNow(); + if(filterName === "bug-by-installation-id") { + data.rows[row].displayDate = moment(data.rows[row].key[2]).fromNow(); } else { data.rows[row].displayDate = moment(data.rows[row].key[1]).fromNow(); } @@ -167,112 +167,111 @@ }; ReportsStore.reportsPerFieldName = function(fieldName, cb, errorHandler) { - return ReportsStore.views.get({view: 'reports-per-' + fieldName, group_level: 1}, cb, errorHandler); + return ReportsStore.views.get({view: fieldName, group_level: 1, stale: 'update_after'}, cb, errorHandler); }; ReportsStore.appVersionsList = function(cb) { - return ReportsStore.views.get({view: 'recent-items-by-appver', group_level: 1}, cb); + return ReportsStore.views.get({view: 'recent-items-by-appver', reduce: true, group_level: 1, include_docs: false, stale: 'update_after'}, cb); }; ReportsStore.appVersionCodesList = function(cb) { - return ReportsStore.views.get({view: 'recent-items-by-appvercode', group_level: 1}, cb); + return ReportsStore.views.get({view: 'recent-items-by-appvercode', reduce: true, group_level: 1, include_docs: false, stale: 'update_after'}, cb); }; ReportsStore.androidVersionsList = function(cb) { - return ReportsStore.views.get({view: 'recent-items-by-androidver', group_level: 1}, cb); + return ReportsStore.views.get({view: 'recent-items-by-androidver', reduce: true, group_level: 1, include_docs: false, stale: 'update_after'}, cb); }; - // BUGS MANAGEMENT - var computeBugId = function(bug) { - if (bug.id) { - return bug.id; - } else { - return hex_md5(bug.key[0] + "|" + bug.key[1] + "|" + bug.key[2]); - } - }; - - ReportsStore.bugsList = function(cb, errorHandler) { - var viewParams = { - view: 'bugs', - descending: true, - group: true - }; + ReportsStore.bugListWithLimit = function(limit, bugId) { + + return function(cb, errorHandler){ + var viewParams = { + view: 'bugs', + descending: true, + group: true, + stale: 'update_after' + }; + + if (limit > 0) { viewParams.limit = limit; } + if (bugId) { viewParams.key = bugId; } + + var bugEqualityTest = function(bug2) { + if( + this.value.key !== bug2.value.key || + this.value.latest !== bug2.value.latest || + this.value.count !== bug2.value.count || + this.value.solved !== bug2.value.solved || + this.value.description !== bug2.value.description) { + return false; + } + return true; + }; - var bugEqualityTest = function(bug2) { - if(this.value.latest !== bug2.value.latest || - this.value.count !== bug2.value.count || - this.value.solved !== bug2.value.solved || - this.value.description !== bug2.value.description) { - return false; - } - return true; - }; + var bugUpdate = function(bug2) { + if(this.value.latest !== bug2.value.latest) { + this.value.latest = bug2.value.latest; + } + if(this.value.count !== bug2.value.count) { + this.value.count = bug2.value.count; + } + if(this.value.solved !== bug2.value.solved) { + this.value.solved = bug2.value.solved; + } + if(this.value.description !== bug2.value.description) { + this.value.description = bug2.value.description; + } + }; - var bugUpdate = function(bug2) { - if(this.value.latest !== bug2.value.latest) { - this.value.latest = bug2.value.latest; - } - if(this.value.count !== bug2.value.count) { - this.value.count = bug2.value.count; - } - if(this.value.solved !== bug2.value.solved) { - this.value.solved = bug2.value.solved; - } - if(this.value.description !== bug2.value.description) { - this.value.description = bug2.value.description; - } - }; + var toggleSolved = function() { + var bug = this; + this.solvedPending = true; + ReportsStore.toggleSolvedBug(bug, function(data){ + bug.solvedPending = false; + }); + }; + + var additionalCallback = function(data) { + // The bug view does not return individual documents. Unless data has been specifically updated about + // one bug, there is no bug document in a database. We add here the computed id of each 'virtual' bug. + for (var i = 0; i < data.rows.length; i++) { + data.rows[i].id = ""+data.rows[i].key; + data.rows[i].equals = bugEqualityTest; + data.rows[i].updateWithBug = bugUpdate; + data.rows[i].toggleSolved = toggleSolved; + data.rows[i].descriptionHtml = converter.makeHtml(data.rows[i].value.description); + } + cb(data); + }; - var toggleSolved = function() { - var bug = this; - this.solvedPending = true; - ReportsStore.toggleSolvedBug(bug, function(data){ - bug.solvedPending = false; - }); + return ReportsStore.views.get(viewParams, additionalCallback, errorHandler); }; + }; - var additionalCallback = function(data) { - // The bug view does not return individual documents. Unless data has been specifically updated about - // one bug, there is no bug document in a database. We add here the computed id of each 'virtual' bug. - for (var i = 0; i < data.rows.length; i++) { - data.rows[i].id = computeBugId(data.rows[i]); - data.rows[i].equals = bugEqualityTest; - data.rows[i].updateWithBug = bugUpdate; - data.rows[i].toggleSolved = toggleSolved; - data.rows[i].descriptionHtml = converter.makeHtml(data.rows[i].value.description); - } - cb(data); - }; + ReportsStore.recentBugsList = ReportsStore.bugListWithLimit(0); - return ReportsStore.views.get(viewParams, additionalCallback, errorHandler); - }; + ReportsStore.bugsList = ReportsStore.bugListWithLimit(0); ReportsStore.toggleSolvedBug = function(bug, callback) { + var updateBrowserBug = function(data) { + bug.value.solved = curBug.solved; + callback(data); + }; var curBug = ReportsStore.bug.get({ bugid: bug.id}, function() { // Success callback curBug.solved = ! curBug.solved; - var state = curBug.solved; - curBug.$save(function(data) { - bug.value.solved = state; - console.log("bug is now:"); - console.log(bug); - callback(data); - }); + ReportsStore.bug.save(curBug, updateBrowserBug); }, function() { // Fail callback curBug = new ReportsStore.bug( { _id: bug.id, - APP_VERSION_CODE: bug.key[0], - digest: bug.key[1], - rootCause: bug.key[2], + SIGNATURE: { + hash: bug.key + }, solved: true, type: "solved_signature" }); - curBug.$save(function(data) { - bug.value.solved = curBug.solved; - callback(data); - }); + ReportsStore.bug.save(curBug, updateBrowserBug); }); }; @@ -285,9 +284,9 @@ curBug = new ReportsStore.bug( { _id: bug.id, - APP_VERSION_CODE: bug.key[0], - digest: bug.key[1], - rootCause: bug.key[2], + signature: { + hash: bug.value.hash + }, solved: bug.value.solved, type: "solved_signature", description: bug.value.description @@ -308,17 +307,11 @@ * @param cb */ ReportsStore.getBugForId = function(bugId, cb) { - var bug = {}; - ReportsStore.bugsList(function(data) { - console.log("looking for bug with id " + bugId); - for (var i = 0; i < data.rows.length; i++) { - if (data.rows[i].id === bugId) { - bug = data.rows[i]; - console.log("Bug found:"); - console.log(bug); - break; - } - } + var bug = null; + console.log("looking for bug with id " + bugId); + ReportsStore.bugListWithLimit(1, bugId)(function(data) { + bug = data.rows[0]; + if (bug === null) { console.log("Error, unable to find bug with id " + bugId); } cb(bug); }); return bug; @@ -483,16 +476,17 @@ var viewParams = { view: 'users-per-bug', reduce: true, - group_level: 4 + group_level: 2, + stale: 'update_after' }; - viewParams.startkey = JSON.stringify([bug.key[0], bug.key[1], bug.key[2]]); - viewParams.endkey = JSON.stringify([bug.key[0], bug.key[1], bug.key[2], {}]); + viewParams.startkey = JSON.stringify([bug.key]); + viewParams.endkey = JSON.stringify([bug.key, {}]); var result = []; ReportsStore.views.get(viewParams,function(data) { for(var row = 0; row < data.rows.length; row++) { var user = { - installationId: data.rows[row].key[3], + installationId: data.rows[row].key[1], reportsCount: data.rows[row].value }; result.push(user);
Application version code:{{bug.key[0]}}{{bug.value.appVersion}}
Exception:{{bug.key[1]}}{{bug.value.exception}}
Root Exception:{{bug.key[2]}}{{bug.value.rootCause}}
Solved: