184 lines
6.2 KiB
JavaScript
184 lines
6.2 KiB
JavaScript
'use strict';
|
|
const path = require('path');
|
|
const isEmpty = require('lodash.isempty');
|
|
const GraphiteSender = require('./graphite-sender');
|
|
const StatsDSender = require('./statsd-sender');
|
|
const merge = require('lodash.merge');
|
|
const get = require('lodash.get');
|
|
const log = require('intel').getLogger('sitespeedio.plugin.graphite');
|
|
const sendAnnotations = require('./send-annotation');
|
|
const DataGenerator = require('./data-generator');
|
|
const graphiteUtil = require('../../support/tsdbUtil');
|
|
const isStatsd = require('./helpers/is-statsd');
|
|
const throwIfMissing = require('../../support/util').throwIfMissing;
|
|
const cliUtil = require('../../cli/util');
|
|
|
|
module.exports = {
|
|
name() {
|
|
return path.basename(__dirname);
|
|
},
|
|
|
|
/**
|
|
* Define `yargs` options with their respective default values. When displayed by the CLI help message
|
|
* all options are namespaced by its plugin name.
|
|
*
|
|
* @return {Object<string, require('yargs').Options} an object mapping the name of the option and its yargs configuration
|
|
*/
|
|
get cliOptions() {
|
|
return require(path.resolve(__dirname, 'cli.js'));
|
|
},
|
|
|
|
open(context, options) {
|
|
throwIfMissing(options.graphite, ['host'], 'graphite');
|
|
const opts = merge({}, this.config, options.graphite);
|
|
this.options = options;
|
|
this.perIteration = get(opts, 'perIteration', false);
|
|
const SenderConstructor = isStatsd(opts) ? StatsDSender : GraphiteSender;
|
|
|
|
this.filterRegistry = context.filterRegistry;
|
|
this.sender = new SenderConstructor(opts.host, opts.port, opts.bulkSize);
|
|
this.dataGenerator = new DataGenerator(
|
|
opts.namespace,
|
|
opts.includeQueryParams,
|
|
options
|
|
);
|
|
log.debug(
|
|
'Setting up Graphite %s:%s for namespace %s',
|
|
opts.host,
|
|
opts.port,
|
|
opts.namespace
|
|
);
|
|
this.timestamp = context.timestamp;
|
|
this.resultUrls = context.resultUrls;
|
|
this.messageTypesToFireAnnotations = [];
|
|
this.receivedTypesThatFireAnnotations = {};
|
|
this.make = context.messageMaker('graphite').make;
|
|
this.sendAnnotation = true;
|
|
this.alias = {};
|
|
this.wptExtras = {};
|
|
this.usingBrowsertime = false;
|
|
},
|
|
|
|
processMessage(message, queue) {
|
|
// First catch if we are running Browsertime and/or WebPageTest
|
|
if (message.type === 'browsertime.setup') {
|
|
this.messageTypesToFireAnnotations.push('browsertime.pageSummary');
|
|
this.usingBrowsertime = true;
|
|
} else if (message.type === 'webpagetest.setup') {
|
|
this.messageTypesToFireAnnotations.push('webpagetest.pageSummary');
|
|
} else if (message.type === 'browsertime.config') {
|
|
if (message.data.screenshot) {
|
|
this.useScreenshots = message.data.screenshot;
|
|
this.screenshotType = message.data.screenshotType;
|
|
}
|
|
} else if (message.type === 'sitespeedio.setup') {
|
|
// Let other plugins know that the Graphite plugin is alive
|
|
queue.postMessage(this.make('graphite.setup'));
|
|
} else if (message.type === 'grafana.setup') {
|
|
this.sendAnnotation = false;
|
|
} else if (message.type === 'browsertime.browser') {
|
|
this.browser = message.data.browser;
|
|
} else if (
|
|
message.type === 'webpagetest.browser' &&
|
|
!this.usingBrowsertime
|
|
) {
|
|
// We are only interested in WebPageTest browser if we run it standalone
|
|
this.browser = message.data.browser;
|
|
}
|
|
|
|
if (message.type === 'browsertime.alias') {
|
|
this.alias[message.url] = message.data;
|
|
}
|
|
|
|
const filterRegistry = this.filterRegistry;
|
|
if (
|
|
!(
|
|
message.type.endsWith('.summary') ||
|
|
message.type.endsWith('.pageSummary') ||
|
|
(this.perIteration && message.type.endsWith('.run'))
|
|
)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
if (this.messageTypesToFireAnnotations.includes(message.type)) {
|
|
this.receivedTypesThatFireAnnotations[message.url]
|
|
? this.receivedTypesThatFireAnnotations[message.url]++
|
|
: (this.receivedTypesThatFireAnnotations[message.url] = 1);
|
|
}
|
|
|
|
if (message.type === 'webpagetest.pageSummary') {
|
|
this.wptExtras[message.url] = {};
|
|
this.wptExtras[message.url].webPageTestResultURL =
|
|
message.data.data.summary;
|
|
this.wptExtras[message.url].connectivity = message.connectivity;
|
|
this.wptExtras[message.url].location = graphiteUtil.toSafeKey(
|
|
message.location
|
|
);
|
|
}
|
|
|
|
// we only sends individual groups to Graphite, not the
|
|
// total of all groups (you can calculate that yourself)
|
|
if (message.group === 'total') {
|
|
return;
|
|
}
|
|
message = filterRegistry.filterMessage(message);
|
|
if (isEmpty(message.data)) return;
|
|
|
|
// TODO Here we could add logic to either create a new timestamp or
|
|
// use the one that we have for that run. Now just use the one for the
|
|
// run
|
|
const dataPoints = this.dataGenerator.dataFromMessage(
|
|
message,
|
|
this.timestamp,
|
|
this.alias
|
|
);
|
|
|
|
if (dataPoints.length > 0) {
|
|
const data = dataPoints.join('\n') + '\n';
|
|
return this.sender.send(data).then(() => {
|
|
// Make sure we only send the annotation once per URL:
|
|
// If we run browsertime, always send on browsertime.pageSummary
|
|
// If we run WebPageTest standalone, send on webPageTestSummary
|
|
// when we configured a base url
|
|
|
|
if (
|
|
this.receivedTypesThatFireAnnotations[message.url] ===
|
|
this.messageTypesToFireAnnotations.length &&
|
|
this.resultUrls.hasBaseUrl() &&
|
|
this.sendAnnotation
|
|
) {
|
|
this.receivedTypesThatFireAnnotations[message.url] = 0;
|
|
const absolutePagePath = this.resultUrls.absoluteSummaryPagePath(
|
|
message.url
|
|
);
|
|
return sendAnnotations.send(
|
|
message.url,
|
|
message.group,
|
|
absolutePagePath,
|
|
this.useScreenshots,
|
|
this.screenshotType,
|
|
this.timestamp,
|
|
this.alias,
|
|
this.wptExtras[message.url],
|
|
this.usingBrowsertime,
|
|
this.browser,
|
|
this.options
|
|
);
|
|
}
|
|
});
|
|
} else {
|
|
return Promise.reject(
|
|
new Error(
|
|
'No data to send to graphite for message:\n' +
|
|
JSON.stringify(message, null, 2)
|
|
)
|
|
);
|
|
}
|
|
},
|
|
|
|
get config() {
|
|
return cliUtil.pluginDefaults(this.cliOptions);
|
|
}
|
|
};
|