"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const notify_1 = require("./features/notify"); const metrics_1 = require("./features/metrics"); const actions_1 = require("./features/actions"); const events_1 = require("./features/events"); const merge = require("deepmerge"); const configuration_1 = require("./configuration"); const metricConfig_1 = require("./utils/metricConfig"); const debug_1 = require("debug"); const fs = require("fs"); const cluster = require("cluster"); const serviceManager_1 = require("./serviceManager"); const transport_1 = require("./services/transport"); const debug = debug_1.default('PM2-IO-APM'); class TransactionConfig { } class MetricsConfig { } class ActionsConfig { } class IOConfig { } class PMX { constructor() { this.notifyFeature = new notify_1.NotifyFeature(); this.metricsFeature = new metrics_1.default(); this.actionsFeature = new actions_1.default(!cluster.isWorker); this.eventsFeature = new events_1.default(); const eventLoopInspector = require('event-loop-inspector')(true); serviceManager_1.ServiceManager.set('eventLoopService', { inspector: eventLoopInspector }); serviceManager_1.ServiceManager.set('transport', new transport_1.default()); } getInitialConfig() { return this.initialConfig; } init(config, force) { let notifyOptions = notify_1.NotifyOptionsDefault; let configMetrics = {}; if (!config) { config = new IOConfig(); } if (process.env.PMX_FORCE_UPDATE) { const IO_KEY = Symbol.for('@pm2/io'); const globalSymbols = Object.getOwnPropertySymbols(global); const alreadyInstanciated = (globalSymbols.indexOf(IO_KEY) > -1); if (alreadyInstanciated) { global[IO_KEY].destroy(); } global[IO_KEY] = this; } if (config.level) { notifyOptions.level = config.level; } if (config.catchExceptions) { notifyOptions.catchExceptions = config.catchExceptions; } if (config.metrics) { configMetrics = config.metrics; } ((_) => tslib_1.__awaiter(this, void 0, void 0, function* () { // Transport if (config.standalone && config.publicKey && config.secretKey && config.appName) { yield serviceManager_1.ServiceManager.get('transport').initStandalone({ publicKey: config.publicKey, secretKey: config.secretKey, appName: config.appName, serverName: config.serverName, sendLogs: config.sendLogs }); } else { serviceManager_1.ServiceManager.get('transport').init(); } // Configuration this.backwardConfigConversion(config); this.notifyFeature.init(notifyOptions); this.metricsFeature.init(config.metrics, force); this.actionsFeature.init(config.actions, force); this.actionsFeature.initListener(); configuration_1.default.init(config); this.initialConfig = config; }))(); return this; } destroy() { if (this.metricsFeature) this.metricsFeature.destroy(); if (this.actionsFeature) this.actionsFeature.destroy(); if (this.notifyFeature) this.notifyFeature.destroy(); } notifyError(err, context) { let level = 'info'; if (context && context.level) { level = context.level; } this.notifyFeature.notifyError(err, level); } metrics(metrics) { const res = {}; let allMetrics = []; if (!Array.isArray(metrics)) { allMetrics[0] = metrics; } else { allMetrics = metrics; } for (let i = 0; i < allMetrics.length; i++) { const currentMetric = allMetrics[i]; if (!currentMetric || !currentMetric.hasOwnProperty('name') || !currentMetric.hasOwnProperty('type')) { console.warn(`Metric can't be initialized : missing some properties !`); console.warn('name => required'); console.warn('type => required'); console.warn('id => optional'); console.warn('unit => optional'); console.warn('value => optional'); console.warn('historic => optional'); console.warn('agg_type => optional'); console.warn('measurement => optional'); continue; } // escape spaces and special characters from metric's name const metricKey = currentMetric.name.replace(/ /g, '_').replace(/[^\w\s]/gi, ''); const type = currentMetric.type; currentMetric.type = currentMetric.id; delete currentMetric.id; if (typeof this.metricsFeature[type] !== 'function') { console.warn(`Metric ${currentMetric.name} cant be initialized : unknown type ${type} !`); continue; } res[metricKey] = this.metricsFeature[type](currentMetric); } return res; } histogram(config) { config = metricConfig_1.default.buildConfig(config); return this.metricsFeature['histogram'](config); } metric(config) { config = metricConfig_1.default.buildConfig(config); return this.metricsFeature['metric'](config); } counter(config) { config = metricConfig_1.default.buildConfig(config); return this.metricsFeature['counter'](config); } meter(config) { config = metricConfig_1.default.buildConfig(config); return this.metricsFeature['meter'](config); } action(name, opts, fn) { if (typeof name === 'object') { opts = name.opts; fn = name.action; name = name.name; } this.actionsFeature.action(name, opts, fn); // Only listen if transporter wasn't initiated (no pmx.init()) if (!serviceManager_1.ServiceManager.get('transport').initiated) { this.actionsFeature.initListener(); } } scopedAction(name, fn) { this.actionsFeature.scopedAction(name, fn); // Only listen if transporter wasn't initiated (no pmx.init()) if (!serviceManager_1.ServiceManager.get('transport').initiated) { this.actionsFeature.initListener(); } } transpose(variableName, reporter) { this.metricsFeature.transpose(variableName, reporter); } onExit(callback) { if (callback && typeof callback === 'function') { const onExit = require('signal-exit'); return onExit(callback); } } // ----------------------------------------------------------- // Retro compatibility // ----------------------------------------------------------- probe() { return { histogram: (histogram) => { return this.genericBackwardConversion(histogram, 'histogram'); }, meter: (meter) => { return this.genericBackwardConversion(meter, 'meter'); }, metric: (metric) => { return this.genericBackwardConversion(metric, 'metric'); }, counter: (counter) => { return this.genericBackwardConversion(counter, 'counter'); }, transpose: (variableName, reporter) => { this.transpose(variableName, reporter); } }; } emit(name, data) { this.eventsFeature.emit(name, data); } emitEvent(name, data) { this.eventsFeature.emit(name, data); } notify(notification) { if (!(notification instanceof Error)) { notification = new Error(notification); } this.notifyFeature.notifyError(notification); } getPID(file) { if (typeof (file) === 'number') return file; return parseInt(fs.readFileSync(file).toString(), 10); } initModule(opts, cb) { if (!opts) opts = {}; if (opts.reference) { opts.name = opts.reference; delete opts.reference; } opts = merge({ widget: {} }, opts); opts.widget = merge({ type: 'generic', logo: 'https://app.keymetrics.io/img/logo/keymetrics-300.png', theme: ['#111111', '#1B2228', '#807C7C', '#807C7C'] }, opts.widget); opts.isModule = true; opts = configuration_1.default.init(opts); if (cb && typeof (cb) === 'function') return cb(null, opts); return opts; } expressErrorHandler() { return this.notifyFeature.expressErrorHandler(); } genericBackwardConversion(object, type) { if (typeof object !== 'object') { console.error('Parameter should be an object'); return null; } object.type = type; // escape spaces and special characters from metric's name const metricKey = object.name.replace(/ /g, '_').replace(/[^\w\s]/gi, ''); return this.metrics(object)[metricKey]; } backwardConfigConversion(config) { // ------------------------------------------ // Network // ------------------------------------------ if (config.hasOwnProperty('network') || config.hasOwnProperty('ports')) { const networkConf = {}; if (config.hasOwnProperty('network')) { networkConf.traffic = Boolean(config.network); delete config.network; } if (config.hasOwnProperty('ports')) { networkConf.ports = Boolean(config.ports); delete config.ports; } this.initMetricsConf(config); config.metrics.network = networkConf; } // ------------------------------------------ // V8 // ------------------------------------------ if (config.hasOwnProperty('v8')) { this.initMetricsConf(config); config.metrics.v8 = config.v8; delete config.v8; } // ------------------------------------------ // transactions // ------------------------------------------ if (config.hasOwnProperty('transactions') || config.hasOwnProperty('http')) { this.initMetricsConf(config); config.metrics.transaction = new TransactionConfig(); if (config.hasOwnProperty('transactions')) { config.metrics.transaction.tracing = config.transactions; delete config.transactions; } if (config.hasOwnProperty('http')) { config.metrics.transaction.http = config.http; delete config.http; } } // ------------------------------------------ // Deep metrics // ------------------------------------------ if (config.hasOwnProperty('deep_metrics')) { this.initMetricsConf(config); config.metrics.deepMetrics = config.deep_metrics; delete config.deep_metrics; } // ------------------------------------------ // Event Loop action // ------------------------------------------ if (config.hasOwnProperty('event_loop_dump')) { this.initActionsConf(config); config.actions.eventLoopDump = config.event_loop_dump; delete config.event_loop_dump; } // ------------------------------------------ // Profiling action // ------------------------------------------ if (config.hasOwnProperty('profiling')) { this.initActionsConf(config); config.actions.profilingHeap = config.profiling; config.actions.profilingHeap = config.profiling; delete config.profiling; } } initMetricsConf(config) { if (!config.metrics) { config.metrics = new MetricsConfig(); } } initActionsConf(config) { if (!config.actions) { config.actions = new ActionsConfig(); } } } exports.default = PMX; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG14LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3BteC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw4Q0FBc0Y7QUFDdEYsZ0RBQStDO0FBQy9DLGdEQUErQztBQUMvQyw4Q0FBNEM7QUFDNUMsbUNBQWtDO0FBQ2xDLG1EQUEyQztBQUMzQyx1REFBOEM7QUFDOUMsaUNBQXlCO0FBQ3pCLHlCQUF3QjtBQUN4QixtQ0FBa0M7QUFDbEMscURBQWlEO0FBRWpELG9EQUFtRDtBQUVuRCxNQUFNLEtBQUssR0FBRyxlQUFLLENBQUMsWUFBWSxDQUFDLENBQUE7QUFFakM7Q0FHQztBQUVEO0NBS0M7QUFFRDtDQUlDO0FBRUQ7Q0FtQkM7QUFpQkQ7SUFTRTtRQUNFLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxzQkFBYSxFQUFFLENBQUE7UUFDeEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLGlCQUFjLEVBQUUsQ0FBQTtRQUMxQyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksaUJBQWMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUMzRCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksZ0JBQVksRUFBRSxDQUFBO1FBRXZDLE1BQU0sa0JBQWtCLEdBQUcsT0FBTyxDQUFDLHNCQUFzQixDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDaEUsK0JBQWMsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLEVBQUU7WUFDckMsU0FBUyxFQUFFLGtCQUFrQjtTQUM5QixDQUFDLENBQUE7UUFDRiwrQkFBYyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsSUFBSSxtQkFBZ0IsRUFBRSxDQUFDLENBQUE7SUFDekQsQ0FBQztJQUVELGdCQUFnQjtRQUNkLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQTtJQUMzQixDQUFDO0lBRUQsSUFBSSxDQUFFLE1BQWlCLEVBQUUsS0FBZTtRQUN0QyxJQUFJLGFBQWEsR0FBa0IsNkJBQW9C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