summaryrefslogtreecommitdiff
path: root/src/client/app/admin/views/queue.chart.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/app/admin/views/queue.chart.vue')
-rw-r--r--src/client/app/admin/views/queue.chart.vue181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/client/app/admin/views/queue.chart.vue b/src/client/app/admin/views/queue.chart.vue
new file mode 100644
index 0000000000..c3d68d75af
--- /dev/null
+++ b/src/client/app/admin/views/queue.chart.vue
@@ -0,0 +1,181 @@
+<template>
+<div>
+ <ui-info warn v-if="latestStats && latestStats.waiting > 0">The queue is jammed.</ui-info>
+ <ui-horizon-group inputs v-if="latestStats" class="fit-bottom">
+ <ui-input :value="latestStats.activeSincePrevTick | number" type="text" readonly>
+ <span>Process</span>
+ <template #prefix><fa :icon="fasPlayCircle"/></template>
+ <template #suffix>jobs/tick</template>
+ </ui-input>
+ <ui-input :value="latestStats.active | number" type="text" readonly>
+ <span>Active</span>
+ <template #prefix><fa :icon="farPlayCircle"/></template>
+ <template #suffix>jobs</template>
+ </ui-input>
+ <ui-input :value="latestStats.waiting | number" type="text" readonly>
+ <span>Waiting</span>
+ <template #prefix><fa :icon="faStopCircle"/></template>
+ <template #suffix>jobs</template>
+ </ui-input>
+ <ui-input :value="latestStats.delayed | number" type="text" readonly>
+ <span>Delayed</span>
+ <template #prefix><fa :icon="faStopwatch"/></template>
+ <template #suffix>jobs</template>
+ </ui-input>
+ </ui-horizon-group>
+ <div ref="chart" class="wptihjuy"></div>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import i18n from '../../i18n';
+import ApexCharts from 'apexcharts';
+import * as tinycolor from 'tinycolor2';
+import { faStopwatch, faPlayCircle as fasPlayCircle } from '@fortawesome/free-solid-svg-icons';
+import { faStopCircle, faPlayCircle as farPlayCircle } from '@fortawesome/free-regular-svg-icons';
+
+export default Vue.extend({
+ i18n: i18n('admin/views/queue.vue'),
+
+ props: {
+ type: {
+ type: String,
+ required: true
+ },
+ connection: {
+ required: true
+ },
+ limit: {
+ type: Number,
+ required: true
+ }
+ },
+
+ data() {
+ return {
+ stats: [],
+ chart: null,
+ faStopwatch, faStopCircle, farPlayCircle, fasPlayCircle
+ };
+ },
+
+ computed: {
+ latestStats(): any {
+ return this.stats.length > 0 ? this.stats[this.stats.length - 1][this.type] : null;
+ }
+ },
+
+ watch: {
+ stats(stats) {
+ this.chart.updateSeries([{
+ name: 'Process',
+ type: 'area',
+ data: stats.map((x, i) => ({ x: i, y: x[this.type].activeSincePrevTick }))
+ }, {
+ name: 'Active',
+ type: 'area',
+ data: stats.map((x, i) => ({ x: i, y: x[this.type].active }))
+ }, {
+ name: 'Waiting',
+ type: 'line',
+ data: stats.map((x, i) => ({ x: i, y: x[this.type].waiting }))
+ }, {
+ name: 'Delayed',
+ type: 'line',
+ data: stats.map((x, i) => ({ x: i, y: x[this.type].delayed }))
+ }]);
+ },
+ },
+
+ mounted() {
+ this.chart = new ApexCharts(this.$refs.chart, {
+ chart: {
+ id: this.type,
+ group: 'queue',
+ type: 'area',
+ height: 200,
+ animations: {
+ dynamicAnimation: {
+ enabled: false
+ }
+ },
+ toolbar: {
+ show: false
+ },
+ zoom: {
+ enabled: false
+ }
+ },
+ dataLabels: {
+ enabled: false
+ },
+ grid: {
+ clipMarkers: false,
+ borderColor: 'rgba(0, 0, 0, 0.1)',
+ xaxis: {
+ lines: {
+ show: true,
+ }
+ },
+ },
+ stroke: {
+ curve: 'straight',
+ width: 2
+ },
+ tooltip: {
+ enabled: false
+ },
+ legend: {
+ labels: {
+ colors: tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--text')).toRgbString()
+ },
+ },
+ series: [] as any,
+ colors: ['#00E396', '#00BCD4', '#FFB300', '#e53935'],
+ xaxis: {
+ type: 'numeric',
+ labels: {
+ show: false
+ },
+ tooltip: {
+ enabled: false
+ }
+ },
+ yaxis: {
+ show: false,
+ min: 0,
+ }
+ });
+
+ this.chart.render();
+
+ this.connection.on('stats', this.onStats);
+ this.connection.on('statsLog', this.onStatsLog);
+
+ this.$once('hook:beforeDestroy', () => {
+ if (this.chart) this.chart.destroy();
+ });
+ },
+
+ methods: {
+ onStats(stats) {
+ this.stats.push(stats);
+ if (this.stats.length > this.limit) this.stats.shift();
+ },
+
+ onStatsLog(statsLog) {
+ for (const stats of statsLog.reverse()) {
+ this.onStats(stats);
+ }
+ },
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.wptihjuy
+ min-height 200px !important
+ margin 0 -8px -8px -8px
+
+</style>