unpkg/modules/StatsAPI.js

174 lines
4.0 KiB
JavaScript
Raw Normal View History

2018-07-06 17:53:16 +00:00
const db = require("./utils/data");
2018-04-04 05:32:32 +00:00
2018-02-18 02:00:56 +00:00
const CloudflareAPI = require("./CloudflareAPI");
const BlacklistAPI = require("./BlacklistAPI");
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);
}
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
}
function createHourKey(date) {
2018-02-18 02:00:56 +00:00
return `${createDayKey(date)}-${date.getUTCHours()}`;
2017-08-16 18:58:01 +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-08-16 18:58:01 +00:00
function createScoresMap(array) {
2018-02-18 02:00:56 +00:00
const map = {};
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
}
2018-02-18 02:00:56 +00:00
return map;
}
function getScoresMap(key, n = 100) {
2017-11-08 18:14:46 +00:00
return new Promise((resolve, reject) => {
2017-11-25 21:25:01 +00:00
db.zrevrange(key, 0, n, "withscores", (error, value) => {
if (error) {
2018-02-18 02:00:56 +00:00
reject(error);
} else {
2018-02-18 02:00:56 +00:00
resolve(createScoresMap(value));
}
2018-02-18 02:00:56 +00:00
});
});
2017-08-16 18:58:01 +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
function getPackageBandwidth(date, n = 100) {
2018-02-18 02:00:56 +00:00
return getScoresMap(`stats-packageBytes-${createDayKey(date)}`, n).then(
prunePackages
);
}
function getProtocolRequests(date) {
2018-02-18 02:00:56 +00:00
return getScoresMap(`stats-protocolRequests-${createDayKey(date)}`);
}
function addDailyMetricsToTimeseries(timeseries) {
2018-02-18 02:00:56 +00:00
const since = new Date(timeseries.since);
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
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
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-02-18 02:00:56 +00:00
const DomainNames = ["unpkg.com", "npmcdn.com"];
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
}
2018-02-18 02:00:56 +00:00
const oneMinute = 1000 * 60;
const oneHour = oneMinute * 60;
const oneDay = oneHour * 24;
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
}
module.exports = {
createDayKey,
createHourKey,
createMinuteKey,
getStats
2018-02-18 02:00:56 +00:00
};