@trusthab/composable-resources
Version:
migrating https://github.com/knetikmedia/hab-api/tree/integration/app/resources/composable
285 lines (254 loc) • 6.98 kB
JavaScript
const Mustache = require('mustache');
const _ = require('lodash');
const composer = require('../mixin_loader');
const DEFAULT_OPERATOR = '>';
const OPERATIONS = {
'==': (a, b) => a === b,
'!=': (a, b) => a !== b,
'>': (a, b) => a > b,
'<': (a, b) => a < b,
'>=': (a, b) => a >= b,
'<=': (a, b) => a <= b
};
const SUPPORTED_COMPARISON_OPERATORS = Object.keys(OPERATIONS);
module.exports = (App) => {
class MetricResource {
static mixins() {
return [
// Functionality
'Validatable',
'Templatable',
// ORMish
'Persistable',
'KnetikCloudPersistence'
];
}
static simpleProperties() {
return true;
}
static fields() {
return {
template: {
type: 'text',
schema_ignore: true
},
id: {
type: 'integer',
or: ['null'],
path: 'id'
},
location_id: {
type: 'text',
or: ['null'],
path: 'data.location_id'
},
location_type: {
type: 'text',
path: 'data.location_type'
},
name: {
type: 'text',
or: ['null'],
path: 'name'
},
machine_name: {
type: 'text',
or: ['null'],
path: 'data.machine_name'
},
category: {
type: 'text',
or: ['null'],
path: 'data.category'
},
alerts_enabled: {
type: 'boolean',
path: 'data.alerts_enabled'
},
enabled: {
type: 'boolean',
path: 'data.enabled'
},
alert_period: {
type: 'integer',
path: 'data.alert_period'
},
threshold_info: {
type: 'double',
path: 'data.threshold_info'
},
threshold_warning: {
type: 'double',
path: 'data.threshold_warning'
},
threshold_urgent: {
type: 'double',
path: 'data.threshold_urgent'
},
threshold_critical: {
type: 'double',
path: 'data.threshold_critical'
},
show_total: {
type: 'boolean',
or: ['null'],
path: 'data.show_total'
},
display_order: {
type: 'integer',
or: ['null'],
path: 'data.display_order'
},
status: {
type: 'text',
or: ['null'],
path: 'status',
get_method: 'getStatus'
},
value: {
type: 'float',
get_method: 'getValue'
},
total: {
type: 'float',
get_method: 'getTotal'
},
operator: {
type: 'text',
or: ['null'],
path: 'data.operator'
},
expression_template: {
type: 'text',
or: ['null'],
path: 'data.expression_template'
},
expression: {
type: 'text',
or: ['null'],
get_method: 'getExpression'
},
precision: {
type: 'integer',
or: ['null'],
path: 'data.precision'
},
editable: {
type: 'boolean',
or: ['null'],
path: 'data.editable'
},
diagnostic_url: {
type: 'text',
or: ['null'],
get_method: 'getDiagnosticUrl'
},
created_at: {
type: 'integer',
or: ['null'],
path: 'created_date'
},
updated_at: {
type: 'integer',
or: ['null'],
path: 'updated_date'
},
unit: {
type: 'text',
or: ['null'],
path: 'data.unit'
},
ymin: {
type: 'integer',
or: ['null'],
path: 'data.ymin'
},
ymax: {
type: 'integer',
or: ['null'],
path: 'data.ymax'
},
version: {
type: 'integer',
or: ['null'],
path: 'data.version'
}
};
}
getExpression(threshold) {
const { machine_name, location_type } = this;
const expression_template = _.get(this._delegate, 'data.expression_template');
const params = { app_id: App.app_id };
if (this.location_id) {
params[`${location_type}_id`] = this.location_id;
}
let param_str = '';
param_str = Object.keys(params).map((key) => {
const val = params[key];
return `${key}="${val}"`;
}).join(',');
param_str = `{ ${param_str} }`;
const properties = {
param_str,
machine_name
};
if (threshold) {
properties.operator = this.operator;
properties.threshold = threshold;
}
return Mustache.render(expression_template, properties);
}
getDiagnosticUrl() {
const query = encodeURIComponent(this.getExpression());
const host = process.env.PROMETHEUS_API_HOST.replace('api/v1', 'graph');
return `${host}?g0.range_input=1h&g0.expr=${query}&g0.tab=0`;
}
getTotal() {
const total = this.get('total');
return this.show_total ? total : '--';
}
getValue() {
const value = this.get('value');
return _.isFinite(value) ? value : '--';
}
getStatus() {
const { enabled, alerts_enabled, value } = this;
const operator = SUPPORTED_COMPARISON_OPERATORS.includes(this.operator) ? this.operator : DEFAULT_OPERATOR;
if (!enabled) { return null; }
if (!alerts_enabled || !_.isFinite(value)) { return 'none'; }
const { threshold_critical, threshold_urgent, threshold_warning, threshold_info } = this;
if (_.isFinite(threshold_critical) && OPERATIONS[operator](value, threshold_critical)) { return 'critical'; }
if (_.isFinite(threshold_urgent) && OPERATIONS[operator](value, threshold_urgent)) { return 'urgent'; }
if (_.isFinite(threshold_warning) && OPERATIONS[operator](value, threshold_warning)) { return 'warning'; }
if (_.isFinite(threshold_info) && OPERATIONS[operator](value, threshold_info)) { return 'info'; }
return 'none';
}
static knetikCloudMethods() {
return {
search: {
index: 'objects',
template: 'alarms'
},
find: {
api: 'ObjectsApi',
method: 'getObjectItem',
paramsBuilder: id => ['alarms', id]
},
create: {
api: 'ObjectsApi',
method: 'createObjectItem',
paramsBuilder: params => ['alarms', { objectItem: params }]
},
update: {
api: 'ObjectsApi',
method: 'updateObjectItem',
paramsBuilder: (id, params) => ['alarms', id, { objectItem: params }]
}
};
}
static customFilters() {
return require('./metric_filters')(App);
}
}
return composer(MetricResource, App);
};