Commit ec449eeb by Johannes Edmeier

Make metrics view config bookmarkable

parent 732ee621
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
import {shallow} from '@vue/test-utils';
import {shallowMount} from '@vue/test-utils';
import moment from 'moment';
import sbaTimeAgo from './sba-time-ago.js';
......@@ -23,7 +23,7 @@ moment.now = () => +new Date(1318781879406);
describe('time-ago', () => {
it('should match the snapshot', () => {
const wrapper = shallow(sbaTimeAgo, {
const wrapper = shallowMount(sbaTimeAgo, {
propsData: {
date: moment(1318781000000)
}
......
......@@ -39,7 +39,7 @@
</ul>
</nav>
</div>
<div class="column is-clipped" v-if="selectedDomain">
<div class="column" v-if="selectedDomain">
<h1 class="heading">MBeans</h1>
<div class="m-bean card" :class="{'is-active': mBean === selectedMBean}"
v-for="mBean in selectedDomain.mBeans" :key="mBean.descriptor.raw" :id="mBean.descriptor.raw"
......@@ -162,8 +162,10 @@
},
watch: {
'$route.query': {
handler: 'updateSelection',
immediate: true
immediate: true,
handler() {
this.selected = this.$route.query;
}
},
selected() {
if (!_.isEqual(this.selected, !this.$route.query)) {
......@@ -209,9 +211,6 @@
mBean: mBean && mBean.descriptor.raw,
view: view || (mBean ? (mBean.attr ? 'attributes' : (mBean.op ? 'operations' : null)) : null)
};
},
updateSelection() {
this.selected = this.$route.query;
}
}
}
......
......@@ -72,8 +72,10 @@
:key="metric.name"
:metric-name="metric.name"
:tag-selections="metric.tagSelections"
:statistic-types="metric.types"
:instance="instance"
@remove="removeMetric"
@type-select="handleTypeSelect"
/>
</div>
</section>
......@@ -84,6 +86,21 @@
import _ from 'lodash';
import Metric from './metric';
const stringify = metrics => {
return {q: metrics.map(JSON.stringify)};
};
const parse = query => {
if (!query.q) {
return [];
}
if (query.q instanceof Array) {
return query.q.map(JSON.parse);
} else {
return JSON.parse(query.q);
}
};
export default {
components: {Metric},
props: {
......@@ -105,12 +122,33 @@
this.fetchMetricIndex();
},
watch: {
selectedMetric: 'fetchAvailableTags'
selectedMetric: 'fetchAvailableTags',
metrics: {
deep: true,
handler() {
this.$router.replace({
name: 'instance/metrics',
query: stringify(this.metrics)
})
}
},
'$route.query': {
immediate: true,
handler() {
this.metrics = parse(this.$route.query);
}
}
},
methods: {
handleSubmit() {
this.addMetric(this.selectedMetric, this.selectedTags)
},
handleTypeSelect(metricName, statistic, type) {
const metric = this.metrics.find(m => m.name === metricName);
if (metric) {
metric.types = {...metric.types, [statistic]: type}
}
},
removeMetric(metricName, idxTagSelection) {
const idxMetric = this.metrics.findIndex(m => m.name === metricName);
if (idxMetric >= 0) {
......@@ -131,7 +169,8 @@
} else {
this.metrics = _.sortBy([...this.metrics, {
name: metricName,
tagSelections: [{...tagSelection}]
tagSelections: [{...tagSelection}],
types: {}
}], [m => m.name]);
}
}
......
......@@ -15,16 +15,16 @@
-->
<template>
<table class="metrics table is-fullwidth is-bordered is-narrow">
<table class="metrics table is-fullwidth">
<thead>
<tr>
<th v-text="metricName"/>
<th class="metrics__label" v-text="metricName"/>
<th class="metrics__statistic-name"
v-for="statistic in statistics"
:key="`head-${statistic.name}`">
<span v-text="statistic.name"/>
:key="`head-${statistic}`">
<span v-text="statistic"/>
<div class="select is-small is-pulled-right">
<select v-model="statistic.type">
<select :value="statisticTypes[statistic]" @input="$emit('type-select', metricName, statistic, $event.target.value)">
<option :value="undefined">-</option>
<option value="integer">Integer</option>
<option value="float">Float</option>
......@@ -39,7 +39,7 @@
</thead>
<tbody>
<tr v-for="(tags, idx) in tagSelections" :key="idx">
<td>
<td class="metrics__label">
<span v-text="getLabel(tags)"/>
<span class="has-text-warning" v-if="errors[idx]" :title="errors[idx]">
<font-awesome-icon icon="exclamation-triangle"/>
......@@ -47,10 +47,10 @@
</td>
<td class="metrics__statistic-value"
v-for="statistic in statistics"
:key="`value-${idx}-${statistic.name}`"
:key="`value-${idx}-${statistic}`"
v-text="getValue(measurements[idx], statistic)"
/>
<td>
<td class="metrics__actions">
<sba-icon-button :icon="'trash'" @click.stop="handleRemove(idx)"/>
</td>
</tr>
......@@ -90,6 +90,10 @@
tagSelections: {
type: Array,
default: () => [{}]
},
statisticTypes: {
type: Object,
default: () => ({})
}
},
data: () => ({
......@@ -102,11 +106,11 @@
this.$emit('remove', this.metricName, idx);
},
getValue(measurements, statistic) {
const measurement = measurements && measurements.find(m => m.statistic === statistic.name);
const measurement = measurements && measurements.find(m => m.statistic === statistic);
if (!measurement) {
return undefined;
}
const type = statistic && statistic.type;
const type = this.statisticTypes[statistic]
switch (type) {
case 'integer':
return measurement.value.toFixed(0);
......@@ -124,8 +128,8 @@
},
getLabel(tags) {
return _.entries(tags).filter(([, value]) => typeof value !== 'undefined')
.map(pair => pair.join('='))
.join(' ');
.map(pair => pair.join(':'))
.join('\n') || '(no tags)';
},
async fetchMetric(tags, idx) {
try {
......@@ -133,14 +137,11 @@
this.$set(this.errors, idx, null);
this.$set(this.measurements, idx, response.data.measurements);
if (idx === 0) {
response.data.measurements.map(m => m.statistic)
.filter(s => !this.statistics.some(stat => stat.name === s))
.map(s => ({name: s, type: undefined}))
.forEach(s => this.statistics.push(s));
this.statistics = response.data.measurements.map(m => m.statistic);
}
} catch (error) {
console.warn(`Fetching metric ${this.metricName} failed:`, error);
this.errors[idx] = error;
this.$set(this.errors, idx, error);
}
},
fetchAllTags() {
......@@ -166,17 +167,23 @@
}
</script>
<style lang="scss">
table.metrics {
table-layout: fixed;
}
.metrics {
table .metrics {
&__label {
width: 300px;
white-space: pre-wrap;
}
&__actions {
width: 1px;
vertical-align: middle;
}
&__statistic-name * {
vertical-align: middle;
}
&__statistic-value {
text-align: right;
vertical-align: middle;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment