1 | 'use strict'
|
2 |
|
3 | const d3 = require('./d3.js')
|
4 | const EventEmitter = require('events')
|
5 | const SubGraph = require('./sub-graph')
|
6 |
|
7 | class Graph extends EventEmitter {
|
8 | constructor () {
|
9 | super()
|
10 |
|
11 | this.data = null
|
12 | this.container = d3.select('#graph')
|
13 |
|
14 | this.cpu = new SubGraph(this.container, {
|
15 | className: 'cpu',
|
16 | name: 'CPU Usage',
|
17 | unit: '%',
|
18 | shortLegend: ['Usage'],
|
19 | showLegend: false,
|
20 | lineStyle: [''],
|
21 | numLines: 1,
|
22 | ymin: 0,
|
23 | ymax: 100
|
24 | })
|
25 |
|
26 | this.memory = new SubGraph(this.container, {
|
27 | className: 'memory',
|
28 | name: 'Memory Usage',
|
29 | unit: 'MB',
|
30 | longLegend: ['RSS', 'Total Heap Allocated', 'Heap Used'],
|
31 | shortLegend: ['RSS', 'THA', 'HU'],
|
32 | tooltipLegend: [
|
33 | 'Total memory allocated for the entire process',
|
34 | 'Amount of V8 memory assigned to store data',
|
35 | 'Heap memory used out of the Total Heap'
|
36 | ],
|
37 | showLegend: true,
|
38 | lineStyle: ['1, 2', '5, 3', ''],
|
39 | numLines: 3,
|
40 | ymin: 0
|
41 | })
|
42 |
|
43 | this.delay = new SubGraph(this.container, {
|
44 | className: 'delay',
|
45 | name: 'Event Loop Delay',
|
46 | unit: 'ms',
|
47 | shortLegend: ['Delay'],
|
48 | showLegend: false,
|
49 | lineStyle: [''],
|
50 | numLines: 1,
|
51 | ymin: 0,
|
52 | interpolation: 'curveStepBefore'
|
53 | })
|
54 |
|
55 | this.handles = new SubGraph(this.container, {
|
56 | className: 'handles',
|
57 | name: 'Active Handles',
|
58 | unit: '',
|
59 | shortLegend: ['Handles'],
|
60 | showLegend: false,
|
61 | lineStyle: [''],
|
62 | numLines: 1,
|
63 | ymin: 0,
|
64 | interpolation: 'curveStepBefore'
|
65 | })
|
66 |
|
67 |
|
68 | for (const subgraph of [this.cpu, this.memory, this.delay, this.handles]) {
|
69 | subgraph.on('hover-update', (unitX) => this.emit('hover-update', unitX))
|
70 | subgraph.on('hover-show', () => this.emit('hover-show'))
|
71 | subgraph.on('hover-hide', () => this.emit('hover-hide'))
|
72 | subgraph.on('alert-click', () => this.emit('alert-click'))
|
73 | }
|
74 | }
|
75 |
|
76 | hoverUpdate (unitX) {
|
77 | if (this.data === null) {
|
78 | throw new Error('data not loaded')
|
79 | }
|
80 |
|
81 | const points = this.data.getPoints(unitX)
|
82 | this.cpu.hoverUpdate(points.cpu)
|
83 | this.memory.hoverUpdate(points.memory)
|
84 | this.delay.hoverUpdate(points.delay)
|
85 | this.handles.hoverUpdate(points.handles)
|
86 | }
|
87 |
|
88 | hoverShow () {
|
89 | if (this.data === null) {
|
90 | throw new Error('data not loaded')
|
91 | }
|
92 |
|
93 | this.cpu.hoverShow()
|
94 | this.memory.hoverShow()
|
95 | this.delay.hoverShow()
|
96 | this.handles.hoverShow()
|
97 | }
|
98 |
|
99 | hoverHide () {
|
100 | if (this.data === null) {
|
101 | throw new Error('data not loaded')
|
102 | }
|
103 |
|
104 | this.cpu.hoverHide()
|
105 | this.memory.hoverHide()
|
106 | this.delay.hoverHide()
|
107 | this.handles.hoverHide()
|
108 | }
|
109 |
|
110 | setData (data) {
|
111 | this.data = data
|
112 |
|
113 | this.cpu.setData(data.cpu, data.analysis.interval, [
|
114 | data.analysis.issues.cpu
|
115 | ])
|
116 | this.delay.setData(data.delay, data.analysis.interval, [
|
117 | data.analysis.issues.delay
|
118 | ])
|
119 | this.handles.setData(data.handles, data.analysis.interval, [
|
120 | data.analysis.issues.handles
|
121 | ])
|
122 | this.memory.setData(data.memory, data.analysis.interval, [
|
123 | data.analysis.issues.memory.rss,
|
124 | data.analysis.issues.memory.heapTotal,
|
125 | data.analysis.issues.memory.heapUsed
|
126 | ])
|
127 | }
|
128 |
|
129 | draw () {
|
130 | this.cpu.draw()
|
131 | this.memory.draw()
|
132 | this.delay.draw()
|
133 | this.handles.draw()
|
134 | }
|
135 | }
|
136 |
|
137 | module.exports = new Graph()
|