Commit 40351b50 by Johannes Edmeier

Add details for garbage collection

parent 69a964e3
......@@ -13,7 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
server.port=8081
info.stage=test
logging.file=/tmp/log.log
......
......@@ -23,7 +23,6 @@
"d3-selection": "^1.2.0",
"d3-shape": "^1.2.0",
"d3-time": "^1.0.8",
"d3-time-format": "^2.1.1",
"event-source-polyfill": "0.0.12",
"linkifyjs": "^2.1.5",
"lodash": "^4.17.4",
......@@ -51,13 +50,13 @@
"css-hot-loader": "^1.3.5",
"css-loader": "^0.28.8",
"css-mqpacker": "^6.0.1",
"eslint": "^4.14.0",
"eslint": "^4.15.0",
"eslint-plugin-html": "^4.0.1",
"eslint-plugin-vue-libs": "^2.1.0",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.6",
"glob": "^7.1.2",
"html-loader": "^0.5.0",
"html-loader": "^0.5.4",
"html-webpack-plugin": "^2.30.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^22.0.4",
......@@ -75,7 +74,7 @@
"vue-test-utils": "^1.0.0-beta.9",
"webpack": "^3.10.0",
"webpack-bundle-analyzer": "^2.9.1",
"webpack-dev-server": "^2.9.7"
"webpack-dev-server": "^2.10.0"
},
"browserslist": [
"> 2%",
......
......@@ -16,7 +16,7 @@
import moment from 'moment';
import {mount} from 'vue-test-utils';
import sbaStatus from './sba-status.vue';
import sbaStatus from './sba-status';
moment.now = () => +new Date(1318781879406);
......
......@@ -21,7 +21,6 @@ import * as scale from 'd3-scale';
import * as selection from 'd3-selection';
import * as shape from 'd3-shape';
import * as time from 'd3-time';
import * as timeFormat from 'd3-time-format';
export default {
...shape,
......@@ -30,6 +29,5 @@ export default {
...array,
...brush,
...time,
...timeFormat,
...selection
}
\ No newline at end of file
......@@ -57,7 +57,7 @@
import subscribing from '@/mixins/subscribing';
import Application from '@/services/application'
import * as _ from 'lodash';
import applicationsList from './applications-list.vue'
import applicationsList from './applications-list';
export default {
mixins: [subscribing],
......
......@@ -53,11 +53,11 @@
max.exit().remove();
//draw areas
const active = vm.areas.selectAll('.mem-chart__area--active')
const active = vm.areas.selectAll('.datasource-chart__area--active')
.data([data]);
active.enter().append('path')
.merge(active)
.attr('class', 'mem-chart__area--active')
.attr('class', 'datasource-chart__area--active')
.attr('d', d3.area()
.x(d => x(d.timestamp))
.y0(y(0))
......@@ -80,7 +80,7 @@
top: 5,
right: 5,
bottom: 30,
left: 20,
left: 25,
};
this.width = this.$el.getBoundingClientRect().width - margin.left - margin.right;
......@@ -115,7 +115,7 @@
.datasource-chart {
&__svg {
height: 125px;
height: 159px;
width: 100%;
}
......
......@@ -53,9 +53,7 @@
export default {
props: ['instance', 'dataSource'],
mixins: [subscribing],
components: {
datasourceChart
},
components: {datasourceChart},
data: () => ({
current: null,
chartData: [],
......
......@@ -29,9 +29,7 @@
export default {
props: ['instance', 'type'],
mixins: [subscribing],
components: {
detailsDatasource
},
components: {detailsDatasource},
data: () => ({
dataSources: [],
}),
......@@ -69,6 +67,3 @@
}
}
</script>
<style lang="scss">
</style>
\ No newline at end of file
<!--
- Copyright 2014-2018 the original author or authors.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-->
<template>
<sba-panel title="Garbage Collection Pauses" v-if="current">
<div slot="text">
<div class="level">
<div class="level-item has-text-centered">
<div>
<p class="heading">Count</p>
<p v-text="current.count"></p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Total time spent</p>
<p v-text="`${current.totalTime.asSeconds()}s`"></p>
</div>
</div>
</div>
</div>
</sba-panel>
</template>
<script>
import subscribing from '@/mixins/subscribing';
import {Observable} from '@/utils/rxjs';
import _ from 'lodash';
import moment from 'moment';
export default {
props: ['instance'],
mixins: [subscribing],
data: () => ({
current: null,
}),
watch: {
instance() {
this.subscribe()
},
dataSource() {
this.current = null;
}
},
methods: {
async fetchMetrics() {
const response = await this.instance.fetchMetric('jvm.gc.pause');
const measurements = response.data.measurements.reduce(
(current, measurement) => ({
...current,
[_.lowerFirst(measurement.statistic)]: measurement.value
}), {}
);
return {...measurements, totalTime: moment.duration(Math.round(measurements.totalTime / 1000))};
},
createSubscription() {
const vm = this;
if (this.instance) {
return Observable.timer(0, 2500)
.concatMap(this.fetchMetrics)
.subscribe({
next: data => {
vm.current = data;
},
errors: err => {
vm.unsubscribe();
}
});
}
}
}
}
</script>
\ No newline at end of file
......@@ -23,12 +23,10 @@
</template>
<script>
import healthDefault from './health/health-default.vue';
import healthDefault from './health/health-default';
export default {
components: {
healthDefault,
},
components: {healthDefault},
props: ['instance'],
data: () => ({
health: {status: 'UNKNOWN', details: []},
......
......@@ -58,9 +58,7 @@
export default {
props: ['instance', 'type'],
mixins: [subscribing],
components: {
memChart
},
components: {memChart},
data: () => ({
current: null,
chartData: [],
......
......@@ -53,9 +53,7 @@
export default {
props: ['instance'],
components: {
processUptime
},
components: {processUptime},
data: () => ({
pid: null,
metrics: {
......
......@@ -15,61 +15,90 @@
-->
<template>
<sba-panel title="Threads" v-if="metrics['jvm.threads.live']">
<div class="level" slot="text">
<div class="level-item has-text-centered">
<div>
<p class="heading">Live</p>
<p v-text="metrics['jvm.threads.live']"></p>
<sba-panel title="Threads" v-if="current">
<div slot="text">
<div class="level threads-current">
<div class="level-item has-text-centered">
<div>
<p class="heading has-bullet has-bullet-warning">Live</p>
<p v-text="current.live"></p>
</div>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Live Peak</p>
<p v-text="metrics['jvm.threads.peak']"></p>
<div class="level-item has-text-centered">
<div>
<p class="heading has-bullet has-bullet-info">Daemon</p>
<p v-text="current.daemon"></p>
</div>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Daemon</p>
<p v-text="metrics['jvm.threads.daemon']"></p>
<div class="level-item has-text-centered">
<div>
<p class="heading">Peak Live</p>
<p v-text="current.peak"></p>
</div>
</div>
</div>
<threads-chart :data="chartData"></threads-chart>
</div>
</sba-panel>
</template>
<script>
import _ from 'lodash';
import subscribing from '@/mixins/subscribing';
import {Observable} from '@/utils/rxjs';
import moment from 'moment';
import threadsChart from './threads-chart';
export default {
props: ['instance'],
mixins: [subscribing],
components: {threadsChart},
data: () => ({
metrics: {
'jvm.threads.live': null,
'jvm.threads.peak': null,
'jvm.threads.daemon': null
}
current: null,
chartData: [],
}),
created() {
this.fetchMetrics();
},
watch: {
instance() {
this.fetchMetrics();
this.subscribe()
},
dataSource() {
this.current = null;
this.chartData = [];
}
},
methods: {
async fetchMetrics() {
const responseLive = this.instance.fetchMetric('jvm.threads.live');
const responsePeak = this.instance.fetchMetric('jvm.threads.peak');
const responseDaemon = this.instance.fetchMetric('jvm.threads.daemon');
return {
live: (await responseLive).data.measurements[0].value,
peak: (await responsePeak).data.measurements[0].value,
daemon: (await responseDaemon).data.measurements[0].value
};
},
createSubscription() {
const vm = this;
if (this.instance) {
const vm = this;
_.entries(vm.metrics).forEach(async ([name]) => {
const response = await vm.instance.fetchMetric(name);
vm.metrics[name] = response.data.measurements[0].value;
}
)
return Observable.timer(0, 2500)
.concatMap(this.fetchMetrics)
.subscribe({
next: data => {
vm.current = data;
vm.chartData.push({...data, timestamp: moment.now().valueOf()});
},
errors: err => {
vm.unsubscribe();
}
});
}
}
}
}
</script>
\ No newline at end of file
</script>
<style lang="scss">
.threads-current {
margin-bottom: 0 !important;
}
</style>
\ No newline at end of file
......@@ -44,7 +44,7 @@
<script>
import _ from 'lodash';
import healthDiskspace from './health-diskspace.vue';
import healthDiskspace from './health-diskspace';
const isChildHealth = (value) => {
return value !== null && typeof value === 'object';
......@@ -52,9 +52,7 @@
export default {
name: "health-default",
components: {
healthDiskspace
},
components: {healthDiskspace},
props: {
name: String,
......
......@@ -28,10 +28,17 @@
<div class="columns">
<div class="column">
<details-process :instance="instance"></details-process>
<details-memory :instance="instance" type="heap"></details-memory>
<details-gc :instance="instance"></details-gc>
</div>
<div class="column">
<details-threads :instance="instance"></details-threads>
</div>
</div>
<div class="columns">
<div class="column">
<details-memory :instance="instance" type="heap"></details-memory>
</div>
<div class="column">
<details-memory :instance="instance" type="nonheap"></details-memory>
</div>
</div>
......@@ -48,6 +55,7 @@
<script>
import detailsDatasources from './details-datasources';
import detailsGc from './details-gc';
import detailsHealth from './details-health';
import detailsInfo from './details-info';
import detailsMemory from './details-memory';
......@@ -56,7 +64,13 @@
export default {
components: {
detailsHealth, detailsInfo, detailsProcess, detailsThreads, detailsDatasources, detailsMemory
detailsHealth,
detailsInfo,
detailsProcess,
detailsThreads,
detailsDatasources,
detailsMemory,
detailsGc
},
props: ['instance']
}
......
......@@ -141,7 +141,7 @@
.mem-chart {
&__svg {
height: 125px;
height: 159px;
width: 100%;
}
......
<!--
- Copyright 2014-2018 the original author or authors.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-->
<template>
<div class="threads-chart">
<svg class="threads-chart__svg"></svg>
</div>
</template>
<script>
import d3 from '@/utils/d3';
import moment from 'moment';
export default {
props: ['data'],
methods: {
drawChart(_data) {
const vm = this;
const data = _data.length === 1 ? _data.concat([{..._data[0], timestamp: _data[0].timestamp + 1}]) : _data;
///setup x and y scale
const extent = d3.extent(data, d => d.timestamp);
const x = d3.scaleTime()
.range([0, vm.width])
.domain(extent);
const y = d3.scaleLinear()
.range([vm.height, 0])
.domain([0, d3.max(data, d => d.live) * 1.1]);
//draw max
const live = vm.areas.selectAll('.threads-chart__area--live')
.data([data]);
live.enter().append('path')
.merge(live)
.attr('class', 'threads-chart__area--live')
.attr('d', d3.area()
.x(d => x(d.timestamp))
.y0(d => y(d.daemon))
.y1(d => y(d.live)));
live.exit().remove();
//draw areas
const daemon = vm.areas.selectAll('.threads-chart__area--daemon')
.data([data]);
daemon.enter().append('path')
.merge(daemon)
.attr('class', 'threads-chart__area--daemon')
.attr('d', d3.area()
.x(d => x(d.timestamp))
.y0(y(0))
.y1(d => y(d.daemon)));
daemon.exit().remove();
//draw axis
vm.xAxis.call(d3.axisBottom(x)
.ticks(5)
.tickFormat(d => moment(d).format("HH:mm:ss"))
);
vm.yAxis.call(d3.axisLeft(y)
.ticks(5)
);
},
},
mounted() {
const margin = {
top: 5,
right: 5,
bottom: 30,
left: 25,
};
this.width = this.$el.getBoundingClientRect().width - margin.left - margin.right;
this.height = this.$el.getBoundingClientRect().height - margin.top - margin.bottom;
this.chartLayer = d3.select(this.$el.querySelector('.threads-chart__svg'))
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
this.xAxis = this.chartLayer.append('g')
.attr('class', 'threads-chart__axis-x')
.attr('transform', `translate(0,${this.height})`);
this.yAxis = this.chartLayer.append('g')
.attr('class', 'threads-chart__axis-y')
.attr('stroke', null);
this.areas = this.chartLayer.append('g');
this.drawChart(this.data);
},
watch: {
data(newVal) {
this.drawChart(newVal);
}
}
}
</script>
<style lang="scss">
@import "~@/assets/css/utilities";
.threads-chart {
&__svg {
height: 159px;
width: 100%;
}
&__area {
&--live {
fill: $warning;
opacity: 0.8;
}
&--daemon {
fill: $info;
opacity: 0.8;
}
}
}
</style>
\ No newline at end of file
......@@ -73,7 +73,7 @@
</template>
<script>
import sbaLoggerControl from './logger-control.vue'
import sbaLoggerControl from './logger-control';
const isPackageName = (name) => {
const i = name.lastIndexOf('.') + 1;
......
......@@ -24,8 +24,8 @@
<script>
import instance from '@/services/instance'
import sbaInstanceHeader from './header.vue'
import sbaInstanceTabs from './tabs.vue'
import sbaInstanceHeader from './header';
import sbaInstanceTabs from './tabs';
export default {
components: {sbaInstanceHeader, sbaInstanceTabs},
......
......@@ -52,7 +52,8 @@
<script>
import d3 from '@/utils/d3';
import {event as d3Event} from 'd3-selection'; //see https://github.com/d3/d3/issues/2733#issuecomment-190743489
//see https://github.com/d3/d3/issues/2733#issuecomment-190743489
import {event as d3Event} from 'd3-selection';
import moment from 'moment-shortformat';
const interval = 1000;
......
......@@ -22,7 +22,7 @@
</template>
<script>
import sbaNavbar from './navbar.vue'
import sbaNavbar from './navbar';
export default {
components: {sbaNavbar},
......
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