148 lines
3.9 KiB
JavaScript
148 lines
3.9 KiB
JavaScript
'use strict';
|
|
|
|
const urlParser = require('url');
|
|
const log = require('intel');
|
|
|
|
function joinNonEmpty(strings, delimeter) {
|
|
return strings.filter(Boolean).join(delimeter);
|
|
}
|
|
|
|
function toSafeKey(key) {
|
|
return key.replace(/[.~ /+|,:?&%)(]|%7C/g, '_');
|
|
}
|
|
|
|
module.exports = {
|
|
keypathFromUrl(url, includeQueryParams, useHash) {
|
|
function flattenQueryParams(params) {
|
|
return Object.keys(params).reduce(
|
|
(result, key) => joinNonEmpty([result, key, params[key]], '_'),
|
|
''
|
|
);
|
|
}
|
|
|
|
url = urlParser.parse(url, !!includeQueryParams);
|
|
|
|
let path = toSafeKey(url.pathname);
|
|
|
|
if (includeQueryParams) {
|
|
path = joinNonEmpty(
|
|
[path, toSafeKey(flattenQueryParams(url.query))],
|
|
'_'
|
|
);
|
|
}
|
|
if (useHash && url.hash) {
|
|
path = joinNonEmpty([path, toSafeKey(url.hash)], '_');
|
|
}
|
|
|
|
const keys = [toSafeKey(url.hostname), path];
|
|
|
|
return joinNonEmpty(keys, '.');
|
|
},
|
|
|
|
flattenMessageData({ data, type }) {
|
|
function isNumericString(n) {
|
|
return !isNaN(parseFloat(n)) && isFinite(n);
|
|
}
|
|
|
|
function recursiveFlatten(target, keyPrefix, value) {
|
|
// super simple version to avoid flatten HAR and screenshot data
|
|
if (keyPrefix.match(/(screenshots\.|har\.)/)) {
|
|
return;
|
|
}
|
|
|
|
// Google is overloading User Timing marks
|
|
// See https://github.com/sitespeedio/browsertime/issues/257
|
|
if (keyPrefix.indexOf('userTimings.marks.goog_') > -1) {
|
|
return;
|
|
}
|
|
|
|
// Google is overloading User Timing marks = the same using WebPageTest
|
|
// See https://github.com/sitespeedio/browsertime/issues/257
|
|
if (keyPrefix.indexOf('userTimes.goog_') > -1) {
|
|
return;
|
|
}
|
|
|
|
const valueType = typeof value;
|
|
|
|
switch (valueType) {
|
|
case 'number':
|
|
{
|
|
if (isFinite(value)) {
|
|
target[keyPrefix] = value;
|
|
} else {
|
|
log.warn(
|
|
`Non-finite number '${value}' found at path '${keyPrefix}' for '${type}' message (url = ${
|
|
data.url
|
|
})`
|
|
);
|
|
}
|
|
}
|
|
break;
|
|
case 'object':
|
|
{
|
|
if (value === null) {
|
|
break;
|
|
}
|
|
|
|
Object.keys(value).forEach(key => {
|
|
// Hey are you coming to the future from 1980s? Please don't
|
|
// look at this code, it's a ugly hack to make sure we can send assets
|
|
// to Graphite and don't send them with array position, instead
|
|
// use the url to generate the key
|
|
|
|
if (type === 'pagexray.pageSummary' && keyPrefix === 'assets') {
|
|
recursiveFlatten(
|
|
target,
|
|
joinNonEmpty(
|
|
[keyPrefix, toSafeKey(value[key].url || key)],
|
|
'.'
|
|
),
|
|
value[key]
|
|
);
|
|
} else {
|
|
recursiveFlatten(
|
|
target,
|
|
joinNonEmpty([keyPrefix, toSafeKey(key)], '.'),
|
|
value[key]
|
|
);
|
|
}
|
|
});
|
|
}
|
|
break;
|
|
case 'string':
|
|
{
|
|
if (isNumericString(value)) {
|
|
target[keyPrefix] = parseFloat(value);
|
|
}
|
|
}
|
|
break;
|
|
case 'boolean':
|
|
{
|
|
target[keyPrefix] = value ? 1 : 0;
|
|
}
|
|
break;
|
|
case 'undefined':
|
|
{
|
|
log.debug(
|
|
`Undefined value found at path '${keyPrefix}' for '${type}' message (url = ${
|
|
data.url
|
|
})`
|
|
);
|
|
}
|
|
break;
|
|
default:
|
|
throw new Error(
|
|
'Unhandled value type ' +
|
|
valueType +
|
|
' found when flattening data for prefix ' +
|
|
keyPrefix
|
|
);
|
|
}
|
|
}
|
|
|
|
let retVal = {};
|
|
recursiveFlatten(retVal, '', data);
|
|
return retVal;
|
|
}
|
|
};
|