зеркало из https://github.com/mozilla/workshop.git
136 строки
4.8 KiB
JavaScript
136 строки
4.8 KiB
JavaScript
const request = require('request');
|
|
const decimal = require('decimal');
|
|
|
|
|
|
module.exports = (flatURL, cb) => {
|
|
request(flatURL, (error, response, body) => {
|
|
if (error) {
|
|
return cb('Cannot fetch ' + flatURL);
|
|
}
|
|
|
|
const flatData = JSON.parse(body);
|
|
cb(null, modifyPopulations(format(flatData)));
|
|
});
|
|
}
|
|
|
|
function format(flatData) {
|
|
const output = {
|
|
'default': [],
|
|
};
|
|
|
|
flatData.forEach((day, index) => {
|
|
const metrics = {};
|
|
const entry = { metrics };
|
|
|
|
Object.keys(day).forEach(key => {
|
|
const value = flatData[index][key];
|
|
const split = key.split(/_(.+)/);
|
|
|
|
// Preserve the date property
|
|
if (key === 'date') {
|
|
entry[key] = value;
|
|
|
|
// Ignore "inactive" and "broken", which we don't use
|
|
} else if (key === 'inactive' || key === 'broken') {
|
|
return;
|
|
|
|
// Use everything else
|
|
} else {
|
|
let newMetricName = split[0];
|
|
|
|
// These aren't used
|
|
if (newMetricName === 'cpuCoresSpeed') {
|
|
return;
|
|
}
|
|
|
|
// Fix some metric names
|
|
if (newMetricName === 'has') {
|
|
newMetricName = 'hasUnity';
|
|
}
|
|
|
|
let bucketName = split[1];
|
|
|
|
// Fix some bucket names
|
|
if (bucketName === 'unity_True') {
|
|
bucketName = 'True';
|
|
} else if (bucketName === 'unity_False') {
|
|
bucketName = 'False';
|
|
}
|
|
|
|
if (metrics[newMetricName] === undefined) {
|
|
metrics[newMetricName] = {};
|
|
}
|
|
|
|
// Avoid artifacts from floating point arithmetic when multiplying by 100
|
|
metrics[newMetricName][bucketName] = decimal(value).mul(100).toNumber();
|
|
}
|
|
});
|
|
|
|
output.default.push(entry);
|
|
});
|
|
|
|
return output;
|
|
}
|
|
|
|
function modifyPopulations(data) {
|
|
const populationModifications = require('./population-modifications.json');
|
|
|
|
// For each entry in the formatted data
|
|
data.default.forEach(entry => {
|
|
|
|
// For each metric NAME in that entry
|
|
Object.keys(entry.metrics).forEach(metricName => {
|
|
if (metricName in populationModifications) {
|
|
|
|
// Process removals
|
|
if (populationModifications[metricName].removals) {
|
|
populationModifications[metricName].removals.forEach(populationToBeRemoved => {
|
|
delete entry.metrics[metricName][populationToBeRemoved];
|
|
});
|
|
}
|
|
|
|
// Process renames
|
|
if (populationModifications[metricName].renames) {
|
|
populationModifications[metricName].renames.forEach(renameMeta => {
|
|
entry.metrics[metricName][renameMeta.to] = entry.metrics[metricName][renameMeta.from];
|
|
delete entry.metrics[metricName][renameMeta.from];
|
|
});
|
|
}
|
|
|
|
// Process replacement groups
|
|
if (populationModifications[metricName].replacementGroups) {
|
|
populationModifications[metricName].replacementGroups.forEach(rg => {
|
|
let combinedPopulationsValue = 0;
|
|
let processedAtLeastOneMember = false;
|
|
|
|
rg.members.forEach(populationToSubsume => {
|
|
if (populationToSubsume in entry.metrics[metricName]) {
|
|
processedAtLeastOneMember = true;
|
|
combinedPopulationsValue = decimal(combinedPopulationsValue).add(entry.metrics[metricName][populationToSubsume]).toNumber();
|
|
delete entry.metrics[metricName][populationToSubsume];
|
|
}
|
|
});
|
|
|
|
if (processedAtLeastOneMember) {
|
|
entry.metrics[metricName][rg.name] = combinedPopulationsValue;
|
|
}
|
|
});
|
|
} // if (populationModifications[metricName].replacementGroups) {
|
|
|
|
// If there's only one population, make the value of that
|
|
// population the value of the metric.
|
|
// https://github.com/mozilla/workshop/issues/10
|
|
if (typeof entry.metrics[metricName] === 'object' && Object.keys(entry.metrics[metricName]).length === 1) {
|
|
const value = entry.metrics[metricName][Object.keys(entry.metrics[metricName])[0]];
|
|
entry.metrics[metricName] = value;
|
|
}
|
|
|
|
} // if (metricName in populationModifications)
|
|
|
|
}); // For each metric NAME in that entry
|
|
|
|
}); // For each entry
|
|
|
|
return data;
|
|
}
|