127 lines
3.8 KiB
JavaScript
127 lines
3.8 KiB
JavaScript
import util, { format } from 'node:util';
|
|
import reduce from 'lodash.reduce';
|
|
import {
|
|
getConnectivity,
|
|
toSafeKey,
|
|
getURLAndGroup
|
|
} from '../../support/tsdbUtil.js';
|
|
import { flattenMessageData } from '../../support/flattenMessage.js';
|
|
import { formatEntry } from './helpers/format-entry.js';
|
|
import { isStatsD } from './helpers/is-statsd.js';
|
|
|
|
const STATSD = 'statsd';
|
|
const GRAPHITE = 'graphite';
|
|
|
|
function keyPathFromMessage(message, options, includeQueryParameters, alias) {
|
|
let typeParts = message.type.split('.');
|
|
typeParts.push(typeParts.shift());
|
|
|
|
// always have browser and connectivity in Browsertime and related tools
|
|
if (
|
|
/(^pagexray|^coach|^browsertime|^largestassets|^slowestassets|^aggregateassets|^domains|^thirdparty|^axe|^sustainable)/.test(
|
|
message.type
|
|
)
|
|
) {
|
|
// if we have a friendly name for your connectivity, use that!
|
|
let connectivity = getConnectivity(options);
|
|
|
|
typeParts.splice(1, 0, connectivity);
|
|
typeParts.splice(1, 0, options.browser);
|
|
} else if (/(^webpagetest)/.test(message.type)) {
|
|
if (message.connectivity) {
|
|
typeParts.splice(2, 0, message.connectivity);
|
|
}
|
|
if (message.location) {
|
|
typeParts.splice(2, 0, toSafeKey(message.location));
|
|
}
|
|
} else if (/(^gpsi)/.test(message.type)) {
|
|
typeParts.splice(2, 0, options.mobile ? 'mobile' : 'desktop');
|
|
}
|
|
|
|
// if we get a URL type, add the URL
|
|
if (message.url) {
|
|
typeParts.splice(
|
|
1,
|
|
0,
|
|
getURLAndGroup(
|
|
options,
|
|
message.group,
|
|
message.url,
|
|
includeQueryParameters,
|
|
alias
|
|
)
|
|
);
|
|
} else if (message.group) {
|
|
// add the group of the summary message
|
|
typeParts.splice(1, 0, toSafeKey(message.group));
|
|
}
|
|
|
|
if (options.graphite && options.graphite.addSlugToKey) {
|
|
typeParts.unshift(options.slug);
|
|
}
|
|
|
|
return typeParts.join('.');
|
|
}
|
|
export class GraphiteDataGenerator {
|
|
constructor(namespace, includeQueryParameters, options) {
|
|
this.namespace = namespace;
|
|
this.includeQueryParams = !!includeQueryParameters;
|
|
this.options = options;
|
|
this.entryFormat = isStatsD(options.graphite) ? STATSD : GRAPHITE;
|
|
}
|
|
|
|
dataFromMessage(message, time, alias) {
|
|
let timestamp = Math.round(time.valueOf() / 1000);
|
|
|
|
const keypath = keyPathFromMessage(
|
|
message,
|
|
this.options,
|
|
this.includeQueryParams,
|
|
alias
|
|
);
|
|
|
|
return reduce(
|
|
flattenMessageData(message),
|
|
(entries, value, key) => {
|
|
if (message.type === 'browsertime.run') {
|
|
if (key.includes('timings') && key.includes('marks')) {
|
|
key = key.replace(/marks\.(\d+)/, function (match, index) {
|
|
return (
|
|
'marks.' + message.data.timings.userTimings.marks[index].name
|
|
);
|
|
});
|
|
}
|
|
|
|
if (key.includes('timings') && key.includes('measures')) {
|
|
key = key.replace(/measures\.(\d+)/, function (match, index) {
|
|
return (
|
|
'measures.' +
|
|
message.data.timings.userTimings.measures[index].name
|
|
);
|
|
});
|
|
}
|
|
}
|
|
if (message.type === 'pagexray.run' && key.includes('assets')) {
|
|
key = key.replace(
|
|
/assets\.(\d+)/,
|
|
function (match, index) {
|
|
let url = new URL(message.data.assets[index].url);
|
|
url.search = '';
|
|
return 'assets.' + toSafeKey(url.toString());
|
|
},
|
|
{}
|
|
);
|
|
}
|
|
|
|
const fullKey = format('%s.%s.%s', this.namespace, keypath, key);
|
|
const arguments_ = [formatEntry(this.entryFormat), fullKey, value];
|
|
this.entryFormat === GRAPHITE && arguments_.push(timestamp);
|
|
|
|
entries.push(format.apply(util, arguments_));
|
|
return entries;
|
|
},
|
|
[]
|
|
);
|
|
}
|
|
}
|