ibmapm-restclient
Version:
Node.js rest client for ICAM.
629 lines (586 loc) • 19.6 kB
JavaScript
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: ibmapm
// This file is licensed under the Apache License 2.0.
// License text available at https://opensource.org/licenses/Apache-2.0
;
var fs = require('fs');
var sender = require('./sender-queue');
var pluginconfig = require('./config').pluginConfig;
var logger = require('../plugins/logutil').getLogger('httpsender.js');
var k8sutil = require('../tools/k8sutil');
var logutil = require('../plugins/logutil');
var rcutil = require('../plugins/util');
pluginconfig.loadPluginsConf(__dirname + '/../../etc/config.json');
var queue;
var cfg = {
tenantID: 'tenantid-0000-0000-0000-000000000000',
metrics: 'metric',
AAR: 'aar/middleware',
ADR: 'adr/middleware'
};
var dcId; // string
var resourceEntities = {}; // {<resourceid>:<entityid>, ...}
var relationships = {}; // {<resourceid>:[{type:<linktype>,to:<toresourceid>}], ...}
module.exports.getK8stool = function() {
return k8sutil;
};
module.exports.getLogUtil = function() {
return logutil;
};
module.exports.getRestclientUtil = function() {
return rcutil;
};
module.exports.checkReadyStatus = function(callback) {
pluginconfig.consumerInsts.forEach(function(inst) {
var name = inst.Name();
inst.checkReadyStatus(function(initialized_status) {
logger.debug(name + ' initialized = ' + initialized_status);
if (initialized_status) {
callback();
}
});
});
return;
};
module.exports.stop = function() {
sender.stopQueue();
};
module.exports.updateLoglevel = function(level) {
var logutil = require('../plugins/logutil.js');
logutil.updateLogLevel(level);
};
module.exports.setConfiguration = function(fileName, callback) {
var tempCfg;
logger.debug('Load configuration files: ', fileName);
var file = process.env.KNJ_CONFIG_FILE || fileName;
try {
if (fs.existsSync(file)) {
var confString = fs.readFileSync(file, 'utf8');
tempCfg = JSON.parse(confString);
cfg = tempCfg;
if (!cfg.metrics) {
cfg.metrics = 'metric';
}
if (!cfg.AAR) {
cfg.AAR = 'aar/middleware';
}
if (!cfg.ADR) {
cfg.ADR = 'adr/middleware';
}
if (cfg.proxy) {
process.env.KNJ_PROXY = cfg.proxy;
}
} else {
logger.debug('No configuration file is set by KNJ_CONFIG_FILE');
}
} catch (e) {
logger.error('register_topology set cofniguration failed.');
logger.error(e);
}
if (process.env.IBAM_TENANT_ID) {
cfg.tenantID = process.env.IBAM_TENANT_ID;
}
logger.debug('Configuration loaded ', cfg);
if (callback && !global.AM_SERVICE_BOUND) {
logger.debug('No backend BAM service, call the callback ', callback.name);
callback();
}
};
module.exports.getConfiguration = function() {
return cfg;
};
module.exports._writeRegistryToFile = function() {
try {
var filename = './' + dcId + '.json';
var fileContent = JSON.stringify({
resourceEntities: resourceEntities,
relationships: relationships
});
fs.writeFileSync(filename, fileContent, 'utf8');
} catch (e) {
logger.error('write registry to file failed');
logger.error(e);
}
};
module.exports._readRegistryFromFile = function() {
try {
var filename = './' + dcId + '.json';
var fileContent = fs.readFileSync(filename, 'utf8');
var jsonContent = JSON.parse(fileContent);
resourceEntities = jsonContent.resourceEntities;
relationships = jsonContent.relationships;
return jsonContent;
} catch (e) {
logger.error('read registry to file failed');
logger.error(e);
}
};
module.exports.getDC = function(id, callback) {
logger.debug('getDC');
if (!queue) {
queue = sender.getQueue('bam');
}
queue.addTask({
keyIndexName: id,
type: 'queryDc:',
callback: callback
});
};
module.exports.getResource = function(obj, callback) {
logger.debug('getResource');
if (!queue) {
queue = sender.getQueue('bam');
}
queue.addTask({
uid: obj.id,
type: 'queryResource:',
callback: callback
});
};
module.exports.queryRelationship = function(id, callback) {
logger.debug('queryRelationship');
if (!queue) {
queue = sender.getQueue('bam');
}
queue.addTask({
id: id,
type: 'queryRelationship:',
callback: callback
});
};
module.exports.getConfiguration = function(callback) {
logger.debug('getConfiguration');
if (!queue) {
queue = sender.getQueue('bam');
}
queue.addTask({
keyIndexName: dcId,
type: 'queryConfiguration:',
callback: callback
});
};
module.exports.registerDC = function(obj, callback) {
logger.debug('registerDC', obj);
if (!queue) {
queue = sender.getQueue('bam');
}
var payload = {
keyIndexName: obj.id,
entityTypes: obj.type,
startedTime: obj.startTime || (new Date()).toISOString(), // '2016-05-27T03:21:25.432Z'
deployment: obj.deployment
};
if (obj.references && obj.references.length > 0) {
var references = [];
for (var ref in obj.references) {
var item = obj.references[ref];
var ref_item = {
_edgeType: item.type
};
ref_item['_' + item.direction + 'Uid'] = item.id;
references.push(ref_item);
}
payload['_references'] = references;
}
for (var prop in obj.properties) { // merge properties
payload[prop] = obj.properties[prop];
}
dcId = obj.id;
queue.addTask({
payload: payload,
type: 'dc:',
callback: callback
});
};
function genRef(refs) {
let references = [];
for (var ref in refs) {
var item = refs[ref];
var ref_item = {
_edgeType: item.type
};
if (item.matchTokens) {
ref_item.matchTokens = item.matchTokens;
}
if (item.id) {
ref_item['_' + item.direction + 'Uid'] = item.id;
}
if (item.pid) {
ref_item['_' + item.direction + 'Id'] = item.pid;
}
references.push(ref_item);
}
return references;
}
module.exports.registerAppResource = function(obj, callback) {
logger.debug('register Application Resource ', obj);
if (!obj.type || !obj.id || !obj.properties) {
logger.error('registerResource payload is not complete, must have: ' +
'id, type and properties');
return;
}
if (!queue) {
queue = sender.getQueue('bam');
}
var payload = { // merge public attributes
uid: obj.id,
entityTypes: obj.type,
// type: obj.type[0],
deployment: obj.deployment
};
if (obj.references && obj.references.length > 0) {
payload['_references'] = genRef(obj.references);
}
for (var prop in obj.properties) { // merge properties
payload[prop] = obj.properties[prop];
}
queue.addTask({
payload: payload,
type: 'resources: ' + payload.entityTypes,
callback: callback
});
};
module.exports.registerResource = function(obj, callback) {
logger.debug('register Resource ', obj);
if (!obj.type || !obj.id || !obj.properties) {
logger.error('registerResource payload is not complete, must have: ' +
'id, type and properties');
return;
}
if (!queue) {
queue = sender.getQueue('bam');
}
var payload = { // merge public attributes
uid: obj.id,
entityTypes: obj.type,
// type: obj.type[0],
deployment: obj.deployment
};
if (obj.VersionDependencies) {
payload['VersionDependencies'] = obj.VersionDependencies;
}
if (obj.references && obj.references.length > 0) {
payload['_references'] = genRef(obj.references);
}
for (var prop in obj.properties) { // merge properties
payload[prop] = obj.properties[prop];
}
queue.addTask({
payload: payload,
callback: callback,
type: 'resources: ' + payload.entityTypes
});
};
module.exports.updateResource = function(obj, loc, callback) {
logger.debug('update Resource ', obj);
if (!obj.type || !obj.id || !obj.properties || !loc) {
logger.error('updateResource payload is not complete, must have: ' +
'location, id, type and properties');
return;
}
if (!queue) {
queue = sender.getQueue('bam');
}
var payload = { // merge public attributes
entityTypes: obj.type,
deployment: obj.deployment
};
if (obj.VersionDependencies) {
payload['VersionDependencies'] = obj.VersionDependencies;
}
if (obj.references && obj.references.length > 0) {
payload['_references'] = genRef(obj.references);
}
for (var prop in obj.properties) { // merge properties
payload[prop] = obj.properties[prop];
}
queue.addTask({
location: loc,
payload: payload,
callback: callback,
type: 'updateResources: ' + payload.entityTypes
});
};
module.exports.postDCConfiguration = function(payload, type, callback) {
queue.addTask({
payload: payload,
type: 'dcconfig: ',
entityType: type,
additionalHeader: {
version: global.DC_VERSION,
providerUniqueId: dcId,
entityType: type
},
callback: callback
});
};
module.exports.postSituationConfiguration = function(payload, callback) {
queue.addTask({
payload: payload,
type: 'situation: ',
callback: callback
});
};
module.exports.sendMetrics = function(payload, callback) {
logger.debug('sendMetrics ', JSON.stringify(payload));
if (!queue) {
queue = sender.getQueue('bam');
}
if (payload instanceof Array) {
var timestamp = (new Date()).toISOString();
for (var index = 0; index < payload.length; index++) {
if (payload[index].hasOwnProperty('APP_NAME')) {
continue; // ignore checking for additional items for BI payload
}
if (process.env.UA_LWDC_LISTENER_URL) {
if (!payload[index].measurement || !payload[index].tags ||
!payload[index].fields) {
logger.warn('sendMetrics payload is not complete, must have: ' +
'measurement, tags and fields');
return;
}
for (const key in payload[index].fields) {
if (payload[index].fields[key] === null ||
payload[index].fields[key] === undefined) {
logger.debug(key, 'The metric value is ',
payload[index].fields[key], ', will skip this.');
return;
}
}
for (const key in payload[index].tags) {
if (payload[index].tags[key].includes('undefined')) {
logger.debug(key, 'The tags value is ',
payload[index].tags[key], ' contains undefined string, will skip this.');
return;
}
}
} else {
if (!payload[index].resourceID || !payload[index].tags ||
!payload[index].metrics) {
logger.warn('sendMetrics payload is not complete, must have: ' +
'resourceID, tags and metrics');
return;
}
for (const key in payload[index].metrics) {
if (payload[index].metrics[key] === null ||
payload[index].metrics[key] === undefined) {
logger.debug(key, 'The metric value is ',
payload[index].metrics[key], ', will skip this.');
return;
}
}
}
if (!payload[index].timestamp) {
payload[index].timestamp = timestamp;
}
}
} else {
if (process.env.UA_LWDC_LISTENER_URL) {
if (!payload.measurement || !payload.tags || !payload.fields) {
logger.warn('sendMetrics payload is not complete, must have: ' +
'measurement, tags and fields');
return;
}
for (const key in payload.fields) {
if (payload.fields.hasOwnProperty(key)) {
if (payload.fields[key] === null ||
payload.fields[key] === undefined) {
logger.debug(key, 'The metric value is ',
payload.fields[key], ', will skip this.');
return;
}
}
}
for (const key in payload.tags) {
if (payload.tags.hasOwnProperty(key)) {
if (payload.tags[key].includes('undefined')) {
logger.debug(key, 'The tags value is ',
payload.tags[key], ' contains undefined string, will skip this.');
return;
}
}
}
} else {
if (!payload.resourceID || !payload.tags || !payload.metrics) {
logger.warn('sendMetrics payload is not complete, must have: ' +
'resourceID, tags and metrics');
return;
}
for (const key in payload.metrics) {
if (payload.metrics.hasOwnProperty(key)) {
if (payload.metrics[key] === null ||
payload.metrics[key] === undefined) {
logger.debug(key, 'The metric value is ',
payload.metrics[key], ', will skip this.');
return;
}
}
}
}
if (!payload.timestamp) {
payload.timestamp = (new Date()).toISOString();
}
}
queue.addTask({
payload: payload,
type: 'metrics: ',
callback: callback
});
};
var aarBatch = {
payload: [],
committed: false
};
module.exports.sendAAR = function(payload, callback, batched) {
logger.debug('sendAAR', JSON.stringify(payload));
if (!payload.properties || !payload.metrics) {
logger.error('sendAAR payload is not complete, must have: properties and metrics');
return;
}
if (!dcId) {
callback({message: 'dcId is not ready'});
return;
}
if (!queue) {
queue = sender.getQueue('bam');
}
if (!batched) {
queue.addTask({
payload: payload,
type: 'aar:',
callback: callback
});
return;
}
if (payload.properties.originID) {
delete payload.properties.originID;
}
payload.properties['tenantID'] = cfg.tenantID;
// Meet Patch Condition KNJ_AAR_BATCH_FREQ, then put into task queue
if (aarBatch.payload.length === 0) {
aarBatch.committed = false;
let timeoutObj = setTimeout(
function() {
if (aarBatch.payload.length > 0) {
queue.addTask({
payload: aarBatch.payload,
type: 'aar: batched',
callback: callback
});
}
aarBatch.payload = [];
aarBatch.committed = true;
},
global.KNJ_AAR_BATCH_FREQ * 1000
);
timeoutObj.unref();
}
if (!aarBatch.committed) {
aarBatch.payload.push(payload);
}
// Meet Patch Condition KNJ_AAR_BATCH_COUNT, then put into task queue
if (aarBatch.payload.length >= global.KNJ_AAR_BATCH_COUNT) {
queue.addTask({
payload: aarBatch.payload,
type: 'aar: batched',
callback: callback
});
aarBatch.committed = true;
aarBatch.payload = [];
}
};
var adrBatch = {
payload: [],
committed: false
};
module.exports.sendADR = function(payload, callback) {
logger.debug('sendADR', JSON.stringify(payload));
if (!payload.properties || !payload.statistics) {
logger.error('sendADR payload is not complete, must have: properties and statistics');
return;
}
if (!dcId) {
callback({message: 'dcId is not ready'});
} else {
if (!queue) {
queue = sender.getQueue('bam');
}
payload.properties['originID'] = global.KNJ_BAM_ORIGINID;
payload.properties['tenantID'] = cfg.tenantID;
// Meet Patch Condition KNJ_ADR_BATCH_FREQ, then put into task queue
if (adrBatch.payload.length === 0) {
adrBatch.committed = false;
let timeoutObj = setTimeout(
function() {
if (adrBatch.payload.length > 0) {
queue.addTask({
payload: adrBatch.payload,
type: 'adr: batched',
callback: callback
});
}
adrBatch.payload = [];
adrBatch.committed = true;
},
global.KNJ_ADR_BATCH_FREQ * 1000
);
timeoutObj.unref();
}
if (!adrBatch.committed) {
adrBatch.payload.push(payload);
}
if (adrBatch.payload.length >= global.KNJ_ADR_BATCH_COUNT) {
queue.addTask({
payload: adrBatch.payload,
type: 'adr: batched',
callback: callback
});
adrBatch.payload = [];
adrBatch.committed = true;
}
}
};
module.exports.sendJSO = function(payload, callback) {
logger.debug('sendJSO');
if (!queue) {
queue = sender.getQueue('bam');
}
queue.addTask({
payload: payload,
type: 'jso: ',
callback: callback
});
};
// Deprecated: applicationMgmt has removed it
module.exports.sendNotify = function(payload, callback) {
queue.addTask({
payload: payload,
type: 'rteNotify: ',
keyIndexName: dcId,
callback: callback
});
};
// the type should be value of PluginConfig.prototype.queuetypes
module.exports.send = function(payload, type, callback) {
if (!queue) {
queue = sender.getQueue('bam');
}
if (type === pluginconfig.queuetypes.DC) {
this.registerDC(payload, callback);
}
if (type === pluginconfig.queuetypes.RESOURCE) {
this.registerResource(payload, callback);
}
if (type === pluginconfig.queuetypes.METRICS) {
this.sendMetrics(payload, callback);
}
if (type === pluginconfig.queuetypes.AAR) {
this.sendAAR(payload, callback);
}
if (type === pluginconfig.queuetypes.ADR) {
this.sendADR(payload, callback);
}
if (type === pluginconfig.queuetypes.JSO) {
this.sendJSO(payload, callback);
}
};