2018-12-17 17:38:05 +00:00
|
|
|
const db = require('./utils/data');
|
2018-04-04 05:32:32 +00:00
|
|
|
|
2018-12-17 17:38:05 +00:00
|
|
|
const CloudflareAPI = require('./CloudflareAPI');
|
|
|
|
const BlacklistAPI = require('./BlacklistAPI');
|
2017-08-22 16:12:57 +00:00
|
|
|
|
|
|
|
function prunePackages(packagesMap) {
|
2017-11-11 20:18:13 +00:00
|
|
|
return Promise.all(
|
|
|
|
Object.keys(packagesMap).map(packageName =>
|
2017-11-12 06:35:30 +00:00
|
|
|
BlacklistAPI.includesPackage(packageName).then(blacklisted => {
|
2017-11-11 20:18:13 +00:00
|
|
|
if (blacklisted) {
|
2018-02-18 02:00:56 +00:00
|
|
|
delete packagesMap[packageName];
|
2017-11-11 20:18:13 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
2018-02-18 02:00:56 +00:00
|
|
|
).then(() => packagesMap);
|
2017-08-22 16:12:57 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 15:31:33 +00:00
|
|
|
function createDayKey(date) {
|
2018-02-18 02:00:56 +00:00
|
|
|
return `${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`;
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-25 23:37:54 +00:00
|
|
|
|
2017-08-22 15:31:33 +00:00
|
|
|
function createHourKey(date) {
|
2018-02-18 02:00:56 +00:00
|
|
|
return `${createDayKey(date)}-${date.getUTCHours()}`;
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-25 23:37:54 +00:00
|
|
|
|
2017-08-22 15:31:33 +00:00
|
|
|
function createMinuteKey(date) {
|
2018-02-18 02:00:56 +00:00
|
|
|
return `${createHourKey(date)}-${date.getUTCMinutes()}`;
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-25 23:37:54 +00:00
|
|
|
|
2017-08-16 18:58:01 +00:00
|
|
|
function createScoresMap(array) {
|
2018-02-18 02:00:56 +00:00
|
|
|
const map = {};
|
2017-05-25 23:37:54 +00:00
|
|
|
|
2017-11-08 18:14:46 +00:00
|
|
|
for (let i = 0; i < array.length; i += 2) {
|
2018-02-18 02:00:56 +00:00
|
|
|
map[array[i]] = parseInt(array[i + 1], 10);
|
2017-11-08 18:14:46 +00:00
|
|
|
}
|
2017-05-25 23:37:54 +00:00
|
|
|
|
2018-02-18 02:00:56 +00:00
|
|
|
return map;
|
2017-05-25 23:37:54 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 15:31:33 +00:00
|
|
|
function getScoresMap(key, n = 100) {
|
2017-11-08 18:14:46 +00:00
|
|
|
return new Promise((resolve, reject) => {
|
2018-12-17 17:38:05 +00:00
|
|
|
db.zrevrange(key, 0, n, 'withscores', (error, value) => {
|
2017-05-25 23:37:54 +00:00
|
|
|
if (error) {
|
2018-02-18 02:00:56 +00:00
|
|
|
reject(error);
|
2017-05-25 23:37:54 +00:00
|
|
|
} else {
|
2018-02-18 02:00:56 +00:00
|
|
|
resolve(createScoresMap(value));
|
2017-05-25 23:37:54 +00:00
|
|
|
}
|
2018-02-18 02:00:56 +00:00
|
|
|
});
|
|
|
|
});
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-25 23:37:54 +00:00
|
|
|
|
2017-08-22 15:31:33 +00:00
|
|
|
function getPackageRequests(date, n = 100) {
|
2018-02-18 02:00:56 +00:00
|
|
|
return getScoresMap(`stats-packageRequests-${createDayKey(date)}`, n).then(
|
|
|
|
prunePackages
|
|
|
|
);
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-30 16:20:45 +00:00
|
|
|
|
2017-08-22 15:31:33 +00:00
|
|
|
function getPackageBandwidth(date, n = 100) {
|
2018-02-18 02:00:56 +00:00
|
|
|
return getScoresMap(`stats-packageBytes-${createDayKey(date)}`, n).then(
|
|
|
|
prunePackages
|
|
|
|
);
|
2017-08-22 15:31:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getProtocolRequests(date) {
|
2018-02-18 02:00:56 +00:00
|
|
|
return getScoresMap(`stats-protocolRequests-${createDayKey(date)}`);
|
2017-08-22 15:31:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function addDailyMetricsToTimeseries(timeseries) {
|
2018-02-18 02:00:56 +00:00
|
|
|
const since = new Date(timeseries.since);
|
2017-08-22 15:31:33 +00:00
|
|
|
|
|
|
|
return Promise.all([
|
|
|
|
getPackageRequests(since),
|
|
|
|
getPackageBandwidth(since),
|
|
|
|
getProtocolRequests(since)
|
2017-11-08 18:14:46 +00:00
|
|
|
]).then(results => {
|
2018-02-18 02:00:56 +00:00
|
|
|
timeseries.requests.package = results[0];
|
|
|
|
timeseries.bandwidth.package = results[1];
|
|
|
|
timeseries.requests.protocol = results[2];
|
|
|
|
return timeseries;
|
|
|
|
});
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-30 16:20:45 +00:00
|
|
|
|
2017-08-16 18:58:01 +00:00
|
|
|
function sumMaps(maps) {
|
2017-11-08 18:14:46 +00:00
|
|
|
return maps.reduce((memo, map) => {
|
|
|
|
Object.keys(map).forEach(key => {
|
2018-02-18 02:00:56 +00:00
|
|
|
memo[key] = (memo[key] || 0) + map[key];
|
|
|
|
});
|
2017-05-30 16:20:45 +00:00
|
|
|
|
2018-02-18 02:00:56 +00:00
|
|
|
return memo;
|
|
|
|
}, {});
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-30 16:20:45 +00:00
|
|
|
|
2017-08-22 15:31:33 +00:00
|
|
|
function addDailyMetrics(result) {
|
2018-02-18 02:00:56 +00:00
|
|
|
return Promise.all(result.timeseries.map(addDailyMetricsToTimeseries)).then(
|
|
|
|
() => {
|
|
|
|
result.totals.requests.package = sumMaps(
|
|
|
|
result.timeseries.map(timeseries => {
|
|
|
|
return timeseries.requests.package;
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
result.totals.bandwidth.package = sumMaps(
|
|
|
|
result.timeseries.map(timeseries => timeseries.bandwidth.package)
|
|
|
|
);
|
|
|
|
|
|
|
|
result.totals.requests.protocol = sumMaps(
|
|
|
|
result.timeseries.map(timeseries => timeseries.requests.protocol)
|
|
|
|
);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
);
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-30 16:20:45 +00:00
|
|
|
|
2017-08-22 15:31:33 +00:00
|
|
|
function extractPublicInfo(data) {
|
|
|
|
return {
|
|
|
|
since: data.since,
|
|
|
|
until: data.until,
|
|
|
|
|
|
|
|
requests: {
|
|
|
|
all: data.requests.all,
|
|
|
|
cached: data.requests.cached,
|
|
|
|
country: data.requests.country,
|
|
|
|
status: data.requests.http_status
|
|
|
|
},
|
|
|
|
|
|
|
|
bandwidth: {
|
|
|
|
all: data.bandwidth.all,
|
|
|
|
cached: data.bandwidth.cached,
|
|
|
|
country: data.bandwidth.country
|
|
|
|
},
|
|
|
|
|
|
|
|
threats: {
|
|
|
|
all: data.threats.all,
|
|
|
|
country: data.threats.country
|
|
|
|
},
|
|
|
|
|
|
|
|
uniques: {
|
|
|
|
all: data.uniques.all
|
|
|
|
}
|
2018-02-18 02:00:56 +00:00
|
|
|
};
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-29 05:41:01 +00:00
|
|
|
|
2018-12-17 17:38:05 +00:00
|
|
|
const DomainNames = ['unpkg.com', 'npmcdn.com'];
|
2017-08-22 15:31:33 +00:00
|
|
|
|
|
|
|
function fetchStats(since, until) {
|
2017-11-11 20:18:13 +00:00
|
|
|
return CloudflareAPI.getZones(DomainNames).then(zones => {
|
2018-02-18 02:00:56 +00:00
|
|
|
return CloudflareAPI.getZoneAnalyticsDashboard(zones, since, until).then(
|
|
|
|
dashboard => {
|
|
|
|
return {
|
|
|
|
timeseries: dashboard.timeseries.map(extractPublicInfo),
|
|
|
|
totals: extractPublicInfo(dashboard.totals)
|
|
|
|
};
|
2017-11-08 18:14:46 +00:00
|
|
|
}
|
2018-02-18 02:00:56 +00:00
|
|
|
);
|
|
|
|
});
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-25 23:37:54 +00:00
|
|
|
|
2018-02-18 02:00:56 +00:00
|
|
|
const oneMinute = 1000 * 60;
|
|
|
|
const oneHour = oneMinute * 60;
|
|
|
|
const oneDay = oneHour * 24;
|
2017-05-25 23:37:54 +00:00
|
|
|
|
2017-11-11 20:18:13 +00:00
|
|
|
function getStats(since, until) {
|
2018-02-18 02:00:56 +00:00
|
|
|
const promise = fetchStats(since, until);
|
|
|
|
return until - since > oneDay ? promise.then(addDailyMetrics) : promise;
|
2017-08-16 18:58:01 +00:00
|
|
|
}
|
2017-05-25 23:37:54 +00:00
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
createDayKey,
|
|
|
|
createHourKey,
|
2017-08-22 15:31:33 +00:00
|
|
|
createMinuteKey,
|
|
|
|
getStats
|
2018-02-18 02:00:56 +00:00
|
|
|
};
|