rittenhop-dev/versions/5.94.2/node_modules/@tryghost/metrics/lib/GhostMetrics.js

121 lines
4.0 KiB
JavaScript
Raw Normal View History

2024-09-23 19:40:12 -04:00
const jsonStringifySafe = require('json-stringify-safe');
/**
* @description Metric shipper class built on the loggingrc config used in Ghost projects
*/
class GhostMetrics {
/**
* Properties in the options bag:
*
* domain: Metadata for metrics in shared databases.
* mode: Is used to print short or long log - used for stdout shipper.
* metrics.transports: An array of transports for metric shipping (e.g. ['stdout', 'elasticsearch'])
* metrics.metadata: A property bag of metadata values to be shipped alongside the metric value
* elasticsearch: Elasticsearch transport configuration
* @param {object} options Bag of options
*/
constructor(options) {
options = options || {};
this.domain = options.domain || 'localhost';
this.elasticsearch = options.elasticsearch || {};
this.mode = process.env.MODE || options.mode || 'short';
if ('metrics' in options && typeof options.metrics === 'object') {
this.transports = options.metrics.transports || [];
this.metadata = options.metrics.metadata || {};
} else {
this.transports = [];
this.metadata = {};
}
// CASE: special env variable to enable long mode and level info
if (process.env.LOIN) {
this.mode = 'long';
}
this.shippers = {};
this.transports.forEach((transport) => {
let transportFn = `setup${transport[0].toUpperCase()}${transport.substr(1)}Shipper`;
if (!this[transportFn]) {
throw new Error(`${transport} is an invalid transport`); // eslint-disable-line
}
this[transportFn]();
});
}
/**
* @description Setup stdout stream.
*/
setupStdoutShipper() {
const GhostPrettyStream = require('@tryghost/pretty-stream');
const prettyStdOut = new GhostPrettyStream({
mode: this.mode
});
prettyStdOut.pipe(process.stdout);
this.shippers.stdout = (name, value) => {
prettyStdOut.write({
msg: `Metric ${name}: ${jsonStringifySafe(value)}`,
level: 30 // Magic number, log level for info
});
return Promise.resolve();
};
}
/**
* @description Setup ElasticSearch metric shipper
* ElasticSearch metrics are shipped to an index individually for each metric.
* The name of the index is the name of the metric prefixed with "metrics-", the metric name itself should be sluggified
*/
setupElasticsearchShipper() {
const ElasticSearch = require('@tryghost/elasticsearch');
const elasticSearch = new ElasticSearch({
node: this.elasticsearch.host,
auth: {
username: this.elasticsearch.username,
password: this.elasticsearch.password
},
requestTimeout: 5000,
proxy: 'proxy' in this.elasticsearch ? this.elasticsearch.proxy : null
});
this.shippers.elasticsearch = (name, value) => {
if (typeof value !== 'object') {
value = {value};
}
if (!('@timestamp' in value)) {
value['@timestamp'] = Date.now();
}
if (this.metadata) {
value.metadata = this.metadata;
}
return elasticSearch.index(value, `metrics-${name}`);
};
}
/**
* @description Metric shipper function
* @param {string} name Name of the metric, should be slugified for increased back-end compatibility (e.g. "memory-usage")
* @param {any} value Value of metric, will be co-erced to an object before being shipped
*/
metric(name, value) {
const promises = [];
for (const metricShipper of Object.values(this.shippers)) {
promises.push(metricShipper(name, value));
}
return Promise.allSettled(promises).then(() => null);
}
}
module.exports = GhostMetrics;