1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.testCosts = void 0;
|
4 | const ava_1 = require("ava");
|
5 | const ppp = require("papaparse");
|
6 | const index_1 = require("../index");
|
7 | const funcs = require("./fixtures/functions");
|
8 | const util_1 = require("./fixtures/util");
|
9 | async function work(faastModule) {
|
10 | await faastModule.functions.monteCarloPI(20000000);
|
11 | }
|
12 | const repetitions = 10;
|
13 | const memorySizes = [1024, 2048];
|
14 | function filter(configurations) {
|
15 | return configurations
|
16 | .filter(c => memorySizes.includes(c.options.memorySize))
|
17 | .map(c => ({ ...c, repetitions }));
|
18 | }
|
19 | async function testCostAnalyzer(t, configurations) {
|
20 | const profile = await index_1.CostAnalyzer.analyze({
|
21 | funcs,
|
22 | work,
|
23 | configurations,
|
24 | silent: true
|
25 | });
|
26 | t.is(profile.estimates.length, configurations.length);
|
27 | for (const { costSnapshot } of profile.estimates) {
|
28 | t.true(costSnapshot.stats.completed > 0, `completed > 0`);
|
29 | t.is(costSnapshot.stats.errors, 0, `errors === 0`);
|
30 | t.true(costSnapshot.stats.estimatedBilledTime.mean > 0, `billed time > 0`);
|
31 | t.true(costSnapshot.total() > 0, `total > 0`);
|
32 | }
|
33 | const parsed = ppp.parse(profile.csv(), {
|
34 | header: true,
|
35 | skipEmptyLines: true,
|
36 | dynamicTyping: true
|
37 | });
|
38 | index_1.log.info(`%O`, parsed.data);
|
39 | t.is(parsed.data.length, configurations.length);
|
40 | for (const row of parsed.data) {
|
41 | // cloud,memory,useQueue,options,completed,errors,retries,cost,executionTime,billedTime
|
42 | t.is(typeof row.cloud, "string");
|
43 | t.is(typeof row.memory, "number");
|
44 | t.is(typeof row.mode, "string");
|
45 | t.is(typeof row.options, "string");
|
46 | t.is(typeof row.completed, "number");
|
47 | t.is(typeof row.errors, "number");
|
48 | t.is(typeof row.retries, "number");
|
49 | t.is(typeof row.cost, "string");
|
50 | t.is(typeof row.executionTime, "number");
|
51 | t.is(typeof row.billedTime, "number");
|
52 | }
|
53 | }
|
54 | async function testCosts(t, provider) {
|
55 | const args = {
|
56 | timeout: 30,
|
57 | memorySize: 512,
|
58 | mode: "queue",
|
59 | maxRetries: 0,
|
60 | gc: "off",
|
61 | description: t.title
|
62 | };
|
63 | const faastModule = await (0, index_1.faast)(provider, funcs, args);
|
64 | try {
|
65 | await faastModule.functions.hello("there");
|
66 | const costs = await faastModule.costSnapshot();
|
67 | const { estimatedBilledTime } = faastModule.stats();
|
68 | t.is((estimatedBilledTime.mean * estimatedBilledTime.samples) / 1000, costs.costMetrics.find(m => m.name === "functionCallDuration").measured);
|
69 | t.true(costs.costMetrics.length > 1, "cost metrics exist");
|
70 | t.true(costs.find("functionCallRequests").measured === 1, "functionCallRequests === 1");
|
71 | const output = costs.toString();
|
72 | const csvOutput = costs.csv();
|
73 | let hasPricedMetric = false;
|
74 | for (const metric of costs.costMetrics) {
|
75 | t.regex(output, new RegExp(metric.name));
|
76 | t.regex(csvOutput, new RegExp(metric.name));
|
77 | if (!metric.informationalOnly) {
|
78 | t.true(metric.cost() > 0, `${metric.name}.cost() > 0`);
|
79 | t.true(metric.measured > 0, `${metric.name}.measured > 0`);
|
80 | t.true(metric.pricing > 0, `${metric.name}.pricing > 0`);
|
81 | }
|
82 | hasPricedMetric = true;
|
83 | t.true(metric.cost() < 0.00001, `${metric.name}.cost() < 0.00001`);
|
84 | t.true(metric.name.length > 0, `${metric.name}.length > 0`);
|
85 | t.true(metric.unit.length > 0, `${metric.name}.unit.length > 0`);
|
86 | t.true(metric.cost() === metric.pricing * metric.measured, `${metric.name} cost is computed correctly`);
|
87 | }
|
88 | if (hasPricedMetric) {
|
89 | t.true(costs.total() >= 0, `costs.total > 0 (hasPricedMetric)`);
|
90 | }
|
91 | else {
|
92 | t.true(costs.total() === 0, `costs.total === 0 (!hasPricedMetric)`);
|
93 | }
|
94 | }
|
95 | finally {
|
96 | await faastModule.cleanup();
|
97 | }
|
98 | }
|
99 | exports.testCosts = testCosts;
|
100 | const { awsConfigurations, googleConfigurations } = index_1.CostAnalyzer;
|
101 | (0, ava_1.default)((0, util_1.title)("aws", "cost analyzer"), testCostAnalyzer, filter(awsConfigurations));
|
102 | (0, ava_1.default)((0, util_1.title)("google", "cost analyzer"), testCostAnalyzer, filter(googleConfigurations));
|
103 | for (const provider of index_1.providers) {
|
104 | (0, ava_1.default)((0, util_1.title)(provider, `cost estimate for basic calls`), testCosts, provider);
|
105 | }
|
106 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29zdC50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdGVzdC9jb3N0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTZDO0FBQzdDLGlDQUFpQztBQUNqQyxvQ0FRa0I7QUFDbEIsOENBQThDO0FBQzlDLDBDQUF3QztBQUV4QyxLQUFLLFVBQVUsSUFBSSxDQUFDLFdBQXNDO0lBQ3RELE1BQU0sV0FBVyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDdkQsQ0FBQztBQUVELE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQztBQUN2QixNQUFNLFdBQVcsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztBQUVqQyxTQUFTLE1BQU0sQ0FBQyxjQUE0QztJQUN4RCxPQUFPLGNBQWM7U0FDaEIsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFVBQVcsQ0FBQyxDQUFDO1NBQ3hELEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxnQkFBZ0IsQ0FDM0IsQ0FBbUIsRUFDbkIsY0FBNEM7SUFFNUMsTUFBTSxPQUFPLEdBQUcsTUFBTSxvQkFBWSxDQUFDLE9BQU8sQ0FBQztRQUN2QyxLQUFLO1FBQ0wsSUFBSTtRQUNKLGNBQWM7UUFDZCxNQUFNLEVBQUUsSUFBSTtLQUNmLENBQUMsQ0FBQztJQUNILENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3RELEtBQUssTUFBTSxFQUFFLFlBQVksRUFBRSxJQUFJLE9BQU8sQ0FBQyxTQUFTLEVBQUU7UUFDOUMsQ0FBQyxDQUFD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QUFHLG9CQUFZLENBQUM7QUFDakUsSUFBQSxhQUFJLEVBQUMsSUFBQSxZQUFLLEVBQUMsS0FBSyxFQUFFLGVBQWUsQ0FBQyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7QUFDakYsSUFBQSxhQUFJLEVBQUMsSUFBQSxZQUFLLEVBQUMsUUFBUSxFQUFFLGVBQWUsQ0FBQyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUM7QUFFdkYsS0FBSyxNQUFNLFFBQVEsSUFBSSxpQkFBUyxFQUFFO0lBQzlCLElBQUEsYUFBSSxFQUFDLElBQUEsWUFBSyxFQUFDLFFBQVEsRUFBRSwrQkFBK0IsQ0FBQyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztDQUMvRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0ZXN0LCB7IEV4ZWN1dGlvbkNvbnRleHQgfSBmcm9tIFwiYXZhXCI7XG5pbXBvcnQgKiBhcyBwcHAgZnJvbSBcInBhcGFwYXJzZVwiO1xuaW1wb3J0IHtcbiAgICBDb21tb25PcHRpb25zLFxuICAgIGZhYXN0LFxuICAgIEZhYXN0TW9kdWxlLFxuICAgIGxvZyxcbiAgICBQcm92aWRlcixcbiAgICBwcm92aWRlcnMsXG4gICAgQ29zdEFuYWx5emVyXG59IGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0ICogYXMgZnVuY3MgZnJvbSBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyB0aXRsZSB9IGZyb20gXCIuL2ZpeHR1cmVzL3V0aWxcIjtcblxuYXN5bmMgZnVuY3Rpb24gd29yayhmYWFzdE1vZHVsZTogRmFhc3RNb2R1bGU8dHlwZW9mIGZ1bmNzPikge1xuICAgIGF3YWl0IGZhYXN0TW9kdWxlLmZ1bmN0aW9ucy5tb250ZUNhcmxvUEkoMjAwMDAwMDApO1xufVxuXG5jb25zdCByZXBldGl0aW9ucyA9IDEwO1xuY29uc3QgbWVtb3J5U2l6ZXMgPSBbMTAyNCwgMjA0OF07XG5cbmZ1bmN0aW9uIGZpbHRlcihjb25maWd1cmF0aW9uczogQ29zdEFuYWx5emVyLkNvbmZpZ3VyYXRpb25bXSkge1xuICAgIHJldHVybiBjb25maWd1cmF0aW9uc1xuICAgICAgICAuZmlsdGVyKGMgPT4gbWVtb3J5U2l6ZXMuaW5jbHVkZXMoYy5vcHRpb25zLm1lbW9yeVNpemUhKSlcbiAgICAgICAgLm1hcChjID0+ICh7IC4uLmMsIHJlcGV0aXRpb25zIH0pKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdGVzdENvc3RBbmFseXplcihcbiAgICB0OiBFeGVjdXRpb25Db250ZXh0LFxuICAgIGNvbmZpZ3VyYXRpb25zOiBDb3N0QW5hbHl6ZXIuQ29uZmlndXJhdGlvbltdXG4pIHtcbiAgICBjb25zdCBwcm9maWxlID0gYXdhaXQgQ29zdEFuYWx5emVyLmFuYWx5emUoe1xuICAgICAgICBmdW5jcyxcbiAgICAgICAgd29yayxcbiAgICAgICAgY29uZmlndXJhdGlvbnMsXG4gICAgICAgIHNpbGVudDogdHJ1ZVxuICAgIH0pO1xuICAgIHQuaXMocHJvZmlsZS5lc3RpbWF0ZXMubGVuZ3RoLCBjb25maWd1cmF0aW9ucy5sZW5ndGgpO1xuICAgIGZvciAoY29uc3QgeyBjb3N0U25hcHNob3QgfSBvZiBwcm9maWxlLmVzdGltYXRlcykge1xuICAgICAgICB0LnRydWUoY29zdFNuYXBzaG90LnN0YXRzLmNvbXBsZXRlZCA+IDAsIGBjb21wbGV0ZWQgPiAwYCk7XG4gICAgICAgIHQuaXMoY29zdFNuYXBzaG90LnN0YXRzLmVycm9ycywgMCwgYGVycm9ycyA9PT0gMGApO1xuICAgICAgICB0LnRydWUoY29zdFNuYXBzaG90LnN0YXRzLmVzdGltYXRlZEJpbGxlZFRpbWUubWVhbiA+IDAsIGBiaWxsZWQgdGltZSA+IDBgKTtcbiAgICAgICAgdC50cnVlKGNvc3RTbmFwc2hvdC50b3RhbCgpID4gMCwgYHRvdGFsID4gMGApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnNlZCA9IHBwcC5wYXJzZTxhbnk+KHByb2ZpbGUuY3N2KCksIHtcbiAgICAgICAgaGVhZGVyOiB0cnVlLFxuICAgICAgICBza2lwRW1wdHlMaW5lczogdHJ1ZSxcbiAgICAgICAgZHluYW1pY1R5cGluZzogdHJ1ZVxuICAgIH0pO1xuICAgIGxvZy5pbmZvKGAlT2AsIHBhcnNlZC5kYXRhKTtcbiAgICB0LmlzKHBhcnNlZC5kYXRhLmxlbmd0aCwgY29uZmlndXJhdGlvbnMubGVuZ3RoKTtcblxuICAgIGZvciAoY29uc3Qgcm93IG9mIHBhcnNlZC5kYXRhKSB7XG4gICAgICAgIC8vIGNsb3VkLG1lbW9yeSx1c2VRdWV1ZSxvcHRpb25zLGNvbXBsZXRlZCxlcnJvcnMscmV0cmllcyxjb3N0LGV4ZWN1dGlvblRpbWUsYmlsbGVkVGltZVxuICAgICAgICB0LmlzKHR5cGVvZiByb3cuY2xvdWQsIFwic3RyaW5nXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cubWVtb3J5LCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93Lm1vZGUsIFwic3RyaW5nXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cub3B0aW9ucywgXCJzdHJpbmdcIik7XG4gICAgICAgIHQuaXModHlwZW9mIHJvdy5jb21wbGV0ZWQsIFwibnVtYmVyXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cuZXJyb3JzLCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93LnJldHJpZXMsIFwibnVtYmVyXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiByb3cuY29zdCwgXCJzdHJpbmdcIik7XG4gICAgICAgIHQuaXModHlwZW9mIHJvdy5leGVjdXRpb25UaW1lLCBcIm51bWJlclwiKTtcbiAgICAgICAgdC5pcyh0eXBlb2Ygcm93LmJpbGxlZFRpbWUsIFwibnVtYmVyXCIpO1xuICAgIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3RDb3N0cyh0OiBFeGVjdXRpb25Db250ZXh0LCBwcm92aWRlcjogUHJvdmlkZXIpIHtcbiAgICBjb25zdCBhcmdzOiBDb21tb25PcHRpb25zID0ge1xuICAgICAgICB0aW1lb3V0OiAzMCxcbiAgICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgICBtb2RlOiBcInF1ZXVlXCIsXG4gICAgICAgIG1heFJldHJpZXM6IDAsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZVxuICAgIH07XG4gICAgY29uc3QgZmFhc3RNb2R1bGUgPSBhd2FpdCBmYWFzdChwcm92aWRlciwgZnVuY3MsIGFyZ3MpO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuZnVuY3Rpb25zLmhlbGxvKFwidGhlcmVcIik7XG4gICAgICAgIGNvbnN0IGNvc3RzID0gYXdhaXQgZmFhc3RNb2R1bGUuY29zdFNuYXBzaG90KCk7XG5cbiAgICAgICAgY29uc3QgeyBlc3RpbWF0ZWRCaWxsZWRUaW1lIH0gPSBmYWFzdE1vZHVsZS5zdGF0cygpO1xuICAgICAgICB0LmlzKFxuICAgICAgICAgICAgKGVzdGltYXRlZEJpbGxlZFRpbWUubWVhbiAqIGVzdGltYXRlZEJpbGxlZFRpbWUuc2FtcGxlcykgLyAxMDAwLFxuICAgICAgICAgICAgY29zdHMuY29zdE1ldHJpY3MuZmluZChtID0+IG0ubmFtZSA9PT0gXCJmdW5jdGlvbkNhbGxEdXJhdGlvblwiKSEubWVhc3VyZWRcbiAgICAgICAgKTtcblxuICAgICAgICB0LnRydWUoY29zdHMuY29zdE1ldHJpY3MubGVuZ3RoID4gMSwgXCJjb3N0IG1ldHJpY3MgZXhpc3RcIik7XG4gICAgICAgIHQudHJ1ZShcbiAgICAgICAgICAgIGNvc3RzLmZpbmQoXCJmdW5jdGlvbkNhbGxSZXF1ZXN0c1wiKSEubWVhc3VyZWQgPT09IDEsXG4gICAgICAgICAgICBcImZ1bmN0aW9uQ2FsbFJlcXVlc3RzID09PSAxXCJcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgb3V0cHV0ID0gY29zdHMudG9TdHJpbmcoKTtcbiAgICAgICAgY29uc3QgY3N2T3V0cHV0ID0gY29zdHMuY3N2KCk7XG4gICAgICAgIGxldCBoYXNQcmljZWRNZXRyaWMgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCBtZXRyaWMgb2YgY29zdHMuY29zdE1ldHJpY3MpIHtcbiAgICAgICAgICAgIHQucmVnZXgob3V0cHV0LCBuZXcgUmVnRXhwKG1ldHJpYy5uYW1lKSk7XG4gICAgICAgICAgICB0LnJlZ2V4KGNzdk91dHB1dCwgbmV3IFJlZ0V4cChtZXRyaWMubmFtZSkpO1xuICAgICAgICAgICAgaWYgKCFtZXRyaWMuaW5mb3JtYXRpb25hbE9ubHkpIHtcbiAgICAgICAgICAgICAgICB0LnRydWUobWV0cmljLmNvc3QoKSA+IDAsIGAke21ldHJpYy5uYW1lfS5jb3N0KCkgPiAwYCk7XG4gICAgICAgICAgICAgICAgdC50cnVlKG1ldHJpYy5tZWFzdXJlZCA+IDAsIGAke21ldHJpYy5uYW1lfS5tZWFzdXJlZCA+IDBgKTtcbiAgICAgICAgICAgICAgICB0LnRydWUobWV0cmljLnByaWNpbmcgPiAwLCBgJHttZXRyaWMubmFtZX0ucHJpY2luZyA+IDBgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhc1ByaWNlZE1ldHJpYyA9IHRydWU7XG4gICAgICAgICAgICB0LnRydWUobWV0cmljLmNvc3QoKSA8IDAuMDAwMDEsIGAke21ldHJpYy5uYW1lfS5jb3N0KCkgPCAwLjAwMDAxYCk7XG4gICAgICAgICAgICB0LnRydWUobWV0cmljLm5hbWUubGVuZ3RoID4gMCwgYCR7bWV0cmljLm5hbWV9Lmxlbmd0aCA+IDBgKTtcbiAgICAgICAgICAgIHQudHJ1ZShtZXRyaWMudW5pdC5sZW5ndGggPiAwLCBgJHttZXRyaWMubmFtZX0udW5pdC5sZW5ndGggPiAwYCk7XG4gICAgICAgICAgICB0LnRydWUoXG4gICAgICAgICAgICAgICAgbWV0cmljLmNvc3QoKSA9PT0gbWV0cmljLnByaWNpbmcgKiBtZXRyaWMubWVhc3VyZWQsXG4gICAgICAgICAgICAgICAgYCR7bWV0cmljLm5hbWV9IGNvc3QgaXMgY29tcHV0ZWQgY29ycmVjdGx5YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGFzUHJpY2VkTWV0cmljKSB7XG4gICAgICAgICAgICB0LnRydWUoY29zdHMudG90YWwoKSA+PSAwLCBgY29zdHMudG90YWwgPiAwIChoYXNQcmljZWRNZXRyaWMpYCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0LnRydWUoY29zdHMudG90YWwoKSA9PT0gMCwgYGNvc3RzLnRvdGFsID09PSAwICghaGFzUHJpY2VkTWV0cmljKWApO1xuICAgICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuY2xlYW51cCgpO1xuICAgIH1cbn1cblxuY29uc3QgeyBhd3NDb25maWd1cmF0aW9ucywgZ29vZ2xlQ29uZmlndXJhdGlvbnMgfSA9IENvc3RBbmFseXplcjtcbnRlc3QodGl0bGUoXCJhd3NcIiwgXCJjb3N0IGFuYWx5emVyXCIpLCB0ZXN0Q29zdEFuYWx5emVyLCBmaWx0ZXIoYXdzQ29uZmlndXJhdGlvbnMpKTtcbnRlc3QodGl0bGUoXCJnb29nbGVcIiwgXCJjb3N0IGFuYWx5emVyXCIpLCB0ZXN0Q29zdEFuYWx5emVyLCBmaWx0ZXIoZ29vZ2xlQ29uZmlndXJhdGlvbnMpKTtcblxuZm9yIChjb25zdCBwcm92aWRlciBvZiBwcm92aWRlcnMpIHtcbiAgICB0ZXN0KHRpdGxlKHByb3ZpZGVyLCBgY29zdCBlc3RpbWF0ZSBmb3IgYmFzaWMgY2FsbHNgKSwgdGVzdENvc3RzLCBwcm92aWRlcik7XG59XG4iXX0= |
\ | No newline at end of file |