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
50 changes: 28 additions & 22 deletions app/Http/Controllers/MonitorController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,12 @@ public function get(): JsonResponse
// Initialize trendline data.
$success_values = [];
$fail_values = [];
$ticks = [];
$num_hours = 0;
for ($timestamp = $begin; $timestamp <= $end; $timestamp += 3600) {
// Truncate this timestamp to the beginning of the hour.
$success_values[$timestamp] = 0;
$fail_values[$timestamp] = 0;
$num_hours++;
if ($num_hours % 6 === 0) {
$ticks[] = $timestamp;
}
}

foreach ($fail_data as $row) {
Expand All @@ -92,33 +88,43 @@ public function get(): JsonResponse
}
}

// Massage data into the format expected by nvd3.
$success_trend = [];
$success_trend['key'] = 'success';
$success_trend['color'] = $palette::Success;
$success_trend['values'] = [];
// Massage data into the expected format
$success_trend = [
'color' => $palette::Success,
'name' => 'Success',
'values' => [],
];
foreach ($success_values as $key => $value) {
$data_point = [$key, $value];
$success_trend['values'][] = $data_point;
$success_trend['values'][] = [
$key,
$value,
];
}

$fail_trend = [];
$fail_trend['key'] = 'fail';
$fail_trend['color'] = $palette::Failure;
$fail_trend['values'] = [];
$fail_trend = [
'color' => $palette::Failure,
'name' => 'Fail',
'values' => [],
];
foreach ($fail_values as $key => $value) {
$data_point = [$key, $value];
$fail_trend['values'][] = $data_point;
$fail_trend['values'][] = [
$key,
$value,
];
}

$time_chart_data = [$success_trend, $fail_trend];

return response()->json([
'backlog_length' => $backlog_length,
'backlog_time' => $backlog_time,
'num_hours' => $num_hours,
'time_chart_data' => $time_chart_data,
'ticks' => $ticks,
'time_chart_data' => [
"data" => [
$success_trend,
$fail_trend,
],
"title" => "Submissions Parsed Over the Past {$num_hours} Hours",
"xLabel" => "Date",
"yLabel" => "# of Submissions",
],
'log_directory' => config('logging.default') === 'stack' ? storage_path('logs') : '',
]);
}
Expand Down
88 changes: 27 additions & 61 deletions resources/js/components/Monitor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,17 @@
<h4 v-if="cdash.backlog_length > 0">
The oldest submission was created {{ cdash.backlog_time }}.
</h4>
<h3 class="center-text">
Submissions parsed over the past {{ cdash.num_hours }} hours
</h3>
<div
id="timechart"
class="row"
>
<div class="col-md-12">
<svg
width="100%"
style="height:375px"
/>
</div>
</div>
<TimelinePlot v-if="plot_data && cdash.time_chart_data"
class="center-text"
:plot-data="plot_data"
:title="cdash.time_chart_data.title"
:x-label="cdash.time_chart_data.xLabel"
:y-label="cdash.time_chart_data.yLabel"
/>
<br>
<p>
Note: Detailed information about submission failures can be found in the CDash logs.<br>
<span v-if="cdash.log_directory.length > 0">
<span v-if="'log_directory' in cdash">
Log files can be found in: <tt>{{ cdash.log_directory }}</tt>
</span>
<span v-else>
Expand All @@ -38,15 +31,21 @@
</template>
<script>
import ApiLoader from './shared/ApiLoader';
import TimelinePlot from './shared/TimelinePlot';
export default {
name: "SubmissionProcessingMonitor",

components: {
TimelinePlot,
},

data () {
return {
// API results.
cdash: {},
loading: true,
errored: false,
plot_data: {},
}
},

Expand All @@ -55,54 +54,21 @@ export default {
},

methods: {
postSetup: function (response) {
var vm = this;
nv.addGraph(function() {
vm.timechart = nv.models.lineChart()
.margin({top: 30, right: 60, bottom: 30, left: 60})
.useInteractiveGuideline(true)
.showLegend(true)
.showYAxis(true)
.showXAxis(true)
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.showLegend(true);

vm.timechart.xAxis.showMaxMin(false);
vm.timechart_selection = d3.select('#timechart svg').datum(vm.cdash.time_chart_data);
vm.timechart_selection.call(vm.timechart);

vm.timechart_selection
.select(".nv-axislabel")
.style('font-size', '16')
.style('font-weight', 'bold');

vm.timechart.update();
nv.utils.windowResize(vm.timechart.update);

// Only allow whole numbers as y-axis ticks.
const yAxisTicks = vm.timechart.yScale().ticks().filter(Number.isInteger);
vm.timechart.yAxis
.tickValues(yAxisTicks)
.tickFormat(d3.format('d'));
postSetup: function() {

// Format x-axis labels as time.
vm.timechart.xAxis
.showMaxMin(false)
.tickValues(vm.cdash.ticks)
.tickFormat(function(d) {
const formatter = new Intl.DateTimeFormat("en-us", {
month: "short",
day: "numeric",
hour: "numeric",
minute: "numeric",
});
// We multiply by 1,000 to convert from epoch seconds to milliseconds
// since that's what Javascript's Date() constructor expects.
return formatter.format(new Date(d * 1000));
});
vm.timechart.update();
// perform data marshalling before sending data to plot template
const formatted_data = [];
this.cdash.time_chart_data.data.forEach((line) => {
formatted_data.push({
color: line.color,
name: line.name,
values: line.values.map((d) => {
// converts UNIX epoch format from API to JS date object
return { x: new Date(d[0]*1000), y: d[1] };
})
})
});
this.plot_data = formatted_data;
}
},
}
Expand Down
Loading