# HG changeset patch # User Andrew Azores # Date 1509025678 14400 # Node ID b35a283eb0165caae279dc802866b959530a5706 # Parent 671cfc1d001d56b57d31d455d9442d115be4c1ea Add resident memory timeseries chart to jvm-memory Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-October/025532.html diff -r 671cfc1d001d -r b35a283eb016 mock-api/endpoints/jvm-memory.endpoint.js --- a/mock-api/endpoints/jvm-memory.endpoint.js Wed Oct 25 11:51:03 2017 -0400 +++ b/mock-api/endpoints/jvm-memory.endpoint.js Thu Oct 26 09:47:58 2017 -0400 @@ -32,6 +32,7 @@ metaspaceMinCapacity: { $numberLong: '0' }, metaspaceCapacity: { $numberLong: (4096 * 1024 * 1024).toString() }, metaspaceUsed: { $numberLong: _.round(4096 * 1024 * 1024 * Math.random()).toString() }, + residentMemory: { $numberLong: _.round(2 * 1024 * 1024 * Math.random()).toString() }, generations: [ { capacity: { $numberLong: (100 * 1024 * 1024).toString() }, diff -r 671cfc1d001d -r b35a283eb016 src/app/components/jvm-info/jvm-memory/en.locale.yaml --- a/src/app/components/jvm-info/jvm-memory/en.locale.yaml Wed Oct 25 11:51:03 2017 -0400 +++ b/src/app/components/jvm-info/jvm-memory/en.locale.yaml Thu Oct 26 09:47:58 2017 -0400 @@ -3,11 +3,13 @@ REFRESH_RATE_LABEL: Refresh Rate MAX_DATA_AGE_LABEL: Max Data Age + RESIDENT: Resident Set Size METASPACE: Metaspace COLLECTOR: '{{name}} generation ({{collector}} collector)' SPACE: Space {{index}} X_AXIS_LABEL: Time - Y_AXIS_LABEL: Bytes + Y_AXIS_LABEL_B: Bytes + Y_AXIS_LABEL_KB: Kibibytes refresh: DISABLED: Disabled diff -r 671cfc1d001d -r b35a283eb016 src/app/components/jvm-info/jvm-memory/jvm-memory.controller.js --- a/src/app/components/jvm-info/jvm-memory/jvm-memory.controller.js Wed Oct 25 11:51:03 2017 -0400 +++ b/src/app/components/jvm-info/jvm-memory/jvm-memory.controller.js Thu Oct 26 09:47:58 2017 -0400 @@ -47,6 +47,15 @@ this._metricToNumber = metricToNumberFilter; this._scaleBytes = scaleBytesService; + this._residentData = { + timestamps: [], + used: [] + }; + this.residentSeriesData = { + xData: ['timestamp'], + yData: ['memory'] + }; + this.metaspaceSnapshotData = { used: 0, total: 0 @@ -64,39 +73,71 @@ units: 'B' }; - $translate(['jvmMemory.X_AXIS_LABEL', 'jvmMemory.Y_AXIS_LABEL']).then(translations => { - this._xAxisLabel = translations['jvmMemory.X_AXIS_LABEL']; - this._yAxisLabel = translations['jvmMemory.Y_AXIS_LABEL']; - this.metaspaceLineConfig = { - chartId: 'metaspaceLineChart', - units: 'B', - axis: { - x: { - show: true, - type: 'timeseries', - label: { - text: this._xAxisLabel, - position: 'outer-center' + $translate(['jvmMemory.X_AXIS_LABEL', + 'jvmMemory.Y_AXIS_LABEL_KB', + 'jvmMemory.Y_AXIS_LABEL_B']) + .then(translations => { + this._xAxisLabel = translations['jvmMemory.X_AXIS_LABEL']; + this._yAxisLabelBytes = translations['jvmMemory.Y_AXIS_LABEL_B']; + this.residentLineConfig = { + chartId: 'residentLineChart', + units: 'KiB', + axis: { + x: { + show: true, + type: 'timeseries', + label: { + text: this._xAxisLabel, + position: 'outer-center' + }, + tick : { + format: timestamp => this._dateFilter(timestamp, this._dateFormat.time.medium), + count: 5, + fit: false + } }, - tick : { - format: timestamp => this._dateFilter(timestamp, this._dateFormat.time.medium), - count: 5, - fit: false - } - }, - y: { - show: true, - min: 0, - padding: 0, - tick: 10, - label: { - text: this._yAxisLabel, - position: 'outer-middle' + y: { + show: true, + min: 0, + padding: 0, + tick: 10, + label: { + text: translations['jvmMemory.Y_AXIS_LABEL_KB'], + position: 'outer-middle' + } } } - } - }; - }); + }; + this.metaspaceLineConfig = { + chartId: 'metaspaceLineChart', + units: 'B', + axis: { + x: { + show: true, + type: 'timeseries', + label: { + text: this._xAxisLabel, + position: 'outer-center' + }, + tick : { + format: timestamp => this._dateFilter(timestamp, this._dateFormat.time.medium), + count: 5, + fit: false + } + }, + y: { + show: true, + min: 0, + padding: 0, + tick: 10, + label: { + text: this._yAxisLabelBytes, + position: 'outer-middle' + } + } + } + }; + }); this.spaceBarConfigs = []; this._generationData = new Map(); this.generationSnapshotData = {}; @@ -134,7 +175,7 @@ padding: 0, tick: 10, label: { - text: this._yAxisLabel, + text: this._yAxisLabelBytes, position: 'outer-middle' } } @@ -187,6 +228,14 @@ return this._dataAgeLimit.toString(); } + multichartResident () { + return new Promise(resolve => + this._jvmMemoryService.getSnapshot(this.jvmId).then(resp => + resolve(this.convertMemStat(resp.residentMemory)) + ) + ); + } + multichartMetaspace () { return new Promise(resolve => this._jvmMemoryService.getSnapshot(this.jvmId).then(resp => @@ -238,6 +287,10 @@ let timestamp = this._metricToNumber(update.timeStamp); + let residentUsed = this.convertMemStat(update.residentMemory); + this._residentData.timestamps.push(timestamp); + this._residentData.used.push(residentUsed); + let metaspaceUsed = this.convertMemStat(update.metaspaceUsed); let metaspaceCapacity = this.convertMemStat(update.metaspaceCapacity); @@ -277,6 +330,16 @@ let now = this._getCurrentTimestamp(); let limit = now - this._dataAgeLimit; + let residentSpliceCount = 0; + for (; residentSpliceCount < this._residentData.timestamps.length; residentSpliceCount++) { + let sample = this._residentData.timestamps[residentSpliceCount]; + if (sample >= limit) { + break; + } + } + this._residentData.timestamps.splice(0, residentSpliceCount); + this._residentData.used.splice(0, residentSpliceCount); + let metaspaceSpliceCount = 0; for (; metaspaceSpliceCount < this._metaspaceData.timestamps.length; metaspaceSpliceCount++) { let sample = this._metaspaceData.timestamps[metaspaceSpliceCount]; @@ -303,6 +366,11 @@ } _updateLineCharts (keys) { + this.residentSeriesData = { + xData: ['timestamp'].concat(this._residentData.timestamps), + yData: ['memory'].concat(this._residentData.used) + }; + this.metaspaceSeriesData = { xData: ['timestamp'].concat(this._metaspaceData.timestamps), yData: ['memory'].concat(this._metaspaceData.used) diff -r 671cfc1d001d -r b35a283eb016 src/app/components/jvm-info/jvm-memory/jvm-memory.controller.spec.js --- a/src/app/components/jvm-info/jvm-memory/jvm-memory.controller.spec.js Wed Oct 25 11:51:03 2017 -0400 +++ b/src/app/components/jvm-info/jvm-memory/jvm-memory.controller.spec.js Thu Oct 26 09:47:58 2017 -0400 @@ -109,6 +109,20 @@ }); }); + describe('residentLineConfig', () => { + it('should be assigned after init', () => { + ctrl.should.have.ownProperty('residentLineConfig'); + }); + + it('should provide an x-axis tick formatter', () => { + let fn = ctrl.residentLineConfig.axis.x.tick.format; + dateFilter.should.not.be.called(); + fn(1234); + dateFilter.should.be.calledOnce(); + dateFilter.should.be.calledWith(1234, dateFormat.time.medium); + }); + }); + describe('metaspaceLineConfig', () => { it('should be assigned after init', () => { ctrl.should.have.ownProperty('metaspaceLineConfig'); @@ -203,18 +217,21 @@ }); describe('_update', () => { - let data; + let timestamp, data; beforeEach(() => { + timestamp = Date.now(); data = [{ agentId: 'foo-agentId', jvmId: 'foo-jvmId', - timeStamp: { $numberLong: Date.now().toString() }, + timeStamp: { $numberLong: timestamp.toString() }, metaspaceMaxCapacity: { $numberLong: '0' }, metaspaceMinCapacity: { $numberLong: '0' }, metaspaceCapacity: { $numberLong: (40 * 1024 * 1024).toString() }, metaspaceUsed: { $numberLong: (20 * 1024 * 1024).toString() }, + residentMemory: { $numberLong: (2 * 1024 * 1024).toString() }, generations: [ { + index: 0, capacity: { $numberLong: (10 * 1024 * 1024).toString() }, collector: 'Shenandoah', maxCapacity: { $numberLong: (60 * 1024 * 1024).toString() }, @@ -235,6 +252,26 @@ promise.then.yield(data); }); + it('should add series data', () => { + ctrl._residentData.should.deepEqual({ + timestamps: [timestamp, timestamp], + used: [2 * 1024 * 1024, 2 * 1024 * 1024] + }); + + ctrl._metaspaceData.should.deepEqual({ + timestamps: [timestamp, timestamp], + used: [20 * 1024 * 1024, 20 * 1024 * 1024], + capacity: [40 * 1024 * 1024, 40 * 1024 * 1024] + }); + + ctrl._generationData.has(ctrl._getKey(0, 0)).should.be.true(); + ctrl._generationData.get(ctrl._getKey(0, 0)).should.deepEqual({ + timestamps: [timestamp, timestamp], + used: [30 * 1024 * 1024, 30 * 1024 * 1024], + capacity: [50 * 1024 * 1024, 50 * 1024 * 1024] + }); + }); + it('should update metaspaceSnapshotData', () => { ctrl.metaspaceSnapshotData.should.deepEqual({ used: 20, @@ -333,6 +370,19 @@ }); describe('_trimData', () => { + it('should trim old resident data', () => { + let now = Date.now(); + ctrl._residentData = { + timestamps: [now - 120 * 60 * 1000, now], + used: [100, 200], + }; + ctrl._trimData(); + ctrl._residentData.should.deepEqual({ + timestamps: [now], + used: [200] + }); + }); + it('should trim old metaspace data', () => { let now = Date.now(); ctrl._metaspaceData = { @@ -380,6 +430,27 @@ }); }); + describe('multichartResident', () => { + it('should return a promise', () => { + let res = ctrl.multichartResident(); + res.should.be.a.Promise(); + }); + + it('should resolve jvm-memory resident memory stat', done => { + promise.then.should.be.calledOnce(); + let res = ctrl.multichartResident(); + res.then(v => { + v.should.equal(9001); + done(); + }); + promise.then.should.be.calledTwice(); + let prom = promise.then.secondCall.args[0]; + prom({ + residentMemory: { $numberLong: '9001' } + }); + }); + }); + describe('multichartMetaspace', () => { it('should return a promise', () => { let res = ctrl.multichartMetaspace(); diff -r 671cfc1d001d -r b35a283eb016 src/app/components/jvm-info/jvm-memory/jvm-memory.html --- a/src/app/components/jvm-info/jvm-memory/jvm-memory.html Wed Oct 25 11:51:03 2017 -0400 +++ b/src/app/components/jvm-info/jvm-memory/jvm-memory.html Thu Oct 26 09:47:58 2017 -0400 @@ -32,6 +32,29 @@
+ + +
+
+ +
+
+
+ + + + + +
+
+ +
+
+