Name

global.EmAiInsight

Description

No description available

Script

var EmAiInsight = Class.create();
var emAiInsightCommon = new EmAiInsightCommon();
EmAiInsight.prototype = {
  
  initialize: function() {
  	this.slowStepsManager = new SlowStepJSManager();
  	this.evtMgmtCommons = new EvtMgmtCommons();
  },
  
getSimilarAlertQuery: function(alertGr, currentAlertGr) {
  
  	this.slowStepsManager.setTopic("ML:Get Similarity Alert Query");
  	this.slowStepsManager.startStep("EmAiInsight: getSimilarAlertQuery");
  	
  	var soultionTitle = gs.getProperty("evt_mgmt_similarity_solution_title","ml_x_global_alert_similarity");
  	var use_threshold = gs.getProperty("evt_mgmt.similarity_use_threshold",true);
  	var similarAlertMaxCount =  gs.getProperty("evt_mgmt.similarity_max_similar_alerts_shown",10);
  	
  	var options = {"top_n": similarAlertMaxCount, "apply_threshold": use_threshold};

  	var solutions = [];
  	solutions[0] = soultionTitle;
      var predictor = new MLPredictor();
      var info = "";
  	var isPredictedSuccessful = false;
      var sysids = "";
      var returnArray = [];
  
  	try {
  		var solutionName =  solutions[0]; 
          var solution = predictor.findActiveSolution(solutionName);
  		if (!solution) 
  			return returnArray;
  		
  		var outcome_array = predictor.getPredictions (currentAlertGr,solution,options);
  		
  		if (outcome_array == null) {
  			return returnArray;
  		}
  	  
  		if (outcome_array.length == 0) {
  			return returnArray;
  		}
  		
  		isPredictedSuccessful = true;
  		
  		for (var i = 0; i < outcome_array.length; i++) {
  			var outcomeInstance = outcome_array[i]; 
  			if (outcomeInstance.hasPrediction()) {
  				var alertNumber = outcomeInstance.predictedValue(); //String //Alert number (do to a bug, this currently return the sys_id)
  				var sysId = outcomeInstance.predictedValueSysId(); //sys_id for similarity
  				if (currentAlertGr.sys_id == alertNumber) {
  					continue;
  				}
                 	var confidence = outcome_array[i].confidence(); //: double //similarity score
  				sysids = sysids + "," + alertNumber;
  				var retJson = {"number": alertNumber, "sys_id": sysId,"confidence":  confidence};
  				returnArray.push(retJson);
  			} 
  		}
  		alertGr.addQuery("sys_id","IN",sysids);
  		
  	}	catch(exception) {
  		var err = "Alerts Similarities\n Alert similarities model fail to locat similarities, possible some input fields are empty /n" + exception;
  		gs.error(err);
  		
  	} finally {
  		this.slowStepsManager.report();
  		if (!isPredictedSuccessful) {
  			return returnArray;
  		}
  		if (this.isDebugEnabled()) 
  			gs.error("Alerts Similarities\n" +  this.printReturnedArray(returnArray));
  		
  		return returnArray;
  	}
  
  },
  
  isDebugEnabled: function() {
  	return (gs.getProperty('evt_mgmt.log_debug', 'false') == 'true');
  },
  
  printReturnedArray: function(returnArray) {
  	var infoString = "";
  	for (var i = 0; i < returnArray.length; i++) {
  		var arr = returnArray[i];
  		infoString = infoString + "   Number     "     + arr.number + 
  			                      "   Sys ID     "     + arr.number + 
  			                      "   Confidence "     + arr.confidence +"\n";
  	}
  	return infoString;
  },
  
  // is the domain separation feature active
  isDomainSepActive:function (){
  	var domainSeparationActive = 
  		GlideProperties.get("glide.sys.domain.partitioning", false); 
  	return domainSeparationActive == "true";
  },
  
  // Related Alert tab
  getRelatedAlertQuery: function (alertGr, currentAlertGr) {
      var useMl = String(gs.getProperty("evt_mgmt.similarity_use_ml", true));
      var isDomain = String(this.isDomainSepActive());
      var isMlPluginActive = String(GlidePluginManager.isActive('com.glide.platform_ml'));
      var isEntitledToML = this.checkMLSimilarityEntitlement();
      if (useMl === "true") {
          if (isMlPluginActive === "true") {
              if (isEntitledToML === "true") {
                  if (isDomain === "false") {
                      try {
                          var res = this.getSimilarAlertQuery(alertGr, currentAlertGr);
                          if (res.length > 0) {
                              gs.warn(" Alerts Similarities: Alerts Similarities were calculate by ML alogritm ");
                              return true;
                          }
                      } catch (exception) {
                          gs.error(" Alerts Similarities: Similarities calculations using ML failed, possibly do to empty input fields  " + exception);
                      }
                  }
              }  else {
  				this.evtMgmtCommons.addDebugLogNoPrefix("Alerts Similarities: Similarities calculations using ML failed, no ML entitelment ");
  			}
          }
      }
  	
  	gs.warn("Alerts Similarities:  Alerts Similarities were calculated by field comparison "); 
  	var cmdbCiClass = currentAlertGr.cmdb_ci.sys_class_name;
  	if(GlideStringUtil.nil(cmdbCiClass)) {
  		alertGr.addQuery("sys_id", "=", "");
  		return false;
  	}
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: calculate Similar Alerts");
  	alertGr.addQuery("cmdb_ci.sys_class_name", "=", cmdbCiClass);
  	if(GlideStringUtil.notNil(currentAlertGr.message_key)) {
  		alertGr.addQuery("message_key", "!=", currentAlertGr.message_key); // Dont show repeated alerts.
  	}
  	emAiInsightCommon.addNotTheSameSysIdQuery(alertGr, currentAlertGr);
  	emAiInsightCommon.addTimeBeforeQuery(alertGr, "evt_mgmt.alert_insight_alert_history_min", 43200 /* 30 days */);
  	this.setSameAsFilter(alertGr, currentAlertGr, "evt_mgmt.alert_insight_alert_same_as_filter", "source,type,resource,metric_name");
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: calculate Similar Alerts. Query string: " + alertGr.getEncodedQuery() );
  	return false;
  },
  
  checkMLSimilarityEntitlement: function() {
      var entitlementProperty = gs.getProperty('evt_mgmt.ml_solutions.overwrite_entitlement', 'disable');
      if (! entitlementProperty === 'disable') {
          this.evtMgmtCommons.addDebugLogNoPrefix("Alerts Similarities: ML entitlement check is overwritten with the value of " + entitlementProperty);
          return entitlementProperty;
      }
      var result = 'false';
      try {
          result = String(new MlValidationHelper().checkEntitlements('similarity_trainer').validation);
      } catch (exception) {
          gs.error("Alerts Similarities: MLEntitlementUtil.checkEntitlements raised exception with the message: " + exception);
      }
      return result;
  },
  
  // Same Alert tab
  getSameAlertQuery: function (alertGr, currentAlertGr) {
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: calculate Repeated Alerts");
  	var message_key = "";
  	if(currentAlertGr.is_group_alert != null && currentAlertGr.is_group_alert) {
  		// For virtual alert we should
  		// 1. Find the message key of the secondary alert that create the virtual alert
  		// 2. Dont show the secondary alert that create the virtual alert
  		this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: calculate Repeated Alerts for virtual group");
  		message_key = emAiInsightCommon.getMessageKeyForVirtualAlertQuery(currentAlertGr);
  		if(GlideStringUtil.notNil(message_key)) {
  			alertGr.addQuery("message_key", "=", message_key);
  		}
  		alertGr.addQuery("sys_id", "!=", currentAlertGr.message_key);
  	}
  	if(GlideStringUtil.nil(message_key)) { // this means it is not a virtual alert
  		alertGr.addQuery("message_key", "=", currentAlertGr.message_key);
  	}
  	emAiInsightCommon.addNotTheSameSysIdQuery(alertGr, currentAlertGr);
  	emAiInsightCommon.addTimeBeforeQuery(alertGr, "evt_mgmt.alert_insight_alert_history_min", 43200 /* 30 days */);
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: calculate Repeated Alerts. Query string: " + alertGr.getEncodedQuery() );
  },
  
  // Same CI task query 
  getSameCiTaskQuery: function (taskGr, currentAlertGr) {
  	var cmdbCiSysId = currentAlertGr.cmdb_ci;
  	if(GlideStringUtil.nil(cmdbCiSysId)) {
  		taskGr.addQuery("sys_id", "=", "");
  		return;
  	}
  	var task = currentAlertGr.incident;
  	if(GlideStringUtil.notNil(task)) {
  		taskGr.addQuery("sys_id", "!=", task); // Ignore the alert task if exists
  	}
  	var taskType = taskGr.getTableName();
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: calculate CI " + taskType);
  	var changeReqResult = this.addSameTaskCondition(taskGr, taskType, cmdbCiSysId);
  	var qc = taskGr.addQuery("cmdb_ci", "=", cmdbCiSysId);
  	if(changeReqResult.length > 0) 
  		qc.addOrCondition('sys_id', "=", changeReqResult);
  	emAiInsightCommon.addTimeBeforeQuery(taskGr, "evt_mgmt.alert_insight_task_history_min", 10080 /* 7 days */);
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: calculate CI " + taskType + " Query string: " + taskGr.getEncodedQuery() );
  },
  
  addSameTaskCondition: function (taskGr, taskType, cmdbCiSysId) {
  	var result = [];
  	if(taskType == "change_request" ) {
  		// For change request we need to look for the following states Implement:-1, review:0 and closed:3
  		taskGr.addQuery("state", "IN", "-1,0,3");
  	
  		//Get array of CHR of CI affected
  		var resultCIAffected = this.getChangeRequestByCI(cmdbCiSysId, "task_ci");
  		//Get array of CHR of services impacted
  		var resultServicesImpacted = this.getChangeRequestByCI(cmdbCiSysId, "task_cmdb_ci_service");
  		result = resultCIAffected.concat(resultServicesImpacted);
  	}
  	return result;
  },
  getChangeRequestByCI: function (cmdbCiSysId, tableName) {
  	
  	var gr = new GlideRecord(tableName);
  	if (tableName == "task_ci")		//Name of the CI column are different in those tables
  		gr.addQuery("ci_item", "=", cmdbCiSysId);
  	else if (tableName == "task_cmdb_ci_service")
  		gr.addQuery("cmdb_ci_service", "=", cmdbCiSysId);
  	var maxTasks = GlideProperties.get("evt_mgmt.alert_insight_max_affected_ci_change_requests", 20);
  	gr.setLimit(maxTasks);
  	gr.orderByDesc("sys_updated_on");
  	gr.query();
  	//Check that only tasks that are CHR will return.
  	var taskResult =[];
  	while (gr.next()) {		
  		var taskSysID = gr.getValue("task");
  		taskResult.push(taskSysID);
  		this.evtMgmtCommons.addDebugLogNoPrefix("taskSysID: " + taskSysID + '\n');
  	}
  	
  	var grCHG = new GlideRecord("change_request");
  	grCHG.addQuery('sys_id', 'IN', taskResult);
  	grCHG.query();
  	var changeReqResult =[];
  	while (grCHG.next()) {
  		var chrSysID = grCHG.getValue("sys_id");
  		changeReqResult.push(chrSysID);
  		this.evtMgmtCommons.addDebugLogNoPrefix("chrSysID: " + chrSysID + '\n');
  	}
  	
  	return changeReqResult;
  },
  
  
  getSameCiTaskJson: function (tableName, alertSysId, type) {
  	var jsonToReturn = {};
  	var currentAlertGr = new GlideRecord("em_alert");
  	if(currentAlertGr.get(alertSysId)) {
  		var taskGr = new GlideRecord(tableName);
  		this.getSameCiTaskQuery(taskGr, currentAlertGr);
  		var count = emAiInsightCommon.getCount(tableName, taskGr);
  		jsonToReturn = emAiInsightCommon.getResultJson(count, tableName, type, taskGr.getEncodedQuery());
  	} else {
  		jsonToReturn = emAiInsightCommon.getEmptyJson(tableName, type);
  	}
  	
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: getSameCiTaskJson JSON: " + JSON.stringify(jsonToReturn));
  	return jsonToReturn;
  },
  
  getSameAlertsJson: function (tableName, alertSysId, type) {
  	var jsonToReturn = {};
  	var currentAlertGr = new GlideRecord("em_alert");
  	if(currentAlertGr.get(alertSysId)) {
  		var alertGr = new GlideRecord(tableName);
  		this.getSameAlertQuery(alertGr, currentAlertGr);
  		var count = emAiInsightCommon.getCount(tableName, alertGr);
  		jsonToReturn = emAiInsightCommon.getResultJson(count, tableName, type, alertGr.getEncodedQuery());
  	} else {
  		jsonToReturn = emAiInsightCommon.getEmptyJson(tableName, type);
  	}
  	
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: getSameAlertsJson JSON: " + JSON.stringify(jsonToReturn));
  	return jsonToReturn;
  },
  
  getRelatedAlertsJson: function (tableName, alertSysId, type) {
  	var jsonToReturn = {};
  	var currentAlertGr = new GlideRecord("em_alert");
  	var isUsingML = false;
  	if(currentAlertGr.get(alertSysId)) {
  		var alertGr = new GlideRecord(tableName);
  		isUsingML = this.getRelatedAlertQuery(alertGr, currentAlertGr);
  		var count = emAiInsightCommon.getCount(tableName, alertGr);
  		jsonToReturn = emAiInsightCommon.getResultJson(count, tableName, type, alertGr.getEncodedQuery());
  	} else {
  		jsonToReturn = emAiInsightCommon.getEmptyJson(tableName, type);
  	}
  	jsonToReturn["isUsingML"] = isUsingML;
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: getRelatedAlertsJson JSON: " + JSON.stringify(jsonToReturn));
  	return jsonToReturn;
  },
  
  getRelatedTaskResults: function(alertId, dataArr) {
  	var alertSysId = emAiInsightCommon.getAlertId(alertId);
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: getRelatedTaskResults for alert: " + alertSysId);
  	var stateJson = emAiInsightCommon.isDoneCalculating(alertSysId);
  	if (stateJson.done) {
  		this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: getRelatedTaskResults - done calculating results for alert: " + alertSysId + "; insightStateId: " + stateJson.sysId);
  		return emAiInsightCommon.getRelatedTaskQuery(stateJson.sysId, dataArr, stateJson.timestamp);
  	} else {
  		return emAiInsightCommon.getEmptyTaskQuery(dataArr);
  	}
  },
  
  calculateRelatedTaskResults: function(alertId, tasks) {
  	var alertSysId = emAiInsightCommon.getAlertId(alertId);
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: calculateRelatedTaskResults for alert: " + alertSysId);
  	if (emAiInsightCommon.toCalculate(alertSysId)) {
  		this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight:  starting to toCalculate insight data for alert: " + alertSysId);
  		emAiInsightCommon.calculate(alertSysId, tasks); //run calcultion async
  		return true;
  	} else {
  		//no need to calculate - already in calculation
  		return false;
  	}
  },
  
// Get a filter from a property and use its fields for same as queries
setSameAsFilter: function(gr, currentAlertGr, sameAsFilterPropertyName, defaultValue) {
  var sameAsFilter = GlideProperties.get(sameAsFilterPropertyName, defaultValue);
  if(GlideStringUtil.nil(sameAsFilter))
    return;
  this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: sameAsFilter: " + sameAsFilter);
  var array = sameAsFilter.split(',');
  if(currentAlertGr.is_group_alert != null && currentAlertGr.is_group_alert) {
    // For virtual alert we should
    // 1. Find the sys id of the secondary alert that create the virtual alert
    // 2. query the secondary alert instead of the virtual alert
    this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: calculate same filter for virtual group");
    var secGr = emAiInsightCommon.getGlideRecordForVirtualAlertQuery(currentAlertGr); //find the secondary alert of the primary message key
    if(secGr != null) {
      currentAlertGr = secGr;
  	gr.addQuery("message_key", "!=", currentAlertGr.message_key); //filter out alerts with the same message key of the secondary
    }
  }
  for(var i=0; i<array.length; i++ ) {
    var key = array[i];
    if(GlideStringUtil.nil(key))
      continue;
    
    var value = currentAlertGr.getValue(key);
    if(GlideStringUtil.nil(value) || value === "NaN") {
      gr.addNullQuery(key);
      continue;
    }
    
    gr.addQuery(key, "=", value);
  }
},
  
  getRelatedTaskResultsByType: function(taskGr, currentAlertGr, taskType) {
  	var alertSysId = currentAlertGr.getUniqueValue();
  	if(currentAlertGr.is_group_alert != null && currentAlertGr.is_group_alert) {
  		this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: getRelatedTaskResultsByType for virtal primary alert: " + alertSysId);
  		alertSysId = currentAlertGr.getValue("message_key");
  	}
  	
  	this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: getRelatedTaskResultsByType for alert: " + alertSysId);
  	var stateJson = emAiInsightCommon.isDoneCalculating(alertSysId);
  	if (stateJson.done) {
  		var insightStateId = stateJson.sysId;
  		this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: getRelatedTaskResultsByType - done calculating results for alert: " + alertSysId + "; insightStateId: " + insightStateId);
  		var grQueryTask = emAiInsightCommon.getGrQueryByTaskType(insightStateId, taskType);
  		taskGr.addEncodedQuery(grQueryTask.getEncodedQuery());
  	} else {
  		this.evtMgmtCommons.addDebugLogNoPrefix("Alert Insight: getRelatedTaskResultsByType - no results for alert: " + alertSysId);
  		taskGr.addQuery("sys_id", "=", "");
  	}
  },

  type: 'EmAiInsight'
};

Sys ID

4d45bdae93e2030054fc31f6357ffb98

Offical Documentation

Official Docs: