pmx.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const configuration_1 = require("./configuration");
  4. const debug_1 = require("debug");
  5. const serviceManager_1 = require("./serviceManager");
  6. const transport_1 = require("./services/transport");
  7. const featureManager_1 = require("./featureManager");
  8. const actions_1 = require("./services/actions");
  9. const metrics_1 = require("./services/metrics");
  10. const constants_1 = require("./constants");
  11. const runtimeStats_1 = require("./services/runtimeStats");
  12. const entrypoint_1 = require("./features/entrypoint");
  13. class IOConfig {
  14. constructor() {
  15. this.catchExceptions = true;
  16. this.profiling = true;
  17. this.tracing = false;
  18. this.standalone = false;
  19. }
  20. }
  21. exports.IOConfig = IOConfig;
  22. exports.defaultConfig = {
  23. catchExceptions: true,
  24. profiling: true,
  25. metrics: {
  26. v8: true,
  27. network: false,
  28. eventLoop: true,
  29. runtime: true,
  30. http: true
  31. },
  32. standalone: false,
  33. apmOptions: undefined,
  34. tracing: {
  35. enabled: false,
  36. outbound: false
  37. }
  38. };
  39. class PMX {
  40. constructor() {
  41. this.featureManager = new featureManager_1.FeatureManager();
  42. this.transport = null;
  43. this.actionService = null;
  44. this.metricService = null;
  45. this.runtimeStatsService = null;
  46. this.logger = debug_1.default('axm:main');
  47. this.initialized = false;
  48. this.Entrypoint = entrypoint_1.Entrypoint;
  49. }
  50. init(config) {
  51. const callsite = (new Error().stack || '').split('\n')[2];
  52. if (callsite && callsite.length > 0) {
  53. this.logger(`init from ${callsite}`);
  54. }
  55. if (this.initialized === true) {
  56. this.logger(`Calling init but was already the case, destroying and recreating`);
  57. this.destroy();
  58. }
  59. if (config === undefined) {
  60. config = exports.defaultConfig;
  61. }
  62. if (!config.standalone) {
  63. const autoStandalone = process.env.PM2_SECRET_KEY && process.env.PM2_PUBLIC_KEY && process.env.PM2_APP_NAME;
  64. config.standalone = !!autoStandalone;
  65. config.apmOptions = autoStandalone ? {
  66. secretKey: process.env.PM2_SECRET_KEY,
  67. publicKey: process.env.PM2_PUBLIC_KEY,
  68. appName: process.env.PM2_APP_NAME
  69. } : undefined;
  70. }
  71. this.transport = transport_1.createTransport(config.standalone === true ? 'websocket' : 'ipc', config.apmOptions);
  72. serviceManager_1.ServiceManager.set('transport', this.transport);
  73. if (constants_1.canUseInspector()) {
  74. const Inspector = require('./services/inspector');
  75. const inspectorService = new Inspector();
  76. inspectorService.init();
  77. serviceManager_1.ServiceManager.set('inspector', inspectorService);
  78. }
  79. this.actionService = new actions_1.ActionService();
  80. this.actionService.init();
  81. serviceManager_1.ServiceManager.set('actions', this.actionService);
  82. this.metricService = new metrics_1.MetricService();
  83. this.metricService.init();
  84. serviceManager_1.ServiceManager.set('metrics', this.metricService);
  85. this.runtimeStatsService = new runtimeStats_1.RuntimeStatsService();
  86. this.runtimeStatsService.init();
  87. if (this.runtimeStatsService.isEnabled()) {
  88. serviceManager_1.ServiceManager.set('runtimeStats', this.runtimeStatsService);
  89. }
  90. this.featureManager.init(config);
  91. configuration_1.default.init(config);
  92. this.initialConfig = config;
  93. this.initialized = true;
  94. return this;
  95. }
  96. destroy() {
  97. this.logger('destroy');
  98. this.featureManager.destroy();
  99. if (this.actionService !== null) {
  100. this.actionService.destroy();
  101. }
  102. if (this.transport !== null) {
  103. this.transport.destroy();
  104. }
  105. if (this.metricService !== null) {
  106. this.metricService.destroy();
  107. }
  108. if (this.runtimeStatsService !== null) {
  109. this.runtimeStatsService.destroy();
  110. }
  111. const inspectorService = serviceManager_1.ServiceManager.get('inspector');
  112. if (inspectorService !== undefined) {
  113. inspectorService.destroy();
  114. }
  115. }
  116. getConfig() {
  117. return this.initialConfig;
  118. }
  119. notifyError(error, context) {
  120. const notify = this.featureManager.get('notify');
  121. return notify.notifyError(error, context);
  122. }
  123. metrics(metric) {
  124. const res = [];
  125. if (metric === undefined || metric === null) {
  126. console.error(`Received empty metric to create`);
  127. console.trace();
  128. return [];
  129. }
  130. let metrics = !Array.isArray(metric) ? [metric] : metric;
  131. for (let metric of metrics) {
  132. if (typeof metric.name !== 'string') {
  133. console.error(`Trying to create a metrics without a name`, metric);
  134. console.trace();
  135. res.push({});
  136. continue;
  137. }
  138. if (metric.type === undefined) {
  139. metric.type = metrics_1.MetricType.gauge;
  140. }
  141. switch (metric.type) {
  142. case metrics_1.MetricType.counter: {
  143. res.push(this.counter(metric));
  144. continue;
  145. }
  146. case metrics_1.MetricType.gauge: {
  147. res.push(this.gauge(metric));
  148. continue;
  149. }
  150. case metrics_1.MetricType.histogram: {
  151. res.push(this.histogram(metric));
  152. continue;
  153. }
  154. case metrics_1.MetricType.meter: {
  155. res.push(this.meter(metric));
  156. continue;
  157. }
  158. case metrics_1.MetricType.metric: {
  159. res.push(this.gauge(metric));
  160. continue;
  161. }
  162. default: {
  163. console.error(`Invalid metric type ${metric.type} for metric ${metric.name}`);
  164. console.trace();
  165. res.push({});
  166. continue;
  167. }
  168. }
  169. }
  170. return res;
  171. }
  172. histogram(config) {
  173. if (typeof config === 'string') {
  174. config = {
  175. name: config,
  176. measurement: metrics_1.MetricMeasurements.mean
  177. };
  178. }
  179. if (this.metricService === null) {
  180. return console.trace(`Tried to register a metric without initializing @pm2/io`);
  181. }
  182. return this.metricService.histogram(config);
  183. }
  184. metric(config) {
  185. if (typeof config === 'string') {
  186. config = {
  187. name: config
  188. };
  189. }
  190. if (this.metricService === null) {
  191. return console.trace(`Tried to register a metric without initializing @pm2/io`);
  192. }
  193. return this.metricService.metric(config);
  194. }
  195. gauge(config) {
  196. if (typeof config === 'string') {
  197. config = {
  198. name: config
  199. };
  200. }
  201. if (this.metricService === null) {
  202. return console.trace(`Tried to register a metric without initializing @pm2/io`);
  203. }
  204. return this.metricService.metric(config);
  205. }
  206. counter(config) {
  207. if (typeof config === 'string') {
  208. config = {
  209. name: config
  210. };
  211. }
  212. if (this.metricService === null) {
  213. return console.trace(`Tried to register a metric without initializing @pm2/io`);
  214. }
  215. return this.metricService.counter(config);
  216. }
  217. meter(config) {
  218. if (typeof config === 'string') {
  219. config = {
  220. name: config
  221. };
  222. }
  223. if (this.metricService === null) {
  224. return console.trace(`Tried to register a metric without initializing @pm2/io`);
  225. }
  226. return this.metricService.meter(config);
  227. }
  228. action(name, opts, fn) {
  229. if (typeof name === 'object') {
  230. const tmp = name;
  231. name = tmp.name;
  232. opts = tmp.options;
  233. fn = tmp.action;
  234. }
  235. if (this.actionService === null) {
  236. return console.trace(`Tried to register a action without initializing @pm2/io`);
  237. }
  238. return this.actionService.registerAction(name, opts, fn);
  239. }
  240. onExit(callback) {
  241. if (typeof callback === 'function') {
  242. const onExit = require('signal-exit');
  243. return onExit(callback);
  244. }
  245. }
  246. emit(name, data) {
  247. const events = this.featureManager.get('events');
  248. return events.emit(name, data);
  249. }
  250. getTracer() {
  251. const tracing = this.featureManager.get('tracing');
  252. return tracing.getTracer();
  253. }
  254. initModule(opts, cb) {
  255. if (!opts)
  256. opts = {};
  257. if (opts.reference) {
  258. opts.name = opts.reference;
  259. delete opts.reference;
  260. }
  261. opts = Object.assign({
  262. widget: {}
  263. }, opts);
  264. opts.widget = Object.assign({
  265. type: 'generic',
  266. logo: 'https://app.keymetrics.io/img/logo/keymetrics-300.png',
  267. theme: ['#111111', '#1B2228', '#807C7C', '#807C7C']
  268. }, opts.widget);
  269. opts.isModule = true;
  270. opts = configuration_1.default.init(opts);
  271. return typeof cb === 'function' ? cb(null, opts) : opts;
  272. }
  273. expressErrorHandler() {
  274. const notify = this.featureManager.get('notify');
  275. return notify.expressErrorHandler();
  276. }
  277. koaErrorHandler() {
  278. const notify = this.featureManager.get('notify');
  279. return notify.koaErrorHandler();
  280. }
  281. }
  282. exports.default = PMX;
  283. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG14LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BteC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZLENBQUE7O0FBRVosbURBQTJDO0FBQzNDLGlDQUF5QjtBQUN6QixxREFBaUQ7QUFDakQsb0RBQWtGO0FBQ2xGLHFEQUFpRDtBQUNqRCxnREFBa0Q7QUFFbEQsZ0RBQXdIO0FBUXhILDJDQUE2QztBQUc3QywwREFBNkQ7QUFDN0Qsc0RBQWtEO0FBR2xELE1BQWEsUUFBUTtJQUFyQjtRQUlFLG9CQUFlLEdBQWEsSUFBSSxDQUFBO1FBY2hDLGNBQVMsR0FBK0IsSUFBSSxDQUFBO1FBSTVDLFlBQU8sR0FBNkIsS0FBSyxDQUFBO1FBS3pDLGVBQVUsR0FBYSxLQUFLLENBQUE7SUFLOUIsQ0FBQztDQUFBO0FBaENELDRCQWdDQztBQUVZLFFBQUEsYUFBYSxHQUFhO0lBQ3JDLGVBQWUsRUFBRSxJQUFJO0lBQ3JCLFNBQVMsRUFBRSxJQUFJO0lBQ2YsT0FBTyxFQUFFO1FBQ1AsRUFBRSxFQUFFLElBQUk7UUFDUixPQUFPLEVBQUUsS0FBSztRQUNkLFNBQVMsRUFBRSxJQUFJO1FBQ2YsT0FBTyxFQUFFLElBQUk7UUFDYixJQUFJLEVBQUUsSUFBSTtLQUNYO0lBQ0QsVUFBVSxFQUFFLEtBQUs7SUFDakIsVUFBVSxFQUFFLFNBQVM7SUFDckIsT0FBTyxFQUFFO1FBQ1AsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsS0FBSztLQUNoQjtDQUNGLENBQUE7QUFFRCxNQUFxQixHQUFHO0lBQXhCO1FBR1UsbUJBQWMsR0FBbUIsSUFBSSwrQkFBYyxFQUFFLENBQUE7UUFDckQsY0FBUyxHQUFxQixJQUFJLENBQUE7UUFDbEMsa0JBQWEsR0FBeUIsSUFBSSxDQUFBO1FBQzFDLGtCQUFhLEdBQXlCLElBQUksQ0FBQTtRQUMxQyx3QkFBbUIsR0FBK0IsSUFBSSxDQUFBO1FBQ3RELFdBQU0sR0FBYSxlQUFLLENBQUMsVUFBVSxD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