-
Notifications
You must be signed in to change notification settings - Fork 86
Create a Plan
Measures and metrics are grouped into a single entity called a plan. Plans provide Resource providers with a way to express the relationship between the measures and metrics. For example, if one needs two measures in order to be able to calculate the value of a metric, it is possible to group the two measures and the metric into a metering plan.
Based on what the plan is responsible for, there are three plan categories: metering, rating, and pricing.
The metering plan defines the metering part of the calculations that Abacus will execute. meter
, accumulate
, and aggregate
functions can be used with a metering plan. For example, consider the object storage metering plan.
The rating plan defines the rating calculations. The charge
and rate
functions can be used with a metering plan. For example, see object storage rating plan.
The pricing plan defines the pricing on per-measure basis. For example, check the object storage pricing plan.
There are a few predefined plans available in Abacus. You can find the examples with the metrics contained for each plan below:
-
object storage
- storage space
- number of API calls
-
basic analytics
- average number of instances
- number of API calls
-
linux container
- memory usage [GB/h]
Note: The basic analytics metrics use deprecated formulas and you can use them as a reference on how to migrate from the formulas to the new functions format.
By default Abacus defines default functions. You can choose to override them by defining your own function with the same name or to work with the default one.
const meter = (metricName) => (measures) => measures[metricName];
const accumulate = (a, qty, start, end, from, to, twCell) =>
end < from || end >= to ? null : new BigNumber(a || 0).add(qty || 0).toNumber();
const aggregate = (a, prev, curr, aggTwCell, accTwCell) =>
new BigNumber(a || 0)
.add(curr)
.sub(prev || 0)
.toNumber();
const summarize = (t, qty) => qty ? qty : 0;
By default the meter
function uses measure with the same name. The accumulate
and aggregate
functions do simple sum. summarize
returns the sum.
const rate = (p, qty) => new BigNumber(p || 0).mul(qty).toNumber();
const charge = (t, cost) => cost ? cost : 0;
Calculates Max value of agent_count
measure.
{
"plan_id": "max_value",
"measures": [
{
"name": "agent_count",
"unit": "number"
}
],
"metrics": [
{
"name": "users",
"unit": "users",
"type": "discrete",
"meter": "(m) => new BigNumber(m.agent_count || 0).toNumber()",
"accumulate": "((a, qty, start, end, from, to, twCell) => end < from || end >= to ? null : Math.max(a, qty))"
}
]
}
Abacus does not support average
out of the box, but this is easily implemented by keeping the sum and the count of elements in compound object. This also increases the accuracy of the result.
{
"plan_id": "average_value",
"measures": [
{
"name": "store",
"unit": "BYTE"
}
],
"metrics": [
{
"name": "store",
"unit": "GIGABYTE",
"type": "discrete",
"meter": "(m) => new BigNumber(m.store || 0).div(1073741824).toNumber()",
"accumulate": "(a, current) => a ? { sum: a.sum + current, count: a.count + 1 } : { sum: current, count: 1 }",
"aggregate": "(a, previous, current) => current",
"summarize": "(t, qty) => qty ? new BigNumber(qty.sum).div(qty.count).toNumber() : 0"
}
]
}
🚨 Note that this plan bypasses the aggregation. If the resource is used by applications in different spaces, we'll not take this into account. Usually this is the case for DB or storage solutions.
Here we are summing several kinds of transactions (charges
, refunds
, others
) into individual metrics. Then we have a global sum transactions that count the number of all operations. We want to keep a breakdown of the individual components, plus the total count of operations.
{
plan_id: 'transactions-plan',
measures: [
{
name: 'charges',
unit: 'NUMBER'
},
{
name: 'refunds',
unit: 'NUMBER'
},
{
name: 'others',
unit: 'NUMBER'
}
],
metrics: [{
name: 'transactions',
unit: 'NUMBER',
type: 'discrete',
meter: (m) => ({
charges: new BigNumber(m.charges || 0).toNumber(),
refunds: new BigNumber(m.refunds || 0).toNumber(),
others: new BigNumber(m.others || 0).toNumber()
}),
accumulate: (a, c) => {
const charges = a ? new BigNumber(a.charges).add(c.charges) : c.charges
const refunds = a ? new BigNumber(a.refunds).add(c.refunds) : c.refunds;
const others = a ? new BigNumber(a.others).add(c.others) : c.others;
const transactions = a ?
a.transactions.add(charges).add(refunds).add(others) :
new BigNumber(0).add(charges).add(refunds).add(others);
return {
charges: charges.toNumber(),
refunds: refunds.toNumber(),
others: others.toNumber(),
transactions: transactions.toNumber()
};
}
}]
}
{
"plan_id": "average_and_sum",
"measures": [
{
"name": "storage",
"unit": "GIGABYTE"
}
],
"metrics": [
{
"meter" : "(m) => new BigNumber(m.storage || 0).toNumber()",
"accumulate" : "(a, current) => a ? { sum: a.sum + current, count: a.count + 1 } : { sum: current, count: 1 }",
"aggregate" : "(a, previous, current) => current",
"summarize" : "(t, qty) => qty ? new BigNumber(qty.sum).div(qty.count).toNumber() : 0",
"type" : "discrete",
"name" : "average",
"unit" : "GIGABYTE"
},
{
"meter" : "(m) => new BigNumber(m.storage || 0).toNumber()",
"type" : "discrete",
"name" : "sum",
"unit" : "GIGABYTE"
}
]
}
<< Create a Resource Provider | Upload Plan >> |
---|
ABOUT | RESOURCE PROVIDER | ABACUS INTEGRATOR
*Abacus icon made by Freepik from www.flaticon.com