Add filter functionality to test-details pythonlogging
On tests with pythonlogging, the DEBUG headers can be quite long and make finding useful information difficult. This patch adds a small, four-button filter to the test-details page that allows a user to select which levels of logging to be displayed (INFO, WARNING, ERROR, DEBUG). This patch will likely serve as the base for additional search functionality for test details (e.g. queries). Change-Id: Ia4286861268de0e43313d3b8d7f966e94697a495
This commit is contained in:
parent
728eb59ae8
commit
6b80ea8fa2
@ -8,14 +8,14 @@ var controllersModule = require('./_index');
|
|||||||
function TestDetailsCtrl($scope, $location, $stateParams, datasetService) {
|
function TestDetailsCtrl($scope, $location, $stateParams, datasetService) {
|
||||||
// ViewModel
|
// ViewModel
|
||||||
var vm = this;
|
var vm = this;
|
||||||
vm.datasetId = $stateParams.datasetId;
|
$scope.datasetId = $stateParams.datasetId;
|
||||||
var testName = $stateParams.test;
|
var testName = $stateParams.test;
|
||||||
vm.testName = testName;
|
$scope.testName = testName;
|
||||||
|
|
||||||
// load dataset, raw json, and details json
|
// load dataset, raw json, and details json
|
||||||
datasetService.get($stateParams.datasetId).then(function(response) {
|
datasetService.get($stateParams.datasetId).then(function(response) {
|
||||||
vm.dataset = response;
|
$scope.dataset = response;
|
||||||
vm.stats = response.stats;
|
$scope.stats = response.stats;
|
||||||
datasetService.raw(response).then(function(raw) {
|
datasetService.raw(response).then(function(raw) {
|
||||||
var item = null;
|
var item = null;
|
||||||
for (var t in raw.data) {
|
for (var t in raw.data) {
|
||||||
@ -23,13 +23,14 @@ function TestDetailsCtrl($scope, $location, $stateParams, datasetService) {
|
|||||||
item = raw.data[t];
|
item = raw.data[t];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vm.item = item;
|
$scope.item = item;
|
||||||
}).catch(function(ex) {
|
}).catch(function(ex) {
|
||||||
$log.error(ex);
|
$log.error(ex);
|
||||||
});
|
});
|
||||||
datasetService.details(response).then(function(deets) {
|
datasetService.details(response).then(function(deets) {
|
||||||
vm.details = deets;
|
$scope.details = deets;
|
||||||
vm.itemDetails = deets.data[testName];
|
$scope.originalDetails = angular.copy(deets.data[testName]);
|
||||||
|
$scope.itemDetails = deets.data[testName];
|
||||||
}).catch(function(ex) {
|
}).catch(function(ex) {
|
||||||
$log.error(ex);
|
$log.error(ex);
|
||||||
});
|
});
|
||||||
@ -37,5 +38,29 @@ function TestDetailsCtrl($scope, $location, $stateParams, datasetService) {
|
|||||||
$log.error(ex);
|
$log.error(ex);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$scope.parsePythonLogging = function(showINFO, showDEBUG, showWARNING, showERROR) {
|
||||||
|
if ($scope.originalDetails && $scope.originalDetails.pythonlogging) {
|
||||||
|
var log = $scope.originalDetails.pythonlogging;
|
||||||
|
var ret = [];
|
||||||
|
var lines = log.split('\n');
|
||||||
|
for (var i in lines) {
|
||||||
|
var line = lines[i];
|
||||||
|
if (showINFO && line.includes("INFO")) {
|
||||||
|
ret.push(line);
|
||||||
|
}
|
||||||
|
else if (showDEBUG && line.includes("DEBUG")) {
|
||||||
|
ret.push(line);
|
||||||
|
}
|
||||||
|
else if (showWARNING && line.includes("WARNING")) {
|
||||||
|
ret.push(line);
|
||||||
|
}
|
||||||
|
else if (showERROR && line.includes("ERROR")) {
|
||||||
|
ret.push(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$scope.itemDetails.pythonlogging = ret.join('\n');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
controllersModule.controller('TestDetailsCtrl', TestDetailsCtrl);
|
controllersModule.controller('TestDetailsCtrl', TestDetailsCtrl);
|
||||||
|
46
app/js/directives/test-details-search.js
Normal file
46
app/js/directives/test-details-search.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var directivesModule = require('./_index.js');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngInject
|
||||||
|
*/
|
||||||
|
function testDetailsSearch() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngInject
|
||||||
|
*/
|
||||||
|
var controller = function($scope, $element) {
|
||||||
|
var self = this;
|
||||||
|
this.open = false;
|
||||||
|
this.showINFO = true;
|
||||||
|
this.showDEBUG = true;
|
||||||
|
this.showWARNING = true;
|
||||||
|
this.showERROR = true;
|
||||||
|
|
||||||
|
var update = function() {
|
||||||
|
$scope.$parent
|
||||||
|
.parsePythonLogging(self.showINFO, self.showDEBUG, self.showWARNING, self.showERROR);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watch(function() { return self.query; }, update);
|
||||||
|
$scope.$watch(function() { return self.showINFO; }, update);
|
||||||
|
$scope.$watch(function() { return self.showDEBUG; }, update);
|
||||||
|
$scope.$watch(function() { return self.showWARNING; }, update);
|
||||||
|
$scope.$watch(function() { return self.showERROR; }, update);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'EA',
|
||||||
|
require: ['^testDetailsSearch', '^testDetails'],
|
||||||
|
scope: {
|
||||||
|
'parsePythonLogging': '&'
|
||||||
|
},
|
||||||
|
controller: controller,
|
||||||
|
controllerAs: 'search',
|
||||||
|
templateUrl: 'directives/test-details-search.html',
|
||||||
|
transclude: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
directivesModule.directive('testDetailsSearch', testDetailsSearch);
|
28
app/styles/directives/_test-details-search.scss
Normal file
28
app/styles/directives/_test-details-search.scss
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
test-details-search {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
.popover {
|
||||||
|
max-width: 600px;
|
||||||
|
|
||||||
|
.test-details-search-popover {
|
||||||
|
width: 400px;
|
||||||
|
.input-group {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-group label {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jump-group li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jump-group ul {
|
||||||
|
max-height: 20em;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@
|
|||||||
@import 'font-awesome/font-awesome';
|
@import 'font-awesome/font-awesome';
|
||||||
@import 'sb-admin-2';
|
@import 'sb-admin-2';
|
||||||
|
|
||||||
|
@import 'directives/_test-details-search.scss';
|
||||||
@import 'directives/_timeline-details.scss';
|
@import 'directives/_timeline-details.scss';
|
||||||
@import 'directives/_timeline-search.scss';
|
@import 'directives/_timeline-search.scss';
|
||||||
@import 'directives/_timeline-viewport.scss';
|
@import 'directives/_timeline-viewport.scss';
|
||||||
|
19
app/views/directives/test-details-search-popover.html
Normal file
19
app/views/directives/test-details-search-popover.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<div class="test-details-search-popover">
|
||||||
|
|
||||||
|
<label>Filter pythonlogging by log level:</label>
|
||||||
|
<div class="status-group btn-group btn-group-justified">
|
||||||
|
<label uib-btn-checkbox
|
||||||
|
ng-model="search.showINFO"
|
||||||
|
class="btn btn-default">INFO</label>
|
||||||
|
<label uib-btn-checkbox
|
||||||
|
ng-model="search.showDEBUG"
|
||||||
|
class="btn btn-default">DEBUG</label>
|
||||||
|
<label uib-btn-checkbox
|
||||||
|
ng-model="search.showWARNING"
|
||||||
|
class="btn btn-default">WARNING</label>
|
||||||
|
<label uib-btn-checkbox
|
||||||
|
ng-model="search.showERROR"
|
||||||
|
class="btn btn-default">ERROR</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
7
app/views/directives/test-details-search.html
Normal file
7
app/views/directives/test-details-search.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<a uib-popover-template="'directives/test-details-search-popover.html'"
|
||||||
|
popover-placement="bottom-right"
|
||||||
|
popover-title="Filter Options"
|
||||||
|
popover-is-open="search.open">
|
||||||
|
<fa name="search"></fa>
|
||||||
|
<fa name="caret-down"></fa>
|
||||||
|
</a>
|
@ -10,7 +10,8 @@
|
|||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h3 class="panel-title">
|
<h3 class="panel-title">
|
||||||
{{testDetails.testName | split:'.' | slice:-2 | join:'.'}}
|
{{testName | split:'.' | slice:-2 | join:'.'}}
|
||||||
|
<test-details-search class="pull-right"></test-details-search>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -20,26 +21,26 @@
|
|||||||
<table class="table table-bordered table-hover table-striped">
|
<table class="table table-bordered table-hover table-striped">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Name</td>
|
<td>Name</td>
|
||||||
<td>{{testDetails.item.name | split:'.' | pickRight:1}}</td>
|
<td>{{item.name | split:'.' | pickRight:1}}</td>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Full Name</td>
|
<td>Full Name</td>
|
||||||
<td>{{testDetails.item.name}}</td>
|
<td>{{item.name}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Status</td>
|
<td>Status</td>
|
||||||
<td>{{testDetails.item.status}}</td>
|
<td>{{item.status}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Tags</td>
|
<td>Tags</td>
|
||||||
<td>{{testDetails.item.tags | join:', '}}</td>
|
<td>{{item.tags | join:', '}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Duration</td>
|
<td>Duration</td>
|
||||||
<td>{{testDetails.item.duration | number:1}} seconds</td>
|
<td>{{item.duration | number:1}} seconds</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
<uib-tab ng-repeat="(entry,log) in testDetails.itemDetails" heading="{{entry}}">
|
<uib-tab ng-repeat="(entry,log) in itemDetails" heading="{{entry}}">
|
||||||
<pre style="height: 400px; overflow-y: scroll;">{{log}}</pre>
|
<pre style="height: 400px; overflow-y: scroll;">{{log}}</pre>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
</uib-tabset>
|
</uib-tabset>
|
||||||
@ -47,7 +48,7 @@
|
|||||||
|
|
||||||
<div class="panel-footer clearfix">
|
<div class="panel-footer clearfix">
|
||||||
<a class="btn btn-default pull-right"
|
<a class="btn btn-default pull-right"
|
||||||
ui-sref="timeline({datasetId: testDetails.dataset.id, test: testDetails.item.name})">
|
ui-sref="timeline({datasetId: dataset.id, test: item.name})">
|
||||||
Timeline
|
Timeline
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user