1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | var multimeter = require('pm2-multimeter');
|
11 | var os = require('os');
|
12 | var p = require('path');
|
13 | var chalk = require('chalk');
|
14 |
|
15 | var UX = require('./UX');
|
16 |
|
17 | var debug = require('debug')('pm2:monit');
|
18 |
|
19 |
|
20 | const RATIO_T1 = Math.floor(os.totalmem() / 500);
|
21 |
|
22 | const RATIO_T2 = Math.floor(os.totalmem() / 50);
|
23 |
|
24 | const RATIO_T3 = Math.floor(os.totalmem() / 5);
|
25 |
|
26 | const RATIO_T4 = Math.floor(os.totalmem());
|
27 |
|
28 | var Monit = {};
|
29 |
|
30 |
|
31 | Object.size = function(obj) {
|
32 | var size = 0, key;
|
33 | for (key in obj) {
|
34 | if (obj.hasOwnProperty(key)) size++;
|
35 | }
|
36 | return size;
|
37 | };
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 | Monit.reset = function(msg) {
|
45 |
|
46 | this.multi.charm.reset();
|
47 |
|
48 | this.multi.write('\x1B[32m⌬ PM2 \x1B[39mmonitoring\x1B[96m (To go further check out https://app.pm2.io) \x1B[39m\n\n');
|
49 |
|
50 | if(msg) {
|
51 | this.multi.write(msg);
|
52 | }
|
53 |
|
54 | this.bars = {};
|
55 |
|
56 | return this;
|
57 | }
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | Monit.init = function() {
|
65 |
|
66 | this.multi = multimeter(process);
|
67 |
|
68 | this.multi.on('^C', this.stop);
|
69 |
|
70 | this.reset();
|
71 |
|
72 | return this;
|
73 | }
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | Monit.stop = function() {
|
80 | this.multi.charm.destroy();
|
81 | process.exit(0);
|
82 | }
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 | Monit.refresh = function(processes) {
|
92 | debug('Monit refresh');
|
93 |
|
94 | if(!processes) {
|
95 | processes = [];
|
96 | }
|
97 |
|
98 | var num = processes.length;
|
99 | this.num_bars = Object.size(this.bars);
|
100 |
|
101 | if(num !== this.num_bars) {
|
102 | debug('Monit addProcesses - actual: %s, new: %s', this.num_bars, num);
|
103 | return this.addProcesses(processes);
|
104 | } else {
|
105 |
|
106 | if(num === 0) {
|
107 | return;
|
108 | }
|
109 |
|
110 | debug('Monit refresh');
|
111 | var proc;
|
112 |
|
113 | for(var i = 0; i < num; i++) {
|
114 | proc = processes[i];
|
115 |
|
116 |
|
117 |
|
118 | if(this.bars[proc.pm_id] && proc.pm2_env.status !== this.bars[proc.pm_id].status) {
|
119 | debug('bars for %s does not exist', proc.pm_id);
|
120 | this.addProcesses(processes);
|
121 | break;
|
122 | }
|
123 |
|
124 | this.updateBars(proc);
|
125 |
|
126 | }
|
127 | }
|
128 |
|
129 | return this;
|
130 | }
|
131 |
|
132 | Monit.addProcess = function(proc, i) {
|
133 | if(proc.pm_id in this.bars) {
|
134 | return ;
|
135 | }
|
136 |
|
137 | if (proc.monit.error)
|
138 | throw new Error(JSON.stringify(proc.monit.error));
|
139 |
|
140 | var process_name = proc.pm2_env.name || p.basename(proc.pm2_env.pm_exec_path);
|
141 | var status = proc.pm2_env.status == 'online' ? chalk.green.bold('●') : chalk.red.bold('●');
|
142 |
|
143 | this.multi.write(' ' + status + ' ' + chalk.green.bold(process_name));
|
144 | this.multi.write('\n');
|
145 | this.multi.write('[' + proc.pm2_env.pm_id + '] [' + proc.pm2_env.exec_mode + ']\n');
|
146 |
|
147 | var bar_cpu = this.multi(40, (i * 2) + 3 + i, {
|
148 | width: 30,
|
149 | solid: {
|
150 | text: '|',
|
151 | foreground: 'white',
|
152 | background: 'blue'
|
153 | },
|
154 | empty: {
|
155 | text: ' '
|
156 | }
|
157 | });
|
158 |
|
159 | var bar_memory = this.multi(40, (i * 2) + 4 + i, {
|
160 | width: 30,
|
161 | solid: {
|
162 | text: '|',
|
163 | foreground: 'white',
|
164 | background: 'red'
|
165 | },
|
166 | empty: {
|
167 | text: ' '
|
168 | }
|
169 | });
|
170 |
|
171 | this.bars[proc.pm_id] = {
|
172 | memory: bar_memory,
|
173 | cpu: bar_cpu,
|
174 | status: proc.pm2_env.status
|
175 | };
|
176 |
|
177 | this.updateBars(proc);
|
178 |
|
179 | this.multi.write('\n');
|
180 |
|
181 | return this;
|
182 | }
|
183 |
|
184 | Monit.addProcesses = function(processes) {
|
185 |
|
186 | if(!processes) {
|
187 | processes = [];
|
188 | }
|
189 |
|
190 | this.reset();
|
191 |
|
192 | var num = processes.length;
|
193 |
|
194 | if(num > 0) {
|
195 | for(var i = 0; i < num; i++) {
|
196 | this.addProcess(processes[i], i);
|
197 | }
|
198 | } else {
|
199 | this.reset('No processes to monit');
|
200 | }
|
201 |
|
202 | }
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 | Monit.drawRatio = function(bar_memory, memory) {
|
213 | var scale = 0;
|
214 |
|
215 | if (memory < RATIO_T1) scale = RATIO_T1;
|
216 | else if (memory < RATIO_T2) scale = RATIO_T2;
|
217 | else if (memory < RATIO_T3) scale = RATIO_T3;
|
218 | else scale = RATIO_T4;
|
219 |
|
220 | bar_memory.ratio(memory,
|
221 | scale,
|
222 | UX.helpers.bytesToSize(memory, 3));
|
223 | };
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 | Monit.updateBars = function(proc) {
|
231 | if (this.bars[proc.pm_id]) {
|
232 | if (proc.pm2_env.status !== 'online' || proc.pm2_env.status !== this.bars[proc.pm_id].status) {
|
233 | this.bars[proc.pm_id].cpu.percent(0, chalk.red(proc.pm2_env.status));
|
234 | this.drawRatio(this.bars[proc.pm_id].memory, 0, chalk.red(proc.pm2_env.status));
|
235 | } else if (!proc.monit) {
|
236 | this.bars[proc.pm_id].cpu.percent(0, chalk.red('No data'));
|
237 | this.drawRatio(this.bars[proc.pm_id].memory, 0, chalk.red('No data'));
|
238 | } else {
|
239 | this.bars[proc.pm_id].cpu.percent(proc.monit.cpu);
|
240 | this.drawRatio(this.bars[proc.pm_id].memory, proc.monit.memory);
|
241 | }
|
242 | }
|
243 |
|
244 | return this;
|
245 | }
|
246 |
|
247 | module.exports = Monit;
|