Name

sn_cimaf.CIMetricEngineSNC

Description

No description available

Script

var CIMetricEngineSNC = Class.create();
CIMetricEngineSNC.prototype = {
  initialize: function() {},

  TABLES: {
  	CI_METRIC: 'sn_cimaf_metric',
  	COLLECTION_RULE: "sn_cimaf_collection_rule",
  	COLLECTION_RULE_METRICS_ASSOCIATION: "sn_cimaf_collection_rule_metric_asscn",
  	ADAPTER_CONFIG: "sn_cimaf_adapter_config",
  	ADAPTER_APPLICABILITY_RULE: "sn_cimaf_adapter_applicability_rule",
  	CMDB_CI: "cmdb_ci",
  	METRIC_DEFINITION: "sn_cimaf_metric_definition"
  },

  CI_AVAILABILITY_EXT_POINT: "sn_cimaf.CIAvailabilityHandler",
  DEFAULT_METRIC_LIMIT : 50,

  FIELDS: {
  	ADAPTER_CONFIG: {
  		metric_definition: "metric_definition",
  		query_flow: "query_flow",
  		query_script: "query_script",
  		order: "order"
  	},
  	ADAPTER_APPLICABILITY_RULE: {
  		adapter_config: "adapter_config",
  		ci_class: "ci_class"
  	},
  	COLLECTION_RULE: {
  		source_table: "source_table",
  		match_ci_extensions: "match_ci_extensions"
  	},
  	COLLECTION_RULE_METRICS_ASSOCIATION: {
  		collection_rule: "collection_rule"
  	}
  },

  QUERY_ACTION_TYPE: {
  	FLOW: "flow",
  	SCRIPT: "script"
  },
  
  // empty states mentioned below are in the order they are being evaluated
  EMPTY_STATES: {
  	NO_ADAPTER_CONFIG: "NO_ADAPTER_CONFIG",
  	PROVIDER_UNAVAILABLE: "PROVIDER_UNAVAILABLE",
  	CI_OFFLINE: "CI_OFFLINE",
  	NO_CI_ASSOCIATED: "NO_CI_ASSOCIATED",
  	NO_PRIMARY_CI: "NO_PRIMARY_CI",
  	NO_SUPPORTED_CI: "NO_SUPPORTED_CI",
  	NO_INITIAL_METRICS: "NO_INITIAL_METRICS",
  	NO_RECENT_METRICS: "NO_RECENT_METRICS"
  },

  /**
   * returns Sys Id of new metric record
   * @param String cmdbCiSysId - configuration item sysId
   * @param String metricDefinitionSysId - metric Definition SysId
   * @param String metricData - payload for metric record
   * @param GlideDateTime timestamp - Timestamp related to metric data
   * @return String metricSysId
   */

  createMetric: function(cmdbCiSysId, metricDefinitionSysId, metricData, timestamp) {
  	if (!cmdbCiSysId || !metricDefinitionSysId || !metricData || !timestamp) {
  		gs.error("The passed parameters are null or invalid");
  		return null;
  	}

  	var metricGr = new GlideRecord(this.TABLES.CI_METRIC);
  	metricGr.initialize();

  	metricGr.setValue('configuration_item', cmdbCiSysId);
  	metricGr.setValue('metric_definition', metricDefinitionSysId);
  	metricGr.setValue('payload', metricData);
  	metricGr.setValue('timestamp', timestamp);

  	return metricGr.insert();
  },

  _getMetricData: function(cmdbCiSysId, metricDefinition, pageOffset, metricLimit, start, end, orderDesc) {
  	var res = {};
  	var data = [];
  	var count = 0;

  	if (!cmdbCiSysId || !metricDefinition) {
  		gs.error("The value provided for configurationItem or metricDefinition is invalid");
  		return res;
  	}

  	pageOffset = (!gs.nil(pageOffset) && typeof pageOffset === 'number') ? pageOffset : 0;
  	metricLimit = (!gs.nil(metricLimit) && typeof metricLimit === 'number') ? metricLimit : this.DEFAULT_METRIC_LIMIT;
  	orderDesc = (!gs.nil(orderDesc) && typeof orderDesc === 'boolean') ? orderDesc : true;

  	var ciMetricGr = new GlideRecord(this.TABLES.CI_METRIC);
  	ciMetricGr.addQuery('configuration_item', cmdbCiSysId);
  	ciMetricGr.addQuery('metric_definition', metricDefinition);

  	if (start || end) {
  		var startGdt = new GlideDateTime();
  		var endGdt = new GlideDateTime();

  		if (start) {
  			startGdt.setValue(start);
  			ciMetricGr.addQuery('timestamp', '>=', startGdt);
  		}

  		if (end) {
  			endGdt.setValue(end);
  			ciMetricGr.addQuery('timestamp', '<=', endGdt);
  		}

  		if (start && end && startGdt > endGdt) {
  			gs.error("The start date: " + start + "should not be greater than end date : " + end);
  			return res;
  		}
  	}

  	orderDesc ? ciMetricGr.orderByDesc('timestamp') : ciMetricGr.orderBy('timestamp');
  	ciMetricGr.query();

  	count = ciMetricGr.getRowCount();
  	ciMetricGr.chooseWindow(pageOffset, (metricLimit + pageOffset));
  	ciMetricGr.query();

  	while (ciMetricGr.next()) {
  		var payload = {};
  		try {
  			payload["payload"] = JSON.parse(ciMetricGr.getValue("payload"));
  			payload["timestamp"] = {
  				value: ciMetricGr.getValue("timestamp"),
  				displayValue: ciMetricGr.getDisplayValue("timestamp")
  			};
  			payload["sys_id"] = ciMetricGr.getUniqueValue();
  		} catch (e) {
  			gs.error("Metric payload is invalid " + e);
  			return res;
  		}

  		data.push(payload);
  	}

  	res.data = data;
  	res.count = count;

  	return res;
  },

  /**
   * returns metric data between provided dates
   * @param String cmdbCiSysId - configuration item sysId
   * @param String metricDefinitionSysId - metric Definition SysId
   * @param Integer pageOffset - optional, defaults to 0
   * @param Integer metricLimit - optional, defaults to 50
   * @param String start - optional
   * @param Integer end - optional
   * @param Boolean orderDesc - optional, defaults to true
   * @return list metricData
   */

  getMetricHistory: function(cmdbCiSysId, metricDefinitionSysId, pageOffset, metricLimit, start, end, orderDesc) {
  	return this._getMetricData(cmdbCiSysId, metricDefinitionSysId, pageOffset, metricLimit, start, end, orderDesc);
  },
  
  /**
   * returns metric data nearest to the given timestamp in the provided time range
   * @param String cmdbCiSysId - configuration item sysId
   * @param String metricDefinitionSysId - metric Definition SysId
   * @param String start
   * @param String end
   * @param String timestamp
   * @return JSON singleMetricData
   */
  getNearestMetric: function(cmdbCiSysId, metricDefinitionSysId, start, end, timestamp) {
  	var res = null;

  	if (!cmdbCiSysId || !metricDefinitionSysId) {
  		gs.error("The value provided for configurationItem or metricDefinition is invalid");
  		return res;
  	}

  	if (!start || !end || !timestamp) {
  		return;
  	}

  	var ciMetricGr = new GlideRecordSecure(this.TABLES.CI_METRIC);
  	ciMetricGr.addQuery('configuration_item', cmdbCiSysId);
  	ciMetricGr.addQuery('metric_definition', metricDefinitionSysId);

  	var startGdt = new GlideDateTime();
  	startGdt.setValue(start);
  	ciMetricGr.addQuery('timestamp', '>=', startGdt);

  	var endGdt = new GlideDateTime();
  	endGdt.setValue(end);
  	ciMetricGr.addQuery('timestamp', '<=', endGdt);

  	if (startGdt > endGdt) {
  		gs.error("The start date: " + start + "should not be greater than end date : " + end);
  		return;
  	}

  	ciMetricGr.orderByDesc('timestamp');
  	ciMetricGr.query();

  	var minDuration = Number.MAX_VALUE;
  	var prevDuration = null;

  	var timestampGdt = new GlideDateTime();
  	timestampGdt.setValue(timestamp);

  	while (ciMetricGr.next()) {

  		var ciMetricGrGdt = GlideDateTime();
  		ciMetricGrGdt.setValue(ciMetricGr.getValue("timestamp"));
  		var duration = Math.abs(timestampGdt.getNumericValue() - ciMetricGrGdt.getNumericValue());
  		if (prevDuration && prevDuration < duration && res) {
  			break;
  		}
  		prevDuration = duration;
  		if (minDuration < duration) {
  			continue;
  		}

  		var payload = {};
  		try {
  			payload["payload"] = JSON.parse(ciMetricGr.getValue("payload"));
  			payload["timestamp"] = {
  				value: ciMetricGr.getValue("timestamp"),
  				displayValue: ciMetricGr.getDisplayValue("timestamp")
  			};
  			payload["sys_id"] = ciMetricGr.getUniqueValue();
  		} catch (e) {
  			gs.error("Metric payload is invalid " + e);
  			continue;
  		}

  		minDuration = duration;
  		res = payload;
  	}

  	return res;
  },

  _getEdgeMetricData: function(cmdbCiSysId, metricDefinitionSysId, start, end, fetchLatest) {
  	var metricData = this._getMetricData(cmdbCiSysId, metricDefinitionSysId, 0, 1, start, end, fetchLatest);
  	if (metricData && metricData.data && metricData.data.length > 0)
  		return metricData.data[0];
  	return null;
  },

  /**
   * returns the latest metric data between the provided start and end dates
   * @param String cmdbCiSysId - configuration item sysId
   * @param String metricDefinitionSysId - metric Definition SysId
   * @param String start - optional
   * @param Integer end - optional
   * @return JSON singleMetricData
   */

  getFirstMetric: function(cmdbCiSysId, metricDefinitionSysId, start, end) {
  	return this._getEdgeMetricData(cmdbCiSysId, metricDefinitionSysId, start, end, true);
  },

  /**
   * returns the oldest metric data between the provided start and end dates
   * @param String cmdbCiSysId - configuration item sysId
   * @param String metricDefinitionSysId - metric Definition SysId
   * @param String start - optional
   * @param Integer end - optional
   * @return JSON singleMetricData
   */

  getLastMetric: function(cmdbCiSysId, metricDefinitionSysId, start, end) {
  	return this._getEdgeMetricData(cmdbCiSysId, metricDefinitionSysId, start, end, false);
  },

  /**
   * returns the batch id
   * @param Object ci - Configuration Item Sys ID or GlideRecord reference
   * @param Object metricDefinition - GlideRecord reference or Sys ID of metric definition record
   */
  requestMetric: function(ci, metricDefinition, skipPreRequestChecks) {
  	if (!ci) {
  		gs.error("[requestMetric]: provide either the GlideRecord reference or sys_id of the CI item");
  		return;
  	}

  	if (!metricDefinition) {
  		gs.error("[requestMetric]: provide either the GlideRecord reference  or sys_id of the Metric definition record");
  	}

  	if (typeof ci === 'string') {
  		var metricEngineUtils = new CIMetricEngineUtils();
  		ci = metricEngineUtils.getGR(this.TABLES.CMDB_CI, ci);
  	}

  	if (typeof metricDefinition === 'string')
  		metricDefinition = this._getGlideRecord(this.TABLES.METRIC_DEFINITION, metricDefinition);

  	if (!ci || !ci.isValidRecord()) {
  		gs.error("[requestMetric]: Provided CI is not a valid record");
  		return;
  	}

  	if (!metricDefinition.isValidRecord()) {
  		gs.error("[requestMetric]: Provided Metric definition is not a valid record");
  		return;
  	}
  	
  	//If there is already a similar metric request in queue just return its batch id
  	var batchId = new CIMetricStagingUtil().checkDuplicateRequestInProgress(ci.getUniqueValue(), metricDefinition.getUniqueValue());
  	if (batchId)
  		return batchId;

  	var adapter = this._getAdapter(metricDefinition, ci);
  	if (adapter.adapterConfigGr && adapter.adapterConfigGr.isValidRecord()) {
  		var metricAdapter = new CIMetricAdapter(adapter.adapterConfigGr, ci.getUniqueValue());
  		return metricAdapter.exec(skipPreRequestChecks);
  	}
  },

  /**
   * returns the Map of Metric definition corresponding to the batch ID
   * @param Object ci - Configuration Item Sys ID or GlideRecord reference
   * @param String metricDefinition - Comma separated Sys IDs of metric definition records
   */
  requestMetrics: function(ci, metricDefinitions) {
  	if (typeof metricDefinitions != 'string')
  		return;

  	var result = {};
  	var metricDefinitionArray = metricDefinitions.split(",");
  	var ctx = this;
  	metricDefinitionArray.forEach(function(metricDefinition) {
  		var batchId = ctx.requestMetric(ci, metricDefinition);
  		if (batchId)
  			result[metricDefinition + ""] = batchId;
  	});

  	return result;
  },

  _getGlideRecord: function(tableName, sysId) {
  	var gr = new GlideRecord(tableName);
  	if (gr.get(sysId))
  		return gr;
  },

  getAdapter: function(metricDefinition, cmdbCi) {

  	if(typeof cmdbCi === 'string'){
  		cmdbCi = new CIMetricEngineUtils().getGR(this.TABLES.CMDB_CI, cmdbCi);
  	}

  	if(typeof metricDefinition === 'string'){
  		metricDefinition = this._getGlideRecord(this.TABLES.METRIC_DEFINITION, metricDefinition);
  	}
  	
  	return this._getAdapter(metricDefinition, cmdbCi).adapterConfigGr;
  },

  _getAdapter: function(metricDefinitionGr, cmdbCiGr) {
  	var result = {
  		adapterConfigGr: null
  	};
  	// store each provider applicability to avoid the multiple checks on the same provider again
  	var providerApplicability = {};
  	var adapterConfigGr = new GlideRecord(this.TABLES.ADAPTER_CONFIG);
  	adapterConfigGr.addQuery(this.FIELDS.ADAPTER_CONFIG.metric_definition, metricDefinitionGr.getUniqueValue());
  	adapterConfigGr.orderBy(this.FIELDS.ADAPTER_CONFIG.order);
  	adapterConfigGr.query();

  	while (adapterConfigGr.next()) {
  		if (
  			(adapterConfigGr.query_action == this.QUERY_ACTION_TYPE.FLOW && global.JSUtil.notNil(adapterConfigGr.query_flow)) ||
  			(adapterConfigGr.query_action == this.QUERY_ACTION_TYPE.SCRIPT && global.JSUtil.notNil(adapterConfigGr.query_script)) ||
  			(global.JSUtil.notNil(adapterConfigGr.provider) && global.JSUtil.notNil(adapterConfigGr.provider.default_query_flow))
  		) {
  			var providerSysId = adapterConfigGr.getValue("provider");
  			// check provider applicability only if it is not already looked up
  			if (providerApplicability[providerSysId] === undefined) {
  				providerApplicability[providerSysId] = this._isProviderApplicable(providerSysId, cmdbCiGr);
  			}
  			if (providerApplicability[providerSysId] && this._isAdapterApplicable(adapterConfigGr, cmdbCiGr)) {
  				result.adapterConfigGr = adapterConfigGr;
  				return result;
  			}
  		}	
  	}

  	// check if atleaset one provider is available to set empty state code
  	var pExists = false;
  	for (var pSysId in providerApplicability) {
  		if (providerApplicability[pSysId]) {
  			pExists = true;
  			break;
  		}
  	}
  	// if provider exists, definitely no matching adapter config exists as we get to this line of execution
  	result.reason = pExists ? this.EMPTY_STATES.NO_ADAPTER_CONFIG : this.EMPTY_STATES.PROVIDER_UNAVAILABLE;

  	gs.info("[_getAdapter]: Did not find any matching Adapter config record or provider is unavailable for the CI item " + cmdbCiGr.getDisplayValue());
  	return result;
  },
  
  _isProviderApplicable: function(provider, cmdbCiGr) {
  	var extPoints = new GlideScriptedExtensionPoint().getExtensions(this.CI_AVAILABILITY_EXT_POINT);
  	if (!extPoints.length) {
  		gs.info("[_isProviderApplicable]: Did not find any extension point defined");
  		return false;
  	}

  	for (var i = 0; i < extPoints.length; i++) {
  		var extPointSI = extPoints[i];
  		if (typeof extPointSI.getProvider == "function" && extPointSI.getProvider() === provider && extPointSI.isProviderApplicable(cmdbCiGr)) {
  			return true;
  		}
  	}
  	return false;
  },

  _isAdapterApplicable: function(adapterConfigGr, cmdbCiGr) {
  	var adapterApplicabilityGr = new GlideRecord(this.TABLES.ADAPTER_APPLICABILITY_RULE);
  	adapterApplicabilityGr.addQuery(this.FIELDS.ADAPTER_APPLICABILITY_RULE.adapter_config, adapterConfigGr.getUniqueValue());
  	adapterApplicabilityGr.query();

  	while (adapterApplicabilityGr.next()) {
  		var isCiConditionMatching;

  		if (adapterApplicabilityGr.match_ci_extensions + "" === 'true') {
  			var tableExtension = new GlideTableHierarchy(adapterApplicabilityGr.ci_class + "").getTableExtensions();
  			tableExtension.push(adapterApplicabilityGr.ci_class + "");
  			isCiConditionMatching = tableExtension.indexOf(cmdbCiGr.sys_class_name + "") > -1;
  		} else
  			isCiConditionMatching = (adapterApplicabilityGr.ci_class + "" === cmdbCiGr.sys_class_name + "");

  		if (!isCiConditionMatching)
  			continue;

  		isCiConditionMatching = GlideFilter.checkRecord(cmdbCiGr, adapterApplicabilityGr.ci_conditions + "");
  		if (isCiConditionMatching)
  			return true;
  	}

  	return false;
  },

  /**
   * @param Object recordGr - GlideRecord reference to the the Source record
   * @param Object fields - populated field names on GlideRecord reference to Configuration items
   */
  evaluateCollectionRule: function(recordGr, fields) {
  	var collectionRules = this._getCollectionRules(recordGr.sys_class_name + "");
  	var isValidSourceRecord = recordGr.isValidRecord();
  	var arrayUtils = new global.ArrayUtil();
  	
  	while (collectionRules.next()) {
  		var isTableConditionMatching = true;
  		if (isValidSourceRecord) {
  			isTableConditionMatching = GlideFilter.checkRecord(recordGr, collectionRules.table_conditions + "");
  			if (!isTableConditionMatching)
  				continue;
  		}

  		var isCiConditionMatching = true;
  		var ciGr = {};
  		if (collectionRules.ci_field && recordGr.isValidField(collectionRules.ci_field + "")) {
  			var fieldName = collectionRules.ci_field + "";
  			if (!arrayUtils.contains(fields,fieldName)) {
  				continue;
  			}
  			if (!ciGr[fieldName]) {
  				ciGr[fieldName] = new sn_cimaf.CIMetricEngineUtils().getGR('cmdb_ci', recordGr.getValue(fieldName));
  				if (!ciGr[fieldName] || !ciGr[fieldName].isValidRecord()) {
  					gs.error("[evaluateCollectionRule] Provided cmdb CI is not a valid record");
  					return;
  				}
  			}
  			var cmdbCiGr = ciGr[fieldName];
  			
  			if (collectionRules.match_ci_extensions + "" === 'true') {
  				// Match cmdbCiGr against CI Class
  				var tableExtension = new GlideTableHierarchy(collectionRules.ci_class + "").getTableExtensions();
  				tableExtension.push(collectionRules.ci_class + "");
  				isCiConditionMatching = tableExtension.indexOf(cmdbCiGr.sys_class_name + "") > -1;
  			} else
  				isCiConditionMatching = (collectionRules.ci_class + "" === cmdbCiGr.sys_class_name + "");

  			if (!isCiConditionMatching)
  				continue;

  			// Match cmdbCiGr against the CI Conditions
  			isCiConditionMatching = GlideFilter.checkRecord(cmdbCiGr, collectionRules.ci_conditions + "");
  			if (!isCiConditionMatching)
  				continue;
  		}

  		var metricCollectionMaps = this._getMetricDefFromCollectionAsscn(collectionRules);
  		while (metricCollectionMaps.next()) {
  			this.requestMetric(cmdbCiGr, metricCollectionMaps.metric_definition.getRefRecord());
  		}
  	}
  },

  _getCollectionRules: function(tableName) {
  	var collectionRuleGr = new GlideRecord(this.TABLES.COLLECTION_RULE);
  	collectionRuleGr.addActiveQuery();
  	if (tableName)
  		collectionRuleGr.addQuery(this.FIELDS.COLLECTION_RULE.source_table, tableName);

  	collectionRuleGr.query();
  	return collectionRuleGr;
  },

  _getMetricDefFromCollectionAsscn: function(collectionRule) {
  	var metricCollectionMaps = new GlideRecord(this.TABLES.COLLECTION_RULE_METRICS_ASSOCIATION);
  	metricCollectionMaps.addQuery(this.FIELDS.COLLECTION_RULE_METRICS_ASSOCIATION.collection_rule, collectionRule.sys_id + "");
  	metricCollectionMaps.query();
  	return metricCollectionMaps;
  },
  /**
   * @param cmdbCISysId - Configuration Item Sys ID
   * @param Array<String> metricDefinitionSysIds - Array of metric definition record sys ids.
   * @return JSON map results per metric definition
   * {
   *  "metricDef_sys_id_1": true,
   *  "metricDef_sys_id_2": false,
   *  "metricDef_sys_id_3": true
   * }
   */
  canFetchMetrics: function(cmdbCISysIds, metricDefinitionSysIds /* Array of sys ids */ ) {
  	var that = this;
  	this.metricDefinitionCache = {}; // clear cache;
  	var result = {};
  	if (!Array.isArray(cmdbCISysIds)) {
  		gs.error("[canFetchMetrics]: Provided cmdbCISysIds is not a valid array object");
  		return;
  	}

  	if (!Array.isArray(metricDefinitionSysIds)) {
  		gs.error("[canFetchMetrics]: Provided metricDefinitionSysIds is not a valid array object");
  		return;
  	}

  	cmdbCISysIds.forEach(function(cmdbCISysId) {
  		result[cmdbCISysId + ''] = that.canFetchMetricsByCI(cmdbCISysId, metricDefinitionSysIds);
  	});

  	return result;
  },

  canFetchMetricsByCI: function(cmdbCISysId, metricDefinitionSysIds) {
  	var that = this;
  	var result = {};
  	if (!cmdbCISysId) {
  		gs.error("[canFetchMetricsByCI]: Provided cmdbCISysId is not a sys id");
  		return;
  	}

  	var metricEngineUtils = new CIMetricEngineUtils();
  	var cmdbCiGr = metricEngineUtils.getGR(this.TABLES.CMDB_CI, cmdbCISysId);

  	result = this.hasMetricsByCI(cmdbCISysId, metricDefinitionSysIds);

  	metricDefinitionSysIds.forEach(function(metricDefinitionSysId) {
  		if (!result[metricDefinitionSysId]) { // if metrics is not already fetched for ci, check for adaptor definition and ci availibities 
  			if (!that.metricDefinitionCache) {
  				that.metricDefinitionCache = {};
  			}
  			if (!that.metricDefinitionCache[metricDefinitionSysId]) {
  				that.metricDefinitionCache[metricDefinitionSysId] = that._getGlideRecord(that.TABLES.METRIC_DEFINITION, metricDefinitionSysId);
  			}
  			var metricDefinitionGr = that.metricDefinitionCache[metricDefinitionSysId] = that._getGlideRecord(that.TABLES.METRIC_DEFINITION, metricDefinitionSysId);
  			if (that._getAdapter(metricDefinitionGr, cmdbCiGr).adapterConfigGr)
  				result[metricDefinitionSysId] = true;
  		}
  	});


  	return result;

  },

  /*
   * Calls adaptor api to check if ci is available or not
   * @returns JSON with status and errors
   * 
   *  {
   *  	status: false,
   *  	message: ""
   *  }
   * 
   */
  getCIStatus: function(ci, providerSysId /* optional */ ) {
  	if (!ci) {
  		gs.error("[isCIAvailable]: provide either the GlideRecord reference or sys_id of the CI item");
  		return;
  	}

  	if (typeof ci === 'string') {
  		var metricEngineUtils = new CIMetricEngineUtils();
  		ci = metricEngineUtils.getGR(this.TABLES.CMDB_CI, ci);
  	}

  	var extPoints = new GlideScriptedExtensionPoint().getExtensions(this.CI_AVAILABILITY_EXT_POINT);
  	if (!extPoints.length) {
  		gs.info("[getCIStatus]: Did not find any extension point defined");
  		return {
  			status: true
  		};
  	}

  	for (var i = 0; i < extPoints.length; i++) {
  		var extPointSI = extPoints[i];
  		if ((providerSysId && extPointSI.getProvider() === providerSysId) || (extPointSI.isProviderInstalled(ci)))
  			return extPointSI.getCIStatus(ci);
  	}

  	return {
  		status: false,
  		message: gs.getMessage("Error fetching metrics. Try again or contact your admin")
  	};
  },

  /**
   * @param cmdbCISysIds - Configuration Item Sys IDs
   * @param Array<String> metricDefinitionSysIds - Array of metric definition record sys ids.
   * @return JSON map results per metric definition
   * {
  	 "cmdb_ci_sys_id_1": {
   *     "metricDef_sys_id_1": true,
   *     "metricDef_sys_id_2": false,
   *     "metricDef_sys_id_3": true
   *   }
   * }
   */
  hasMetrics: function(cmdbCISysIds /* Array of sys ids */ , metricDefinitionSysIds /* Array of sys ids */ ) {
  	var that = this;
  	var result = {};
  	if (!Array.isArray(cmdbCISysIds)) {
  		gs.error("[hasMetrics]: Provided cmdbCISysIds is not a valid array object");
  		return;
  	}

  	if (!Array.isArray(metricDefinitionSysIds)) {
  		gs.error("[hasMetrics]: Provided metricDefinitionSysIds is not a valid array object");
  		return;
  	}

  	cmdbCISysIds.forEach(function(cmdbCISysId) {
  		result[cmdbCISysId + ''] = that.hasMetricsByCI(cmdbCISysId, metricDefinitionSysIds);
  	});

  	return result;
  },

  hasMetricsByCI: function(cmdbCISysId, metricDefinitionSysIds) {
  	var result = {};
  	if (!cmdbCISysId) {
  		gs.error("[hasMetricsByCI]: Provided cmdbCISysId is not a sys id");
  		return;
  	}

  	// Initialize result map, so output will always contain all metric definition keys, even in false case.
  	metricDefinitionSysIds.forEach(function(metricDefinitionSysId) {
  		result[metricDefinitionSysId + ''] = false;
  	});

  	var ciMetricGr = new GlideAggregate(this.TABLES.CI_METRIC);
  	ciMetricGr.addQuery('configuration_item', cmdbCISysId);
  	ciMetricGr.addQuery('metric_definition', 'IN', metricDefinitionSysIds);
  	ciMetricGr.groupBy("metric_definition");
  	ciMetricGr.query();
  	while (ciMetricGr.next()) {
  		result[ciMetricGr.metric_definition + ''] = true;
  	}
  	return result;
  },
  
  /**
   * @param cmdbCISysId - Configuration Item Sys ID
   * @param Array<String> metricDefinitionSysIds - Array of metric definition record sys ids.
   * @return JSON map results per metric definition
   * {
   *     "metricDef_sys_id_1": { adapterConfigGr: <null|GlideRecord>, reason: <EMPTY_STATE>},
   *     "metricDef_sys_id_2": { adapterConfigGr: null, reason: NO_ADAPTER_CONFIG },
   *     "metricDef_sys_id_3": { adapterConfigGr: GlideRecord }
   * }
   */
  hasApplicableAdapter: function(cmdbCISysId, metricDefinitionSysIds) {
  	var result = {};
  	if (!cmdbCISysId) {
  		gs.error("[hasAdapterApplicable]: Provided cmdbCISysId is not a sys id");
  		return;
  	}
  	if (!Array.isArray(metricDefinitionSysIds)) {
  		gs.error("[hasAdapter]: Provided metricDefinitionSysIds is not a valid array object");
  		return;
  	}
  	
  	var metricEngineUtils = new CIMetricEngineUtils();
  	var cmdbCiGr = metricEngineUtils.getGR(this.TABLES.CMDB_CI, cmdbCISysId);
  	if (!cmdbCiGr){
  		gs.error("[hasAdapterApplicable]: Provided cmdbCISysId is not valid");
  		return;
  	}
  	

  	// Initialize result map, so output will always contain all metric definition keys, even in false case.
  	metricDefinitionSysIds.forEach(function(metricDefinitionSysId) {
  		result[metricDefinitionSysId + ''] = false;
  	});
  	
  	
  	var metricDefinitionGr = new GlideRecord(this.TABLES.METRIC_DEFINITION);
  	metricDefinitionGr.addQuery('sys_id', 'IN', metricDefinitionSysIds);
  	metricDefinitionGr.query();
  	while(metricDefinitionGr.next()) {
  		var adapter = this._getAdapter(metricDefinitionGr, cmdbCiGr);
  		result[metricDefinitionGr.getUniqueValue()] = adapter;
  		if (adapter.adapterConfigGr) {
  			// if at least one metric def has adapter config, no need to check for other metric defs
  			break;
  		}
  	}

  	return result;
  },

  type: 'CIMetricEngineSNC'
};

Sys ID

9e00cd0f53870110a487ddeeff7b127f

Offical Documentation

Official Docs: