|
|
@@ -1,102 +1,109 @@
|
|
|
-import { forEach, get, round } from 'lodash'
|
|
|
+import { forEach, get, round } from "lodash";
|
|
|
+import { costMetricToPropName } from "./cloudCost/tokens";
|
|
|
|
|
|
// rangeToCumulative takes an AllocationSetRange (type: array[AllocationSet])
|
|
|
// and accumulates the values into a single AllocationSet (type: object)
|
|
|
export function rangeToCumulative(allocationSetRange, aggregateBy) {
|
|
|
if (allocationSetRange.length === 0) {
|
|
|
- return null
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- const result = {}
|
|
|
+ const result = {};
|
|
|
|
|
|
forEach(allocationSetRange, (allocSet) => {
|
|
|
forEach(allocSet, (alloc) => {
|
|
|
if (result[alloc.name] === undefined) {
|
|
|
- const hrs = get(alloc, 'minutes', 0) / 60.0
|
|
|
+ const hrs = get(alloc, "minutes", 0) / 60.0;
|
|
|
|
|
|
result[alloc.name] = {
|
|
|
name: alloc.name,
|
|
|
[aggregateBy]: alloc.name,
|
|
|
- cpuCost: get(alloc, 'cpuCost', 0),
|
|
|
- gpuCost: get(alloc, 'gpuCost', 0),
|
|
|
- ramCost: get(alloc, 'ramCost', 0),
|
|
|
- pvCost: get(alloc, 'pvCost', 0),
|
|
|
- networkCost: get(alloc, 'networkCost', 0),
|
|
|
- sharedCost: get(alloc, 'sharedCost', 0),
|
|
|
- externalCost: get(alloc, 'externalCost', 0),
|
|
|
- totalCost: get(alloc, 'totalCost', 0),
|
|
|
- cpuUseCoreHrs: get(alloc, 'cpuCoreUsageAverage', 0) * hrs,
|
|
|
- cpuReqCoreHrs: get(alloc, 'cpuCoreRequestAverage', 0) * hrs,
|
|
|
- ramUseByteHrs: get(alloc, 'ramByteUsageAverage', 0) * hrs,
|
|
|
- ramReqByteHrs: get(alloc, 'ramByteRequestAverage', 0) * hrs,
|
|
|
- cpuEfficiency: get(alloc, 'cpuEfficiency', 0),
|
|
|
- ramEfficiency: get(alloc, 'ramEfficiency', 0),
|
|
|
- totalEfficiency: get(alloc, 'totalEfficiency', 0),
|
|
|
- }
|
|
|
+ cpuCost: get(alloc, "cpuCost", 0),
|
|
|
+ gpuCost: get(alloc, "gpuCost", 0),
|
|
|
+ ramCost: get(alloc, "ramCost", 0),
|
|
|
+ pvCost: get(alloc, "pvCost", 0),
|
|
|
+ networkCost: get(alloc, "networkCost", 0),
|
|
|
+ sharedCost: get(alloc, "sharedCost", 0),
|
|
|
+ externalCost: get(alloc, "externalCost", 0),
|
|
|
+ totalCost: get(alloc, "totalCost", 0),
|
|
|
+ cpuUseCoreHrs: get(alloc, "cpuCoreUsageAverage", 0) * hrs,
|
|
|
+ cpuReqCoreHrs: get(alloc, "cpuCoreRequestAverage", 0) * hrs,
|
|
|
+ ramUseByteHrs: get(alloc, "ramByteUsageAverage", 0) * hrs,
|
|
|
+ ramReqByteHrs: get(alloc, "ramByteRequestAverage", 0) * hrs,
|
|
|
+ cpuEfficiency: get(alloc, "cpuEfficiency", 0),
|
|
|
+ ramEfficiency: get(alloc, "ramEfficiency", 0),
|
|
|
+ totalEfficiency: get(alloc, "totalEfficiency", 0),
|
|
|
+ };
|
|
|
} else {
|
|
|
- const hrs = get(alloc, 'minutes', 0) / 60.0
|
|
|
-
|
|
|
- result[alloc.name].cpuCost += get(alloc, 'cpuCost', 0)
|
|
|
- result[alloc.name].gpuCost += get(alloc, 'gpuCost', 0)
|
|
|
- result[alloc.name].ramCost += get(alloc, 'ramCost', 0)
|
|
|
- result[alloc.name].pvCost += get(alloc, 'pvCost', 0)
|
|
|
- result[alloc.name].networkCost += get(alloc, 'networkCost', 0)
|
|
|
- result[alloc.name].sharedCost += get(alloc, 'sharedCost', 0)
|
|
|
- result[alloc.name].externalCost += get(alloc, 'externalCost', 0)
|
|
|
- result[alloc.name].totalCost += get(alloc, 'totalCost', 0)
|
|
|
- result[alloc.name].cpuUseCoreHrs += get(alloc, 'cpuCoreUsageAverage', 0) * hrs
|
|
|
- result[alloc.name].cpuReqCoreHrs += get(alloc, 'cpuCoreRequestAverage', 0) * hrs
|
|
|
- result[alloc.name].ramUseByteHrs += get(alloc, 'ramByteUsageAverage', 0) * hrs
|
|
|
- result[alloc.name].ramReqByteHrs += get(alloc, 'ramByteRequestAverage', 0) * hrs
|
|
|
+ const hrs = get(alloc, "minutes", 0) / 60.0;
|
|
|
+
|
|
|
+ result[alloc.name].cpuCost += get(alloc, "cpuCost", 0);
|
|
|
+ result[alloc.name].gpuCost += get(alloc, "gpuCost", 0);
|
|
|
+ result[alloc.name].ramCost += get(alloc, "ramCost", 0);
|
|
|
+ result[alloc.name].pvCost += get(alloc, "pvCost", 0);
|
|
|
+ result[alloc.name].networkCost += get(alloc, "networkCost", 0);
|
|
|
+ result[alloc.name].sharedCost += get(alloc, "sharedCost", 0);
|
|
|
+ result[alloc.name].externalCost += get(alloc, "externalCost", 0);
|
|
|
+ result[alloc.name].totalCost += get(alloc, "totalCost", 0);
|
|
|
+ result[alloc.name].cpuUseCoreHrs +=
|
|
|
+ get(alloc, "cpuCoreUsageAverage", 0) * hrs;
|
|
|
+ result[alloc.name].cpuReqCoreHrs +=
|
|
|
+ get(alloc, "cpuCoreRequestAverage", 0) * hrs;
|
|
|
+ result[alloc.name].ramUseByteHrs +=
|
|
|
+ get(alloc, "ramByteUsageAverage", 0) * hrs;
|
|
|
+ result[alloc.name].ramReqByteHrs +=
|
|
|
+ get(alloc, "ramByteRequestAverage", 0) * hrs;
|
|
|
}
|
|
|
- })
|
|
|
- })
|
|
|
+ });
|
|
|
+ });
|
|
|
|
|
|
// If the range is of length > 1 (i.e. it is not just a single set) then
|
|
|
// compute efficiency for each result after accumulating.
|
|
|
if (allocationSetRange.length > 1) {
|
|
|
forEach(result, (alloc, name) => {
|
|
|
// If we can't compute total efficiency, it defaults to 0.0
|
|
|
- let totalEfficiency = 0.0
|
|
|
+ let totalEfficiency = 0.0;
|
|
|
|
|
|
// CPU efficiency is defined as (usage/request). If request == 0.0 but
|
|
|
// usage > 0, then efficiency gets set to 1.0.
|
|
|
- let cpuEfficiency = 0.0
|
|
|
+ let cpuEfficiency = 0.0;
|
|
|
if (alloc.cpuReqCoreHrs > 0) {
|
|
|
- cpuEfficiency = alloc.cpuUseCoreHrs / alloc.cpuReqCoreHrs
|
|
|
+ cpuEfficiency = alloc.cpuUseCoreHrs / alloc.cpuReqCoreHrs;
|
|
|
} else if (alloc.cpuUseCoreHrs > 0) {
|
|
|
- cpuEfficiency = 1.0
|
|
|
+ cpuEfficiency = 1.0;
|
|
|
}
|
|
|
|
|
|
// RAM efficiency is defined as (usage/request). If request == 0.0 but
|
|
|
// usage > 0, then efficiency gets set to 1.0.
|
|
|
- let ramEfficiency = 0.0
|
|
|
+ let ramEfficiency = 0.0;
|
|
|
if (alloc.ramReqByteHrs > 0) {
|
|
|
- ramEfficiency = alloc.ramUseByteHrs / alloc.ramReqByteHrs
|
|
|
+ ramEfficiency = alloc.ramUseByteHrs / alloc.ramReqByteHrs;
|
|
|
} else if (alloc.ramUseByteHrs > 0) {
|
|
|
- ramEfficiency = 1.0
|
|
|
+ ramEfficiency = 1.0;
|
|
|
}
|
|
|
|
|
|
// Compute efficiency as the cost-weighted average of CPU and RAM
|
|
|
// efficiency
|
|
|
- if ((alloc.cpuCost + alloc.ramCost) > 0.0) {
|
|
|
- totalEfficiency = ((alloc.cpuCost*cpuEfficiency)+(alloc.ramCost*ramEfficiency)) / (alloc.cpuCost + alloc.ramCost)
|
|
|
+ if (alloc.cpuCost + alloc.ramCost > 0.0) {
|
|
|
+ totalEfficiency =
|
|
|
+ (alloc.cpuCost * cpuEfficiency + alloc.ramCost * ramEfficiency) /
|
|
|
+ (alloc.cpuCost + alloc.ramCost);
|
|
|
}
|
|
|
|
|
|
- result[name].cpuEfficiency = cpuEfficiency
|
|
|
- result[name].ramEfficiency = ramEfficiency
|
|
|
- result[name].totalEfficiency = totalEfficiency
|
|
|
- })
|
|
|
+ result[name].cpuEfficiency = cpuEfficiency;
|
|
|
+ result[name].ramEfficiency = ramEfficiency;
|
|
|
+ result[name].totalEfficiency = totalEfficiency;
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- return result
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
// cumulativeToTotals adds each entry in the given AllocationSet (type: object)
|
|
|
// and returns a single Allocation (type: object) representing the totals
|
|
|
export function cumulativeToTotals(allocationSet) {
|
|
|
let totals = {
|
|
|
- name: 'Totals',
|
|
|
+ name: "Totals",
|
|
|
cpuCost: 0,
|
|
|
gpuCost: 0,
|
|
|
ramCost: 0,
|
|
|
@@ -108,177 +115,223 @@ export function cumulativeToTotals(allocationSet) {
|
|
|
cpuEfficiency: 0,
|
|
|
ramEfficiency: 0,
|
|
|
totalEfficiency: 0,
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
// Use these for computing efficiency. As such, idle will not factor into
|
|
|
// these numbers, including CPU and RAM cost.
|
|
|
- let cpuReqCoreHrs = 0
|
|
|
- let cpuUseCoreHrs = 0
|
|
|
- let ramReqByteHrs = 0
|
|
|
- let ramUseByteHrs = 0
|
|
|
- let cpuCost = 0
|
|
|
- let ramCost = 0
|
|
|
+ let cpuReqCoreHrs = 0;
|
|
|
+ let cpuUseCoreHrs = 0;
|
|
|
+ let ramReqByteHrs = 0;
|
|
|
+ let ramUseByteHrs = 0;
|
|
|
+ let cpuCost = 0;
|
|
|
+ let ramCost = 0;
|
|
|
|
|
|
forEach(allocationSet, (alloc, name) => {
|
|
|
// Accumulate efficiency-related fields
|
|
|
if (name !== "__idle__") {
|
|
|
- cpuReqCoreHrs += get(alloc, 'cpuReqCoreHrs', 0.0)
|
|
|
- cpuUseCoreHrs += get(alloc, 'cpuUseCoreHrs', 0.0)
|
|
|
- ramReqByteHrs += get(alloc, 'ramReqByteHrs', 0.0)
|
|
|
- ramUseByteHrs += get(alloc, 'ramUseByteHrs', 0.0)
|
|
|
- cpuCost += get(alloc, 'cpuCost', 0.0)
|
|
|
- ramCost += get(alloc, 'ramCost', 0.0)
|
|
|
+ cpuReqCoreHrs += get(alloc, "cpuReqCoreHrs", 0.0);
|
|
|
+ cpuUseCoreHrs += get(alloc, "cpuUseCoreHrs", 0.0);
|
|
|
+ ramReqByteHrs += get(alloc, "ramReqByteHrs", 0.0);
|
|
|
+ ramUseByteHrs += get(alloc, "ramUseByteHrs", 0.0);
|
|
|
+ cpuCost += get(alloc, "cpuCost", 0.0);
|
|
|
+ ramCost += get(alloc, "ramCost", 0.0);
|
|
|
}
|
|
|
|
|
|
// Sum cumulative fields
|
|
|
- totals.cpuCost += get(alloc, 'cpuCost', 0)
|
|
|
- totals.gpuCost += get(alloc, 'gpuCost', 0)
|
|
|
- totals.ramCost += get(alloc, 'ramCost', 0)
|
|
|
- totals.pvCost += get(alloc, 'pvCost', 0)
|
|
|
- totals.networkCost += get(alloc, 'networkCost', 0)
|
|
|
- totals.sharedCost += get(alloc, 'sharedCost', 0)
|
|
|
- totals.externalCost += get(alloc, 'externalCost', 0)
|
|
|
- totals.totalCost += get(alloc, 'totalCost', 0)
|
|
|
- })
|
|
|
+ totals.cpuCost += get(alloc, "cpuCost", 0);
|
|
|
+ totals.gpuCost += get(alloc, "gpuCost", 0);
|
|
|
+ totals.ramCost += get(alloc, "ramCost", 0);
|
|
|
+ totals.pvCost += get(alloc, "pvCost", 0);
|
|
|
+ totals.networkCost += get(alloc, "networkCost", 0);
|
|
|
+ totals.sharedCost += get(alloc, "sharedCost", 0);
|
|
|
+ totals.externalCost += get(alloc, "externalCost", 0);
|
|
|
+ totals.totalCost += get(alloc, "totalCost", 0);
|
|
|
+ });
|
|
|
|
|
|
// Compute efficiency
|
|
|
if (cpuReqCoreHrs > 0) {
|
|
|
- totals.cpuEfficiency = cpuUseCoreHrs / cpuReqCoreHrs
|
|
|
+ totals.cpuEfficiency = cpuUseCoreHrs / cpuReqCoreHrs;
|
|
|
} else if (cpuUseCoreHrs > 0) {
|
|
|
- totals.cpuEfficiency = 1.0
|
|
|
+ totals.cpuEfficiency = 1.0;
|
|
|
}
|
|
|
|
|
|
if (ramReqByteHrs > 0) {
|
|
|
- totals.ramEfficiency = ramUseByteHrs / ramReqByteHrs
|
|
|
+ totals.ramEfficiency = ramUseByteHrs / ramReqByteHrs;
|
|
|
} else if (ramUseByteHrs > 0) {
|
|
|
- totals.ramEfficiency = 1.0
|
|
|
+ totals.ramEfficiency = 1.0;
|
|
|
}
|
|
|
|
|
|
- if ((cpuCost + ramCost) > 0) {
|
|
|
- totals.totalEfficiency = ((cpuCost*totals.cpuEfficiency) + (ramCost*totals.ramEfficiency)) / (cpuCost + ramCost)
|
|
|
+ if (cpuCost + ramCost > 0) {
|
|
|
+ totals.totalEfficiency =
|
|
|
+ (cpuCost * totals.cpuEfficiency + ramCost * totals.ramEfficiency) /
|
|
|
+ (cpuCost + ramCost);
|
|
|
}
|
|
|
|
|
|
- totals.cpuReqCoreHrs = cpuReqCoreHrs
|
|
|
- totals.cpuUseCoreHrs = cpuUseCoreHrs
|
|
|
- totals.ramReqByteHrs = ramReqByteHrs
|
|
|
- totals.ramUseByteHrs = ramUseByteHrs
|
|
|
+ totals.cpuReqCoreHrs = cpuReqCoreHrs;
|
|
|
+ totals.cpuUseCoreHrs = cpuUseCoreHrs;
|
|
|
+ totals.ramReqByteHrs = ramReqByteHrs;
|
|
|
+ totals.ramUseByteHrs = ramUseByteHrs;
|
|
|
|
|
|
- return totals
|
|
|
+ return totals;
|
|
|
}
|
|
|
|
|
|
export function toVerboseTimeRange(window) {
|
|
|
- const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
|
|
-
|
|
|
- const start = new Date()
|
|
|
- start.setUTCHours(0, 0, 0, 0)
|
|
|
-
|
|
|
- const end = new Date()
|
|
|
- end.setUTCHours(0, 0, 0, 0)
|
|
|
+ const months = [
|
|
|
+ "January",
|
|
|
+ "February",
|
|
|
+ "March",
|
|
|
+ "April",
|
|
|
+ "May",
|
|
|
+ "June",
|
|
|
+ "July",
|
|
|
+ "August",
|
|
|
+ "September",
|
|
|
+ "October",
|
|
|
+ "November",
|
|
|
+ "December",
|
|
|
+ ];
|
|
|
+
|
|
|
+ const start = new Date();
|
|
|
+ start.setUTCHours(0, 0, 0, 0);
|
|
|
+
|
|
|
+ const end = new Date();
|
|
|
+ end.setUTCHours(0, 0, 0, 0);
|
|
|
|
|
|
switch (window) {
|
|
|
- case 'today':
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()}`
|
|
|
- case 'yesterday':
|
|
|
- start.setUTCDate(start.getUTCDate()-1)
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()}`
|
|
|
- case 'week':
|
|
|
- start.setUTCDate(start.getUTCDate()-start.getUTCDay())
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()} until now`
|
|
|
- case 'month':
|
|
|
- start.setUTCDate(1)
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()} until now`
|
|
|
- case 'lastweek':
|
|
|
- start.setUTCDate(start.getUTCDate()-(start.getUTCDay()+7))
|
|
|
- end.setUTCDate(end.getUTCDate()-(end.getUTCDay()+1))
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()} through ${end.getUTCDate()} ${months[end.getUTCMonth()]} ${end.getUTCFullYear()}`
|
|
|
- case 'lastmonth':
|
|
|
- end.setUTCDate(1)
|
|
|
- end.setUTCDate(end.getUTCDate()-1)
|
|
|
- start.setUTCDate(1)
|
|
|
- start.setUTCDate(start.getUTCDate()-1)
|
|
|
- start.setUTCDate(1)
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()} through ${end.getUTCDate()} ${months[end.getUTCMonth()]} ${end.getUTCFullYear()}`
|
|
|
- case '6d':
|
|
|
- start.setUTCDate(start.getUTCDate()-6)
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()} through now`
|
|
|
- case '29d':
|
|
|
- start.setUTCDate(start.getUTCDate()-29)
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()} through now`
|
|
|
- case '59d':
|
|
|
- start.setUTCDate(start.getUTCDate()-59)
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()} through now`
|
|
|
- case '89d':
|
|
|
- start.setUTCDate(start.getUTCDate()-89)
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()} through now`
|
|
|
+ case "today":
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()}`;
|
|
|
+ case "yesterday":
|
|
|
+ start.setUTCDate(start.getUTCDate() - 1);
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()}`;
|
|
|
+ case "week":
|
|
|
+ start.setUTCDate(start.getUTCDate() - start.getUTCDay());
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()} until now`;
|
|
|
+ case "month":
|
|
|
+ start.setUTCDate(1);
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()} until now`;
|
|
|
+ case "lastweek":
|
|
|
+ start.setUTCDate(start.getUTCDate() - (start.getUTCDay() + 7));
|
|
|
+ end.setUTCDate(end.getUTCDate() - (end.getUTCDay() + 1));
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()} through ${end.getUTCDate()} ${
|
|
|
+ months[end.getUTCMonth()]
|
|
|
+ } ${end.getUTCFullYear()}`;
|
|
|
+ case "lastmonth":
|
|
|
+ end.setUTCDate(1);
|
|
|
+ end.setUTCDate(end.getUTCDate() - 1);
|
|
|
+ start.setUTCDate(1);
|
|
|
+ start.setUTCDate(start.getUTCDate() - 1);
|
|
|
+ start.setUTCDate(1);
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()} through ${end.getUTCDate()} ${
|
|
|
+ months[end.getUTCMonth()]
|
|
|
+ } ${end.getUTCFullYear()}`;
|
|
|
+ case "6d":
|
|
|
+ start.setUTCDate(start.getUTCDate() - 6);
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()} through now`;
|
|
|
+ case "29d":
|
|
|
+ start.setUTCDate(start.getUTCDate() - 29);
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()} through now`;
|
|
|
+ case "59d":
|
|
|
+ start.setUTCDate(start.getUTCDate() - 59);
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()} through now`;
|
|
|
+ case "89d":
|
|
|
+ start.setUTCDate(start.getUTCDate() - 89);
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()} through now`;
|
|
|
}
|
|
|
|
|
|
- const splitDates = window.split(",")
|
|
|
+ const splitDates = window.split(",");
|
|
|
if (checkCustomWindow(window) && splitDates.length > 1) {
|
|
|
- let s = splitDates[0].split(/\D+/).slice(0, 3)
|
|
|
- let e = splitDates[1].split(/\D+/).slice(0, 3)
|
|
|
+ let s = splitDates[0].split(/\D+/).slice(0, 3);
|
|
|
+ let e = splitDates[1].split(/\D+/).slice(0, 3);
|
|
|
if (s.length === 3 && e.length === 3) {
|
|
|
- start.setUTCFullYear(s[0], s[1]-1, s[2])
|
|
|
- end.setUTCFullYear(e[0], e[1]-1, e[2])
|
|
|
+ start.setUTCFullYear(s[0], s[1] - 1, s[2]);
|
|
|
+ end.setUTCFullYear(e[0], e[1] - 1, e[2]);
|
|
|
if (start === end) {
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()}`
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()}`;
|
|
|
} else {
|
|
|
- return `${start.getUTCDate()} ${months[start.getUTCMonth()]} ${start.getUTCFullYear()} through ${end.getUTCDate()} ${months[end.getUTCMonth()]} ${end.getUTCFullYear()}`
|
|
|
+ return `${start.getUTCDate()} ${
|
|
|
+ months[start.getUTCMonth()]
|
|
|
+ } ${start.getUTCFullYear()} through ${end.getUTCDate()} ${
|
|
|
+ months[end.getUTCMonth()]
|
|
|
+ } ${end.getUTCFullYear()}`;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- return null
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
export function bytesToString(bytes) {
|
|
|
- const ei = Math.pow(1024, 6)
|
|
|
+ const ei = Math.pow(1024, 6);
|
|
|
if (bytes >= ei) {
|
|
|
- return `${round(bytes/ei, 1)} EiB`
|
|
|
+ return `${round(bytes / ei, 1)} EiB`;
|
|
|
}
|
|
|
- const pi = Math.pow(1024, 5)
|
|
|
+ const pi = Math.pow(1024, 5);
|
|
|
if (bytes >= pi) {
|
|
|
- return `${round(bytes/pi, 1)} PiB`
|
|
|
+ return `${round(bytes / pi, 1)} PiB`;
|
|
|
}
|
|
|
- const ti = Math.pow(1024, 4)
|
|
|
+ const ti = Math.pow(1024, 4);
|
|
|
if (bytes >= ti) {
|
|
|
- return `${round(bytes/ti, 1)} TiB`
|
|
|
+ return `${round(bytes / ti, 1)} TiB`;
|
|
|
}
|
|
|
- const gi = Math.pow(1024, 3)
|
|
|
+ const gi = Math.pow(1024, 3);
|
|
|
if (bytes >= gi) {
|
|
|
- return `${round(bytes/gi, 1)} GiB`
|
|
|
+ return `${round(bytes / gi, 1)} GiB`;
|
|
|
}
|
|
|
- const mi = Math.pow(1024, 2)
|
|
|
+ const mi = Math.pow(1024, 2);
|
|
|
if (bytes >= mi) {
|
|
|
- return `${round(bytes/mi, 1)} MiB`
|
|
|
+ return `${round(bytes / mi, 1)} MiB`;
|
|
|
}
|
|
|
- const ki = Math.pow(1024, 1)
|
|
|
+ const ki = Math.pow(1024, 1);
|
|
|
if (bytes >= ki) {
|
|
|
- return `${round(bytes/ki, 1)} KiB`
|
|
|
+ return `${round(bytes / ki, 1)} KiB`;
|
|
|
}
|
|
|
|
|
|
- return `${round(bytes, 1)} B`
|
|
|
+ return `${round(bytes, 1)} B`;
|
|
|
}
|
|
|
|
|
|
-const currencyLocale = "en-US"
|
|
|
+const currencyLocale = "en-US";
|
|
|
|
|
|
export function toCurrency(amount, currency, precision) {
|
|
|
if (typeof amount !== "number") {
|
|
|
- console.warn(`Tried to convert "${amount}" to currency, but it is not a number`)
|
|
|
- return ""
|
|
|
+ console.warn(
|
|
|
+ `Tried to convert "${amount}" to currency, but it is not a number`
|
|
|
+ );
|
|
|
+ return "";
|
|
|
}
|
|
|
|
|
|
if (currency === undefined || currency === "") {
|
|
|
- currency = "USD"
|
|
|
+ currency = "USD";
|
|
|
}
|
|
|
|
|
|
const opts = {
|
|
|
style: "currency",
|
|
|
currency: currency,
|
|
|
-
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
if (typeof precision === "number") {
|
|
|
- opts.minimumFractionDigits = precision
|
|
|
- opts.maximumFractionDigits = precision
|
|
|
+ opts.minimumFractionDigits = precision;
|
|
|
+ opts.maximumFractionDigits = precision;
|
|
|
}
|
|
|
|
|
|
return amount.toLocaleString(currencyLocale, opts);
|
|
|
@@ -286,11 +339,123 @@ export function toCurrency(amount, currency, precision) {
|
|
|
|
|
|
export function checkCustomWindow(window) {
|
|
|
// Example ISO interval string: 2020-12-02T00:00:00Z,2020-12-03T23:59:59Z
|
|
|
- const customDateRegex = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z,\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/
|
|
|
- return customDateRegex.test(window)
|
|
|
+ const customDateRegex =
|
|
|
+ /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z,\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/;
|
|
|
+ return customDateRegex.test(window);
|
|
|
}
|
|
|
|
|
|
+export function getCloudFilters(filters) {
|
|
|
+ const filterNamesMap = {
|
|
|
+ "invoice entity": "filterInvoiceEntityIDs",
|
|
|
+ provider: "filterProviders",
|
|
|
+ providerids: "filterProviderIDs",
|
|
|
+ service: "filterServices",
|
|
|
+ account: "filterAccountIDs",
|
|
|
+ };
|
|
|
+ const params = new URLSearchParams();
|
|
|
+ const labelFilters = [];
|
|
|
+
|
|
|
+ for (let filter of filters) {
|
|
|
+ const mapped = filterNamesMap[filter.property.toLowerCase()];
|
|
|
+
|
|
|
+ if (mapped) {
|
|
|
+ params.set(mapped, filter.value);
|
|
|
+ } else if (filter.property === "Labels") {
|
|
|
+ labelFilters.push(filter.value);
|
|
|
+ } else if (filter.property.startsWith(":")) {
|
|
|
+ labelFilters.push(`${filter.property.slice(6)}:${filter.value}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (labelFilters.length) {
|
|
|
+ params.set("filterLabels", labelFilters.join(","));
|
|
|
+ }
|
|
|
+
|
|
|
+ return `&${params.toString()}`;
|
|
|
+}
|
|
|
+
|
|
|
+export function formatSampleItemsForGraph({ data, costMetric }) {
|
|
|
+ const costMetricPropName = costMetric
|
|
|
+ ? costMetricToPropName[costMetric]
|
|
|
+ : "amortizedNetCost";
|
|
|
+ const graphData = data.sets.map(({ cloudCosts, window: { end, start } }) => {
|
|
|
+ return {
|
|
|
+ end,
|
|
|
+ items: Object.entries(cloudCosts).map(([name, item]) => ({
|
|
|
+ name,
|
|
|
+ value: item.netCost.cost,
|
|
|
+ })),
|
|
|
+ start,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ const accumulator = {};
|
|
|
+ data.sets.forEach(({ cloudCosts, window }) => {
|
|
|
+ Object.entries(cloudCosts).forEach(([name, cloudCostItem]) => {
|
|
|
+ const { properties } = cloudCostItem;
|
|
|
+ accumulator[name] ||= {
|
|
|
+ cost: 0,
|
|
|
+ start: "",
|
|
|
+ end: "",
|
|
|
+ providerID: "",
|
|
|
+ labelName: "",
|
|
|
+ kubernetesCost: 0,
|
|
|
+ kubernetesPercent: 0,
|
|
|
+ };
|
|
|
+ accumulator[name].cost += cloudCostItem[costMetricPropName].cost;
|
|
|
+ accumulator[name].kubernetesCost +=
|
|
|
+ cloudCostItem[costMetricPropName].cost *
|
|
|
+ cloudCostItem[costMetricPropName].kubernetesPercent;
|
|
|
+ accumulator[name].start = window.start;
|
|
|
+ accumulator[name].end = window.end;
|
|
|
+ accumulator[name].providerID = properties.providerID;
|
|
|
+ accumulator[name].labelName = properties.labels?.name;
|
|
|
+ accumulator[name].kubernetesPercent =
|
|
|
+ cloudCostItem[costMetricPropName].kubernetesPercent;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ const tableRows = Object.entries(accumulator).map(
|
|
|
+ ([
|
|
|
+ name,
|
|
|
+ {
|
|
|
+ cost,
|
|
|
+ start,
|
|
|
+ end,
|
|
|
+ providerID,
|
|
|
+ kubernetesCost,
|
|
|
+ kubernetesPercent,
|
|
|
+ labelName,
|
|
|
+ },
|
|
|
+ ]) => ({
|
|
|
+ cost,
|
|
|
+ name,
|
|
|
+ kubernetesCost,
|
|
|
+ kubernetesPercent,
|
|
|
+ start,
|
|
|
+ end,
|
|
|
+ providerID,
|
|
|
+ labelName,
|
|
|
+ })
|
|
|
+ );
|
|
|
+
|
|
|
+ const tableTotal = tableRows.reduce(
|
|
|
+ (tr1, tr2) => ({
|
|
|
+ ...tr1,
|
|
|
+ cost: tr1.cost + tr2.cost,
|
|
|
+ kubernetesCost: tr1.kubernetesCost + tr2.kubernetesCost,
|
|
|
+ }),
|
|
|
+ {
|
|
|
+ cost: 0,
|
|
|
+ name: "",
|
|
|
+ kubernetesCost: 0,
|
|
|
+ kubernetesPercent: 0,
|
|
|
+ end: "",
|
|
|
+ start: "",
|
|
|
+ labelName: "",
|
|
|
+ providerID: "",
|
|
|
+ }
|
|
|
+ );
|
|
|
|
|
|
+ return { graphData, tableRows, tableTotal };
|
|
|
+}
|
|
|
|
|
|
export default {
|
|
|
rangeToCumulative,
|
|
|
@@ -299,4 +464,4 @@ export default {
|
|
|
bytesToString,
|
|
|
toCurrency,
|
|
|
checkCustomWindow,
|
|
|
-}
|
|
|
+};
|