faastjs
Version:
Serverless batch computing made simple.
106 lines • 17.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.testCosts = void 0;
const tslib_1 = require("tslib");
const ava_1 = tslib_1.__importDefault(require("ava"));
const papaparse_1 = tslib_1.__importDefault(require("papaparse"));
const index_1 = require("../index");
const funcs = tslib_1.__importStar(require("./fixtures/functions"));
const util_1 = require("./fixtures/util");
async function work(faastModule) {
await faastModule.functions.monteCarloPI(20000000);
}
const repetitions = 10;
const memorySizes = [1024, 2048];
function filter(configurations) {
return configurations
.filter(c => memorySizes.includes(c.options.memorySize))
.map(c => ({ ...c, repetitions }));
}
async function testCostAnalyzer(t, configurations) {
const profile = await index_1.CostAnalyzer.analyze({
funcs,
work,
configurations,
silent: true
});
t.is(profile.estimates.length, configurations.length);
for (const { costSnapshot } of profile.estimates) {
t.true(costSnapshot.stats.completed > 0, `completed > 0`);
t.is(costSnapshot.stats.errors, 0, `errors === 0`);
t.true(costSnapshot.stats.estimatedBilledTime.mean > 0, `billed time > 0`);
t.true(costSnapshot.total() > 0, `total > 0`);
}
const parsed = papaparse_1.default.parse(profile.csv(), {
header: true,
skipEmptyLines: true,
dynamicTyping: true
});
index_1.log.info(`%O`, parsed.data);
t.is(parsed.data.length, configurations.length);
for (const row of parsed.data) {
// cloud,memory,useQueue,options,completed,errors,retries,cost,executionTime,billedTime
t.is(typeof row.cloud, "string");
t.is(typeof row.memory, "number");
t.is(typeof row.mode, "string");
t.is(typeof row.options, "string");
t.is(typeof row.completed, "number");
t.is(typeof row.errors, "number");
t.is(typeof row.retries, "number");
t.is(typeof row.cost, "string");
t.is(typeof row.executionTime, "number");
t.is(typeof row.billedTime, "number");
}
}
async function testCosts(t, provider) {
const args = {
timeout: 30,
memorySize: 512,
mode: "queue",
maxRetries: 0,
gc: "off",
description: t.title
};
const faastModule = await (0, index_1.faast)(provider, funcs, args);
try {
await faastModule.functions.hello("there");
const costs = await faastModule.costSnapshot();
const { estimatedBilledTime } = faastModule.stats();
t.is((estimatedBilledTime.mean * estimatedBilledTime.samples) / 1000, costs.costMetrics.find(m => m.name === "functionCallDuration").measured);
t.true(costs.costMetrics.length > 1, "cost metrics exist");
t.true(costs.find("functionCallRequests").measured === 1, "functionCallRequests === 1");
const output = costs.toString();
const csvOutput = costs.csv();
let hasPricedMetric = false;
for (const metric of costs.costMetrics) {
t.regex(output, new RegExp(metric.name));
t.regex(csvOutput, new RegExp(metric.name));
if (!metric.informationalOnly) {
t.true(metric.cost() > 0, `${metric.name}.cost() > 0`);
t.true(metric.measured > 0, `${metric.name}.measured > 0`);
t.true(metric.pricing > 0, `${metric.name}.pricing > 0`);
}
hasPricedMetric = true;
t.true(metric.cost() < 0.00001, `${metric.name}.cost() < 0.00001`);
t.true(metric.name.length > 0, `${metric.name}.length > 0`);
t.true(metric.unit.length > 0, `${metric.name}.unit.length > 0`);
t.true(metric.cost() === metric.pricing * metric.measured, `${metric.name} cost is computed correctly`);
}
if (hasPricedMetric) {
t.true(costs.total() >= 0, `costs.total > 0 (hasPricedMetric)`);
}
else {
t.true(costs.total() === 0, `costs.total === 0 (!hasPricedMetric)`);
}
}
finally {
await faastModule.cleanup();
}
}
exports.testCosts = testCosts;
const { awsConfigurations } = index_1.CostAnalyzer;
(0, ava_1.default)((0, util_1.title)("aws", "cost analyzer"), testCostAnalyzer, filter(awsConfigurations));
for (const provider of index_1.providers) {
(0, ava_1.default)((0, util_1.title)(provider, `cost estimate for basic calls`), testCosts, provider);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29zdC50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdGVzdC9jb3N0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLHNEQUE2QztBQUM3QyxrRUFBNEI7QUFDNUIsb0NBUWtCO0FBQ2xCLG9FQUE4QztBQUM5QywwQ0FBd0M7QUFFeEMsS0FBSyxVQUFVLElBQUksQ0FBQyxXQUFzQztJQUN0RCxNQUFNLFdBQVcsQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3ZELENBQUM7QUFFRCxNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUM7QUFDdkIsTUFBTSxXQUFXLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFFakMsU0FBUyxNQUFNLENBQUMsY0FBNEM7SUFDeEQsT0FBTyxjQUFjO1NBQ2hCLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFXLENBQUMsQ0FBQztTQUN4RCxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFFRCxLQUFLLFVBQVUsZ0JBQWdCLENBQzNCLENBQW1CLEVBQ25CLGNBQTRDO0lBRTVDLE1BQU0sT0FBTyxHQUFHLE1BQU0sb0JBQVksQ0FBQyxPQUFPLENBQUM7UUFDdkMsS0FBSztRQUNMLElBQUk7UUFDSixjQUFjO1FBQ2QsTUFBTSxFQUFFLElBQUk7S0FDZixDQUFDLENBQUM7SUFDSCxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0RCxLQUFLLE1BQU0sRUFBRSxZQUFZLEVBQUUsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFO1FBQzlDLENBQUMsQ0FB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Q0FBQztBQUMzQyxJQUFBLGFBQUksRUFBQyxJQUFBLFlBQUssRUFBQyxLQUFLLEVBQUUsZUFBZSxDQUFDLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztBQUVqRixLQUFLLE1BQU0sUUFBUSxJQUFJLGlCQUFTLEVBQUU7SUFDOUIsSUFBQSxhQUFJLEVBQUMsSUFBQSxZQUFLLEVBQUMsUUFBUSxFQUFFLCtCQUErQixDQUFDLEVBQUUsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0NBQy9FIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRlc3QsIHsgRXhlY3V0aW9uQ29udGV4dCB9IGZyb20gXCJhdmFcIjtcbmltcG9ydCBwcHAgZnJvbSBcInBhcGFwYXJzZVwiO1xuaW1wb3J0IHtcbiAgICBDb21tb25PcHRpb25zLFxuICAgIGZhYXN0LFxuICAgIEZhYXN0TW9kdWxlLFxuICAgIGxvZyxcbiAgICBQcm92aWRlcixcbiAgICBwcm92aWRlcnMsXG4gICAgQ29zdEFuYWx5emVyXG59IGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0ICogYXMgZnVuY3MgZnJvbSBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyB0aXRsZSB9IGZyb20gXCIuL2ZpeHR1cmVzL3V0aWxcIjtcblxuYXN5bmMgZnVuY3Rpb24gd29yayhmYWFzdE1vZHVsZTogRmFhc3RNb2R1bGU8dHlwZW9mIGZ1bmNzPikge1xuICAgIGF3YWl0IGZhYXN0TW9kdWxlLmZ1bmN0aW9ucy5tb250ZUNhcmxvUEkoMjAwMDAwMDApO1xufVxuXG5jb25zdCByZXBldGl0aW9ucyA9IDEwO1xuY29uc3QgbWVtb3J5U2l6ZXMgPSBbMTAyNCwgMjA0OF07XG5cbmZ1bmN0aW9uIGZpbHRlcihjb25maWd1cmF0aW9uczogQ29zdEFuYWx5emVyLkNvbmZpZ3VyYXRpb25bXSkge1xuICAgIHJldHVybiBjb25maWd1cmF0aW9uc1xuICAgICAgICAuZmlsdGVyKGMgPT4gbWVtb3J5U2l6ZXMuaW5jbHVkZXMoYy5vcHRpb25zLm1lbW9yeVNpemUhKSlcbiAgICAgICAgLm1hcChjID0+ICh7IC4uLmMsIHJlcGV0aXRpb25zIH0pKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdGVzdENvc3RBbmFseXplcihcbiAgICB0OiBFeGVjdXRpb25Db250ZXh0LFxuICAgIGNvbmZpZ3VyYXRpb25zOiBDb3N0QW5hbHl6ZXIuQ29uZmlndXJhdGlvbltdXG4pIHtcbiAgICBjb25zdCBwcm9maWxlID0gYXdhaXQgQ29zdEFuYWx5emVyLmFuYWx5emUoe1xuICAgICAgICBmdW5jcyxcbiAgICAgICAgd29yayxcbiAgICAgICAgY29uZmlndXJhdGlvbnMsXG4gICAgICAgIHNpbGVudDogdHJ1ZVxuICAgIH0pO1xuICAgIHQuaXMocHJvZmlsZS5lc3RpbWF0ZXMubGVuZ3RoLCBjb25maWd1cmF0aW9ucy5sZW5ndGgpO1xuICAgIGZvciAoY29uc3QgeyBjb3N0U25hcHNob3QgfSBvZiBwcm9maWxlLmVzdGltYXRlcykge1xuICAgICAgICB0LnRydWUoY29zdFNuYXBzaG90LnN0YXRzLmNvbXBsZXRlZCA+IDAsIGBjb21wbGV0ZWQgPiAwYCk7XG4gICAgICAgIHQuaXMoY29zdFNuYXBzaG90LnN0YXRzLmVycm9ycywgMCwgYGVycm9ycyA9PT0gMGApO1xuICAgICAgICB0LnRydWUoY29zdFNuYXBzaG90LnN0YXRzLmVzdGltYXRlZEJpbGxlZFRpbWUubWVhbiA+IDAsIGBiaWxsZWQgdGltZSA+IDBgKTtcbiAgICAgICAgdC50cnVlKGNvc3RTbmFwc2hvdC50b3RhbCgpID4gMCwgYHRvdGFsID4gMGApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZCA9IHBwcC5wYXJzZTxhbnk+KHByb2ZpbGUuY3N2KCksIHtcbiAgICAgICAgaGVhZGVyOiB0cnVlLFxuICAgICAgICBza2lwRW1wdHlMaW5lczogdHJ1ZSxcbiAgICAgICAgZHluYW1pY1R5cGluZzogdHJ1ZVxuICAgIH0pO1xuICAgIGxvZy5pbmZvKGAlT2AsIHBhcnNlZC5kYXRhKTtcbiAgICB0LmlzKHBhcnNlZC5kYXRhLmxlbmd0aCwgY29uZmlndXJhdGlvbnMubGVuZ3RoKTtcblxuICAgIGZvciAoY29uc3Qgcm93IG9mIHBhcnNlZC5kYXRhKSB7XG4gICAgICAgIC8vIGNsb3VkLG1lbW9yeSx1c2VRdWV1ZSxvcHRpb25zLGNvbXBsZXRlZCxlcnJvcnMscmV0cmllcyxjb3N0LGV4ZWN1dGlvblRpbWUsYmlsbGVkVGltZVxuICAgICAgICB0LmlzKHR5cGVvZiByb3cuY2xvdWQsIFwic3RyaW5nXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cubWVtb3J5LCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93Lm1vZGUsIFwic3RyaW5nXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cub3B0aW9ucywgXCJzdHJpbmdcIik7XG4gICAgICAgIHQuaXModHlwZW9mIHJvdy5jb21wbGV0ZWQsIFwibnVtYmVyXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cuZXJyb3JzLCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93LnJldHJpZXMsIFwibnVtYmVyXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cuY29zdCwgXCJzdHJpbmdcIik7XG4gICAgICAgIHQuaXModHlwZW9mIHJvdy5leGVjdXRpb25UaW1lLCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93LmJpbGxlZFRpbWUsIFwibnVtYmVyXCIpO1xuICAgIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3RDb3N0cyh0OiBFeGVjdXRpb25Db250ZXh0LCBwcm92aWRlcjogUHJvdmlkZXIpIHtcbiAgICBjb25zdCBhcmdzOiBDb21tb25PcHRpb25zID0ge1xuICAgICAgICB0aW1lb3V0OiAzMCxcbiAgICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgICBtb2RlOiBcInF1ZXVlXCIsXG4gICAgICAgIG1heFJldHJpZXM6IDAsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZVxuICAgIH07XG4gICAgY29uc3QgZmFhc3RNb2R1bGUgPSBhd2FpdCBmYWFzdChwcm92aWRlciwgZnVuY3MsIGFyZ3MpO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuZnVuY3Rpb25zLmhlbGxvKFwidGhlcmVcIik7XG4gICAgICAgIGNvbnN0IGNvc3RzID0gYXdhaXQgZmFhc3RNb2R1bGUuY29zdFNuYXBzaG90KCk7XG5cbiAgICAgICAgY29uc3QgeyBlc3RpbWF0ZWRCaWxsZWRUaW1lIH0gPSBmYWFzdE1vZHVsZS5zdGF0cygpO1xuICAgICAgICB0LmlzKFxuICAgICAgICAgICAgKGVzdGltYXRlZEJpbGxlZFRpbWUubWVhbiAqIGVzdGltYXRlZEJpbGxlZFRpbWUuc2FtcGxlcykgLyAxMDAwLFxuICAgICAgICAgICAgY29zdHMuY29zdE1ldHJpY3MuZmluZChtID0+IG0ubmFtZSA9PT0gXCJmdW5jdGlvbkNhbGxEdXJhdGlvblwiKSEubWVhc3VyZWRcbiAgICAgICAgKTtcblxuICAgICAgICB0LnRydWUoY29zdHMuY29zdE1ldHJpY3MubGVuZ3RoID4gMSwgXCJjb3N0IG1ldHJpY3MgZXhpc3RcIik7XG4gICAgICAgIHQudHJ1ZShcbiAgICAgICAgICAgIGNvc3RzLmZpbmQoXCJmdW5jdGlvbkNhbGxSZXF1ZXN0c1wiKSEubWVhc3VyZWQgPT09IDEsXG4gICAgICAgICAgICBcImZ1bmN0aW9uQ2FsbFJlcXVlc3RzID09PSAxXCJcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgb3V0cHV0ID0gY29zdHMudG9TdHJpbmcoKTtcbiAgICAgICAgY29uc3QgY3N2T3V0cHV0ID0gY29zdHMuY3N2KCk7XG4gICAgICAgIGxldCBoYXNQcmljZWRNZXRyaWMgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBtZXRyaWMgb2YgY29zdHMuY29zdE1ldHJpY3MpIHtcbiAgICAgICAgICAgIHQucmVnZXgob3V0cHV0LCBuZXcgUmVnRXhwKG1ldHJpYy5uYW1lKSk7XG4gICAgICAgICAgICB0LnJlZ2V4KGNzdk91dHB1dCwgbmV3IFJlZ0V4cChtZXRyaWMubmFtZSkpO1xuICAgICAgICAgICAgaWYgKCFtZXRyaWMuaW5mb3JtYXRpb25hbE9ubHkpIHtcbiAgICAgICAgICAgICAgICB0LnRydWUobWV0cmljLmNvc3QoKSA+IDAsIGAke21ldHJpYy5uYW1lfS5jb3N0KCkgPiAwYCk7XG4gICAgICAgICAgICAgICAgdC50cnVlKG1ldHJpYy5tZWFzdXJlZCA+IDAsIGAke21ldHJpYy5uYW1lfS5tZWFzdXJlZCA+IDBgKTtcbiAgICAgICAgICAgICAgICB0LnRydWUobWV0cmljLnByaWNpbmcgPiAwLCBgJHttZXRyaWMubmFtZX0ucHJpY2luZyA+IDBgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhc1ByaWNlZE1ldHJpYyA9IHRydWU7XG4gICAgICAgICAgICB0LnRydWUobWV0cmljLmNvc3QoKSA8IDAuMDAwMDEsIGAke21ldHJpYy5uYW1lfS5jb3N0KCkgPCAwLjAwMDAxYCk7XG4gICAgICAgICAgICB0LnRydWUobWV0cmljLm5hbWUubGVuZ3RoID4gMCwgYCR7bWV0cmljLm5hbWV9Lmxlbmd0aCA+IDBgKTtcbiAgICAgICAgICAgIHQudHJ1ZShtZXRyaWMudW5pdC5sZW5ndGggPiAwLCBgJHttZXRyaWMubmFtZX0udW5pdC5sZW5ndGggPiAwYCk7XG4gICAgICAgICAgICB0LnRydWUoXG4gICAgICAgICAgICAgICAgbWV0cmljLmNvc3QoKSA9PT0gbWV0cmljLnByaWNpbmcgKiBtZXRyaWMubWVhc3VyZWQsXG4gICAgICAgICAgICAgICAgYCR7bWV0cmljLm5hbWV9IGNvc3QgaXMgY29tcHV0ZWQgY29ycmVjdGx5YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGFzUHJpY2VkTWV0cmljKSB7XG4gICAgICAgICAgICB0LnRydWUoY29zdHMudG90YWwoKSA+PSAwLCBgY29zdHMudG90YWwgPiAwIChoYXNQcmljZWRNZXRyaWMpYCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0LnRydWUoY29zdHMudG90YWwoKSA9PT0gMCwgYGNvc3RzLnRvdGFsID09PSAwICghaGFzUHJpY2VkTWV0cmljKWApO1xuICAgICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuY2xlYW51cCgpO1xuICAgIH1cbn1cblxuY29uc3QgeyBhd3NDb25maWd1cmF0aW9ucyB9ID0gQ29zdEFuYWx5emVyO1xudGVzdCh0aXRsZShcImF3c1wiLCBcImNvc3QgYW5hbHl6ZXJcIiksIHRlc3RDb3N0QW5hbHl6ZXIsIGZpbHRlcihhd3NDb25maWd1cmF0aW9ucykpO1xuXG5mb3IgKGNvbnN0IHByb3ZpZGVyIG9mIHByb3ZpZGVycykge1xuICAgIHRlc3QodGl0bGUocHJvdmlkZXIsIGBjb3N0IGVzdGltYXRlIGZvciBiYXNpYyBjYWxsc2ApLCB0ZXN0Q29zdHMsIHByb3ZpZGVyKTtcbn1cbiJdfQ==