Name
sn_em_ai.EvtMgmtAlertCrawlerUtils
Description
No description available
Script
var EvtMgmtAlertCrawlerUtils = Class.create();
EvtMgmtAlertCrawlerUtils.prototype = {
initialize: function() {
this.evtMgmtCommons = new global.EvtMgmtCommons();
// we want to exclude secodaries when iterating over em_alert - secondaries will be dealt with on using the sn_em_ai_alert_queue table.
this.EXCLUDE_SECONDARIES_QUERY = gs.getProperty("sn_em_ai.exclude_secodaried_query",
"^correlation_groupNOT IN2,3^sn_extra_data.category=null^ORsn_extra_data.category!=3");
this.ALERT_CRAWLER_TRIGGER = "alert_crawler_trigger";
this.ALERT_PROCESSING_LIMIT_PROPERTY = 'sn_em_ai.alert_processing_query_limit';
this.alertProcessingQueryLimit = parseInt(gs.getProperty(this.ALERT_PROCESSING_LIMIT_PROPERTY, 1000), 10) || 1000;
this.changedAlertProcessingLimit = parseInt(gs.getProperty('sn_em_ai.changed_alerts_processing_limit', 1000), 10) || 1000;
this.POPULATE_ALERT_CIS_PROPERTY = "sn_em_ai.populate_alert_cis_table_enabled";
this.POPULATE_ALERT_SERVICES_PROPERTY = "sn_em_ai.populate_alert_services_table_enabled";
this.POPULATE_ALERT_TAGS_PROPERTY = "sn_em_ai.populate_alert_tags_table_enabled";
this.bulkLimit = parseInt(gs.getProperty("evt_mgmt.batchInsertSingleField.bulk_size", 500), 10) || 500;
//Constants
this.SYS_CREATED_ON = "sys_created_on";
this.CMDB_CI = 'cmdb_ci';
this.DOMAIN = 'sys_domain';
this.ALERT = 'alert';
this.BUSINESS_SERVICE = 'business_service';
this.NAME = "name";
this.CLASS = "class";
this.SYS_ID = "sys_id";
this.EM_ALERT_TABLE = "em_alert";
this.ALERT_TAGS = "sn_alert_tags";
this.NUMBER = "number";
this.IS_LA_ALERT = "is_la_alert";
//sn_em_ai_alert_cis
this.ALERT_CIS_TABLE = 'sn_em_ai_alert_cis';
this.CI_NAME = 'cmdb_ci_name';
this.CI_CLASS = 'cmdb_ci_sys_class_name';
//sn_em_ai_alert_services
this.ALERT_SERVICES_TABLE = 'sn_em_ai_alert_services';
this.BS_NAME = 'business_service_name';
this.BS_CLASS = 'business_service_sys_class_name';
this.REFERENCE_CIS = 'reference_cmdb_cis';
//sn_em_ai_agg_alert_queue
this.ALERT_QUEUE_TABLE = 'sn_em_ai_agg_alert_queue';
this.PARENT = 'parent';
this.ADDITIONAL_INFO = 'additional_info';
this.STATES = {
PENDING: 'pending',
PROCESSING: 'processing',
COMPLETE: 'complete',
FAILED: 'failed'
};
this.STATE = 'state';
this.ACTIONS = {
ALERT_ADDED_TO_GROUP: '1',
ALERT_REMOVED_FROM_GROUP: '2',
ALERT_TAGS_CHANGED: '3',
};
this.ACTION = "action";
//em_impact_graph
this.EM_IMPACT_GRAPH = "em_impact_graph";
this.CHILD_ID = "child_id";
this.PARENT_ID = "parent_id";
this.STATUS = "status";
//sn_em_ai_alert_tags
this.ALERT_TAGS_TABLE = "sn_em_ai_alert_tags";
this.TAG_NAME = "tag_name";
this.TAG_VALUE = "tag_value";
this.POPULATE_ALERT_TAGS = this.shouldPopulateAlertTags();
this.POPULATE_ALERT_CIS = this.shouldPopulateTable(this.POPULATE_ALERT_CIS_PROPERTY, true, this.ALERT_CIS_TABLE);
this.POPULATE_ALERT_SERVICES = this.shouldPopulateTable(this.POPULATE_ALERT_SERVICES_PROPERTY, true, this.ALERT_SERVICES_TABLE);
// In memory objects saving the data that will be inserted to the utility tables in bulks, at the end of the job run.
this.alertCisMap = {}; // Map of alerts with their configuration items
this.cisExtraData = {}; // save the name and sys_class_name of each CI
this.alertServicesMap = {}; // Map of alerts with their impacted services, and the refrence CI of each service.
this.servicesExtraData = {}; // save the name and sys_class_name of each impacted service
this.alertDomains = {}; // Map of alert and sys_domain
this.alertTagsMap = {}; //Map of alerts and the key-value pair of the alert tags.
},
getHashDefaultEmpty: function(hashName) {
var hashGr = this.evtMgmtCommons.getHashGr(hashName);
if (!hashGr.next()) {
// create on demand, with empty hash value
hashGr = new GlideRecord('sa_hash');
hashGr.name = hashName;
hashGr.insert();
return "";
} else {
return hashGr.getValue("hash");
}
},
getAlertsBetweenTimes: function(alertProcessTimeForAlerts, lastJobRunTime) {
var gr = new GlideRecord(this.EM_ALERT_TABLE);
if (lastJobRunTime) {
gr.addQuery(this.SYS_CREATED_ON, ">=", lastJobRunTime);
}
if (this.EXCLUDE_SECONDARIES_QUERY) {
gr.addEncodedQuery(this.EXCLUDE_SECONDARIES_QUERY);
}
gr.addQuery(this.SYS_CREATED_ON, "<", alertProcessTimeForAlerts);
if (this.alertProcessingQueryLimit > 0) { // unlimit the number of records by setting this property to 0 or less
gr.setLimit(this.alertProcessingQueryLimit);
}
// here we are sorting by Created_On since the alerts should to process record in order
gr.orderBy(this.SYS_CREATED_ON);
gr.query();
return gr;
},
getChangedAlerts: function(alertDelayTime) {
var gr = new GlideRecord(this.ALERT_QUEUE_TABLE);
gr.addQuery(this.STATE, this.STATES.PENDING);
gr.addQuery(this.SYS_CREATED_ON, "<", alertDelayTime);
if (this.changedAlertProcessingLimit > 0) { // unlimit the number of records by setting this property to 0 or less
gr.setLimit(this.changedAlertProcessingLimit);
}
// here we are sorting by Created_On since the alerts should to process record in order
gr.orderBy(this.SYS_CREATED_ON);
gr.query();
return gr;
},
addToAlertCIsTable: function(alertId, ciId, ciName, ciClass, alertDomain) {
if (alertId) {
if (ciId) { //If the record being added has a CI, need to remove any record with "empty" Ci value for this alert
this.removeEmptyCiRecordIfExists(alertId);
}
var addRecord = ciId ? !this.doesCiExistForAlert(alertId, ciId) : !this.doesAlertExistInCiTable(alertId);
if (addRecord) {
this.addToAlertCisMap(alertId, ciId);
this.addToAlertDomainMap(alertId, alertDomain);
if (ciId) {
this.addToCisExtraData(ciId, ciName, ciClass);
}
}
}
},
doesCiExistForAlert: function(alertId, ciId) {
if (alertId && ciId) {
//first check in the alertCisMap, if not found search the table
if (this.alertCisMap?.[alertId] && this.alertCisMap?.[alertId].has(ciId)) {
return true;
}
var gr = new GlideRecord(this.ALERT_CIS_TABLE);
gr.addQuery(this.ALERT, alertId);
if (ciId) {
gr.addQuery(this.CMDB_CI, ciId);
}
gr.setLimit(1);
gr.query();
return gr.next();
}
return false;
},
doesAlertExistInCiTable: function(parentId) {
//first check in the alertCisMap, if not found search the table
if (this.alertCisMap?.[parentId]) {
return true;
}
var gr = new GlideRecord(this.ALERT_CIS_TABLE);
return gr.get(this.ALERT, parentId);
},
removeEmptyCiRecordIfExists: function(alertId) {
//remove also from memory if exists
if (this.alertCisMap?.[alertId]) {
this.alertCisMap[alertId].delete("");
}
var gr = new GlideRecord(this.ALERT_CIS_TABLE);
gr.addQuery(this.ALERT, alertId);
gr.addNullQuery(this.CMDB_CI);
gr.query();
gr.deleteMultiple();
},
removeAllAlertRecords: function(alertId) {
if (alertId) {
this.evtMgmtCommons.addDebugLogNoPrefix(this.type + ': records for alert sys id: ' + alertId + ' are removed from ' + this.ALERT_CIS_TABLE + ', ' + this.ALERT_SERVICES_TABLE + ", and " + this.ALERT_TAGS_TABLE + ' tables.');
if (this.POPULATE_ALERT_CIS) {
delete this.alertCisMap[alertId];
var gr = new GlideRecord(this.ALERT_CIS_TABLE);
gr.addQuery(this.ALERT, alertId);
gr.query();
gr.deleteMultiple();
}
if (this.POPULATE_ALERT_SERVICES) {
delete this.alertServicesMap[alertId];
gr = new GlideRecord(this.ALERT_SERVICES_TABLE);
gr.addQuery(this.ALERT, alertId);
gr.query();
gr.deleteMultiple();
}
if (this.POPULATE_ALERT_TAGS) {
this.removeAlertTagsForAlert(alertId);
}
}
},
handleImpactedService: function(alertId, ciId, currAlertDomain, isGroupedAlert) {
//check if CI was allready handled for the alert
if (!this.doesCiExistForAlertService(alertId, ciId)) {
var impactedServices = this.getImpactedServicesOfCi(ciId);
if (impactedServices.length == 0) { // no impacted services
if (!isGroupedAlert || !this.doesGroupHaveImpactedServices(alertId)) {
this.addToAlertServicesTable(alertId, "", "", "", currAlertDomain, ciId);
}
} else {
for (var i = 0; i < impactedServices.length; i++) {
var impactedServiceObj = impactedServices[i];
this.addToAlertServicesTable(alertId, impactedServiceObj["sys_id"], impactedServiceObj["name"], impactedServiceObj["class"], currAlertDomain, ciId);
}
}
}
},
addToAlertServicesTable: function(alertId, bsId, bsName, bsClass, alertDomain, referenceCi) {
if (alertId) {
//If the record being added has an impacted service, need to remove any record with "empty" service value for this alert
if (bsId) {
this.removeEmptyBsRecordIfExists(alertId);
}
// search alertServicesMap before searchin in table.
if (this.alertServicesMap?.[alertId]?.[bsId]) { // if the service already exists for the alert - we should update the "reference ci" field.
if (referenceCi) {
this.alertServicesMap[alertId][bsId].add(referenceCi);
}
} else { // search the table for the alert-service record, if doesn't exist then add a new record.
var gr = new GlideRecord(this.ALERT_SERVICES_TABLE);
gr.addQuery(this.ALERT, alertId);
gr.addQuery(this.BUSINESS_SERVICE, bsId);
gr.query();
if (!gr.next()) { // add new record if doesn't exists
this.addToAlertServicesMap(alertId, bsId, referenceCi);
this.addToAlertDomainMap(alertId, alertDomain);
if (bsId) {
this.addToServicesExtraData(bsId, bsName, bsClass);
}
} else if (referenceCi) { // add the CI to the reference Ci list
var referenceCiList = gr.getValue(this.REFERENCE_CIS) || "";
//make sure the CI doesn't exists in the list
if (referenceCiList.indexOf(referenceCi) <= -1) {
gr.setValue(this.REFERENCE_CIS, referenceCiList + "," + referenceCi);
gr.update();
}
}
}
}
},
doesGroupHaveImpactedServices: function(parentId) {
if (parentId) {
//first check in the alertServicesMap, if not found search the table
if (this.alertServicesMap?.[parentId] && (Object.keys(this.alertServicesMap?.[parentId]).length == 0)) {
return true;
}
var gr = new GlideRecord(this.ALERT_SERVICES_TABLE);
gr.addQuery(this.ALERT, parentId);
gr.addNotNullQuery(this.BUSINESS_SERVICE);
gr.setLimit(1);
gr.query();
return gr.next();
}
return false;
},
doesCiExistForAlertService: function(alertId, ciId) {
if (alertId && ciId) {
//first check in the alertServicesMap, if not found search the table
if (this.alertServicesMap?.[alertId]) {
var services = Object.keys(this.alertServicesMap[alertId]);
for (var service of services) {
if (this.alertServicesMap[alertId][service].has(ciId)) {
return true;
}
}
}
var gr = new GlideRecord(this.ALERT_SERVICES_TABLE);
gr.addQuery(this.ALERT, alertId);
gr.addQuery(this.REFERENCE_CIS, 'LIKE', ciId);
gr.setLimit(1);
gr.query();
return gr.next();
}
return false;
},
removeEmptyBsRecordIfExists: function(alertId) {
if (alertId) {
//remove from memory if exists
if (this.alertServicesMap?.[alertId]?.[""]) {
delete this.alertServicesMap[alertId][""];
}
var gr = new GlideRecord(this.ALERT_SERVICES_TABLE);
gr.addQuery(this.ALERT, alertId);
gr.addNullQuery(this.BUSINESS_SERVICE);
gr.query();
gr.deleteMultiple();
}
},
getImpactedServicesOfCi: function(ciId) {
var impactedServices = [];
if (ciId) {
var impactGraphGr = new GlideAggregate(this.EM_IMPACT_GRAPH);
impactGraphGr.addQuery(this.STATUS, "valid").addOrCondition(this.STATUS, null);
impactGraphGr.addQuery(this.CHILD_ID, ciId);
impactGraphGr.groupBy(this.BUSINESS_SERVICE);
impactGraphGr.query();
while (impactGraphGr.next()) {
var bsId = impactGraphGr.getValue(this.BUSINESS_SERVICE);
var bsClass = impactGraphGr.business_service.sys_class_name;
var bsName = impactGraphGr.getDisplayValue(this.BUSINESS_SERVICE);
var bsObj = {};
bsObj[this.NAME] = bsName;
bsObj[this.CLASS] = bsClass;
bsObj[this.SYS_ID] = bsId;
impactedServices.push(bsObj);
}
}
return impactedServices;
},
addToAlertsQueue: function(alertId, parent, ciId, alertTags, actionType, additionalInfo, alertDomain) {
if (alertId) {
var gr = new GlideRecord(this.ALERT_QUEUE_TABLE);
gr.setValue(this.ALERT, alertId);
gr.setValue(this.PARENT, parent);
gr.setValue(this.ALERT_TAGS, alertTags);
gr.setValue(this.ACTION, actionType);
gr.setValue(this.CMDB_CI, ciId);
gr.setValue(this.STATE, this.STATES.PENDING);
gr.setValue(this.ADDITIONAL_INFO, additionalInfo);
gr.setValue(this.DOMAIN, alertDomain);
gr.insert();
}
},
addToAlertTagTable: function(alertId, tagName, tagValue, alertDomain) {
if (alertId && tagName) {
this.addToAlertTagsMap(alertId, tagName, tagValue);
this.addToAlertDomainMap(alertId, alertDomain);
}
},
removeAlertTagsForAlert: function(alertId) {
if (alertId) {
delete this.alertTagsMap[alertId];
var gr = new GlideRecord(this.ALERT_TAGS_TABLE);
gr.addQuery(this.ALERT, alertId);
gr.query();
gr.deleteMultiple();
}
},
parseJsonReturnEmptyDefault(jsonStr) {
try {
var obj = JSON.parse(jsonStr);
return obj;
} catch (e) {
return {};
}
},
shouldPopulateAlertTags: function() {
if (this.shouldPopulateTable(this.POPULATE_ALERT_TAGS_PROPERTY, true, this.ALERT_TAGS_TABLE)) {
var alertState = gs.getProperty('evt_mgmt.alert_tags_state', 'true');
if (alertState == 'true' || alertState == 'partial') { // check if "Alert tags" column exists in em_alert table
var gr = new GlideRecord(this.EM_ALERT_TABLE);
var element = gr.getElement(this.ALERT_TAGS);
return (element != undefined);
}
}
return false;
},
shouldPopulateTable: function(propertyName, defaultPropertyValue, tableName) {
return ((gs.getProperty(propertyName, defaultPropertyValue) == "true") && gs.tableExists(tableName));
},
checkBatchInsertMultiple: function(jsonArr, tableName, jsonCounter, limit) {
if (jsonCounter >= limit && jsonCounter > 0) {
var batchUtilMediator;
if (typeof new global.EvtMgmtAlertMgmtMediator().batchInsertMultiple == 'function') {
batchUtilMediator = new global.EvtMgmtAlertMgmtMediator();
} else {
batchUtilMediator = new global.EMLicensingUtilWrapper();
}
batchUtilMediator.batchInsertMultiple(JSON.stringify(jsonArr), tableName, '');
jsonCounter = 0;
jsonArr = [];
}
return [jsonCounter, jsonArr];
},
insertAlertCisBatchRecords: function() {
var alertCisJsonArr = [];
var alertCisCounter = 0;
for (var alert in this.alertCisMap) {
for (var ciId of this.alertCisMap[alert]) {
var json = {
[this.ALERT]: alert,
[this.CMDB_CI]: ciId,
[this.CI_NAME]: this.cisExtraData?.[ciId]?.[this.CI_NAME] ?? "",
[this.CI_CLASS]: this.cisExtraData?.[ciId]?.[this.CI_CLASS] ?? "",
[this.DOMAIN]: this.alertDomains?.[alert] ?? "global",
};
alertCisJsonArr.push(json);
alertCisCounter++;
[alertCisCounter, alertCisJsonArr] = this.checkBatchInsertMultiple(alertCisJsonArr, this.ALERT_CIS_TABLE, alertCisCounter, this.bulkLimit);
}
}
[alertCisCounter, alertCisJsonArr] = this.checkBatchInsertMultiple(alertCisJsonArr, this.ALERT_CIS_TABLE, alertCisCounter, 0);
},
insertAlertServicesBatchRecords: function() {
var alertServicesJsonArr = [];
var alertServicesCounter = 0;
for (var alert in this.alertServicesMap) {
for (var service in this.alertServicesMap[alert]) {
var json = {
[this.ALERT]: alert,
[this.BUSINESS_SERVICE]: service,
[this.BS_NAME]: this.servicesExtraData?.[service]?.[this.BS_NAME] ?? "",
[this.BS_CLASS]: this.servicesExtraData?.[service]?.[this.BS_CLASS] ?? "",
[this.REFERENCE_CIS]: Array.from(this.alertServicesMap[alert][service]).join(","),
[this.DOMAIN]: this.alertDomains?.[alert] ?? "global",
};
alertServicesJsonArr.push(json);
alertServicesCounter++;
[alertServicesCounter, alertServicesJsonArr] = this.checkBatchInsertMultiple(alertServicesJsonArr, this.ALERT_SERVICES_TABLE, alertServicesCounter, this.bulkLimit);
}
}
[alertServicesCounter, alertServicesJsonArr] = this.checkBatchInsertMultiple(alertServicesJsonArr, this.ALERT_SERVICES_TABLE, alertServicesCounter, 0);
},
insertAlertTagsBatchRecords: function() {
var alertTagsJsonArr = [];
var alertTagsCounter = 0;
for (var alert in this.alertTagsMap) {
for (var tagName in this.alertTagsMap[alert]) {
var json = {
[this.ALERT]: alert,
[this.TAG_NAME]: tagName,
[this.TAG_VALUE]: this.alertTagsMap?.[alert]?.[tagName] ?? "",
[this.DOMAIN]: this.alertDomains?.[alert] ?? "global",
};
alertTagsJsonArr.push(json);
alertTagsCounter++;
[alertTagsCounter, alertTagsJsonArr] = this.checkBatchInsertMultiple(alertTagsJsonArr, this.ALERT_TAGS_TABLE, alertTagsCounter, this.bulkLimit);
}
}
[alertTagsCounter, alertTagsJsonArr] = this.checkBatchInsertMultiple(alertTagsJsonArr, this.ALERT_TAGS_TABLE, alertTagsCounter, 0);
},
addToAlertCisMap: function(alertId, ciId) {
ciId = ciId ?? "";
if (!this.alertCisMap?.[alertId]) {
this.alertCisMap[alertId] = new Set();
}
this.alertCisMap[alertId].add(ciId);
},
addToAlertDomainMap: function(alertId, domain) {
if (!this.alertDomains?.[alertId]) {
this.alertDomains[alertId] = domain;
}
},
addToCisExtraData: function(ciId, ciName, ciClass) {
if (!this.cisExtraData?.[ciId]) {
var ciObj = {
[this.CI_NAME]: String(ciName),
[this.CI_CLASS]: String(ciClass)
};
this.cisExtraData[ciId] = ciObj;
}
},
addToServicesExtraData: function(bsId, bsName, bsClass) {
bsId = bsId ?? "";
if (!this.servicesExtraData?.[bsId]) {
var bsObj = {
[this.BS_NAME]: String(bsName),
[this.BS_CLASS]: String(bsClass)
};
this.servicesExtraData[bsId] = bsObj;
}
},
addToAlertServicesMap: function(alertId, serviceId, ciId) {
if (!this.alertServicesMap?.[alertId]) {
this.alertServicesMap[alertId] = {};
}
if (!this.alertServicesMap?.[alertId]?.[serviceId]) {
this.alertServicesMap[alertId][serviceId] = new Set();
}
this.alertServicesMap[alertId][serviceId].add(ciId);
},
addToAlertTagsMap: function(alertId, alertTag, value) {
value = value ?? "";
if (!this.alertTagsMap?.[alertId]) {
this.alertTagsMap[alertId] = {};
}
this.alertTagsMap[alertId][alertTag] = value;
},
type: 'EvtMgmtAlertCrawlerUtils'
};
Sys ID
82506e7707f62510b34ce06b0fd30081