Name

sn_em_arm.EvtMgmtAlertMgmtJobWrapper

Description

No description available

Script

gs.include('EvtMgmtCreateAlertMgmtJob');
gs.include('EvtMgmtUpdateAlertMgmtJob');

var EvtMgmtAlertMgmtJobWrapper = Class.create();
EvtMgmtAlertMgmtJobWrapper.prototype = {

  type: 'EvtMgmtAlertMgmtJobWrapper',
  /*
   * This scoped Alert Management job wrapper was changed from its Global version
   */

  initialize: function() {
      this.LAST_CALCULATED_INCIDENTS = "last_calculated_alert_job";
      this.LAST_CALCULATED_GROUPING_G1 = "analytics_trigger_g1";
      this.LAST_CALCULATED_GROUPING_G2 = "analytics_trigger_g2";
      this.LAST_CALCULATED_ALERT_MANAGEMENT = "last_calculated_alert_management_job";
      this.LAST_SIMULTANEOUSLY_CREATED_ALERT = "last_simultaneously_created_alert";
      this.LAST_SIMULTANEOUSLY_UPDATED_ALERT = "last_simultaneously_updated_alert";
      this.QUERY_JOB_LAST_RUN = "query_job_last_run";
      this.evtMgmtCommons = new global.EvtMgmtCommons();
      this.NUM_OF_PROCESS_JOBS = gs.getProperty('sn_em_arm.alert_management.num_of_jobs', 1);

  },

  execute: function() {
      this.executeForJob();
  },

  executeForJob: function(jobNum) {
      // If the "active AM scope" property is false then:
      // 1. Log warning that the AM scoped app is inactive.
      // 2. Don't execute the rest of the code.
      if (!global.EvtMgmtAlertMgmtProperties.isARMScopedAppActive()) {
          this.warnOnInactiveScopedApp();
          return;
      }

      var multiJobProcess = false;
      // validate the jobNum against the property
      // in case the jobNum is higher than|equals to the property - we fail the process since we don't want it to run and miss alerts processing
      // in case the jobNum is 0 and there property is 1 - we don't want to do the scale-out so we remove the jobNum and work in no-scale mode

      if(jobNum >= this.NUM_OF_PROCESS_JOBS){
          gs.error("ARM - wrong job number to process (higher than property - 'sn_em_arm.alert_management.num_of_jobs')");
          return null;
      }
      if(jobNum != null){
          if(jobNum == 0 && this.NUM_OF_PROCESS_JOBS == 1) {
          // use default no-multi job behavior
              gs.info("ARM - The property - 'sn_em_arm.alert_management.num_of_jobs' is 1 so this job is the only job running - use single job behavior");
              jobNum = null;
          }
          else
              multiJobProcess = true; 
      } 

      var lastArmJobHash, lastCreatedTimeHash, lastQueryJobRunHash, lastSimultaneouslyCreatedAlert, lastSimultaneouslyUpdatedAlert;
      var slowStepManager = new global.SlowStepJSManager();

      /* this code is now called from the Event Management - Close alerts when incident resolved
  	
  	slowStepManager.startStep(this.getScriptName() + ": legacy run actions");

      //Call legacy job, including close alert by incident logic and alert rule action caclulation 
      global.EvtMgmtAlertActions.runAlertActionsFromManagementJob();

      slowStepManager.startStep(this.getScriptName() + ": After legacy run actions");
  	*/
      slowStepManager.startStep(this.getScriptName() + ": Get hash");

      if (!multiJobProcess) {
          lastArmJobHash = this.getHash(this.LAST_CALCULATED_ALERT_MANAGEMENT); // Update job hash
          lastCreatedTimeHash = this.getHash(this.LAST_CALCULATED_GROUPING_G2); // Create job hash
          lastQueryJobRunHash = this.getHash(this.LAST_CALCULATED_GROUPING_G1); // Grouping hash
          lastSimultaneouslyCreatedAlert = this.getHashDefaultEmpty(this.LAST_SIMULTANEOUSLY_CREATED_ALERT);
          lastSimultaneouslyUpdatedAlert = this.getHashDefaultEmpty(this.LAST_SIMULTANEOUSLY_UPDATED_ALERT);
      } else {
          lastArmJobHash = this.getHash(this.LAST_CALCULATED_ALERT_MANAGEMENT, jobNum); // Update job hash
          lastCreatedTimeHash = this.getHash(this.LAST_CALCULATED_GROUPING_G2, jobNum); // Create job hash
          lastQueryJobRunHash = this.getHash(this.LAST_CALCULATED_GROUPING_G1); // Grouping hash
          lastSimultaneouslyCreatedAlert = this.getHashDefaultEmpty(this.LAST_SIMULTANEOUSLY_CREATED_ALERT, jobNum);
          lastSimultaneouslyUpdatedAlert = this.getHashDefaultEmpty(this.LAST_SIMULTANEOUSLY_UPDATED_ALERT, jobNum);
      }
      this.evtMgmtCommons.addDebugMessage('Start job EvtMgmtAlertMgmtJobWrapper.execute()\n Hash at the beginning:   lastCreatedTimeHash = ' + lastCreatedTimeHash.getValue('hash') + ', lastQueryJobRunHash = ' + lastQueryJobRunHash.getValue('hash') + ', lastArmJobHash = ' + lastArmJobHash.getValue('hash'));
      
      //in case the grouping is not running for 5 minutes, the feature disabled, 
      //do not block the Alert Management in case the grouping is not working well or disabled.
      var gdt = new GlideDateTime();
      var backMillis = gs.getProperty('evt_mgmt.avoid_int_interval', "300000");
      var groupingHashTime = new GlideDateTime(lastQueryJobRunHash.getValue('hash'));

      var timeNow = gdt.getNumericValue();

      var useQueryLastRun = gs.getProperty('evt_mgmt.use_query_last_runtime', 'true') == 'true';
      var timeG1 = useQueryLastRun ? this.getQueryJobLastRun(groupingHashTime) : groupingHashTime.getNumericValue();

      var timeEnabled = timeNow - timeG1 < backMillis;

      //if the grouping is not running for the 'backMillis' time, there is need to 
      //change the grouping hash so we do not miss created alerts.
      if (!timeEnabled) {
          lastQueryJobRunHash.setValue('hash', gdt);
          lastQueryJobRunHash.update();
      }

      var isAvoidIntsEnabled = gs.getProperty('evt_mgmt.avoid_int_enabled', 'false') == 'true';
      var isAggregationDisabled = gs.getProperty('sa_analytics.aggregation_enabled', 'true') == 'false';
      var waitForGrouping = isAvoidIntsEnabled && !isAggregationDisabled;

      if (waitForGrouping) {
          var alertMgmtForCreated = new EvtMgmtCreateAlertMgmtJob(slowStepManager, lastArmJobHash, lastQueryJobRunHash, lastCreatedTimeHash, true, lastSimultaneouslyCreatedAlert);
          alertMgmtForCreated.evaluateAlertsCalc(jobNum);
      }

      var alertMgmtForUpdated = new EvtMgmtUpdateAlertMgmtJob(slowStepManager, lastArmJobHash, lastQueryJobRunHash, lastCreatedTimeHash, waitForGrouping, lastSimultaneouslyUpdatedAlert);
      alertMgmtForUpdated.evaluateAlertsCalc(jobNum);

      slowStepManager.report();
  },

  getHash: function(hashName, jobNum) {
      if(jobNum != null)
          hashName = this.createHashNameWithJobNum(hashName, jobNum);
      var hashGr = this.evtMgmtCommons.getHashGr(hashName);
      if (!(hashGr.next())) {
          hashGr = this.getOrCreateHashTimestamp(hashName);
          hashGr = this.evtMgmtCommons.getHashGr(hashName);
          hashGr.next(); //need to run the next to get the record
      }
      return hashGr;
  },

  getOrCreateHashTimestamp: function(hashName) {
      //setting an the initial time based on last incident time or the current time if doesn't exist
      var timeStamp;
      var incidentHashGr = this.evtMgmtCommons.getHashGr(this.LAST_CALCULATED_INCIDENTS);
      if (incidentHashGr.next())
          timeStamp = incidentHashGr.getValue('hash');
      else
          timeStamp = new GlideDateTime();

      var hashGr = new GlideRecord('sa_hash');
      hashGr.name = hashName;
      hashGr.hash = timeStamp;
      hashGr.insert();
  },

  getHashDefaultEmpty: function(hashName, jobNum) {
      var hashGr;
      if(jobNum != null)
  		hashName = this.createHashNameWithJobNum(hashName, jobNum);
  	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 hashGr;
  },

  createHashNameWithJobNum: function(hashName, jobNum){
      return hashName+ "_" + jobNum;
  },

  // Log a warning that the AM scoped app is inactive. 
  // The warning will be logged about 2-3 times every 10 minutes.
  warnOnInactiveScopedApp: function() {
      var gdt = new GlideDateTime();
      var minutes = gdt.getTime().getMinutesLocalTime();
      var seconds = gdt.getTime().getSeconds();

      var isTenMinutesCycle = !(minutes % 10); // Every 10 minutes (00, 10, 20, 30, 40, 50)
      var limitPerMinute = seconds < 30; // This script is called by the scheduled job every 11 minutes, so the warning will show 2-3 times

      if (isTenMinutesCycle && limitPerMinute) {
          var message = gs.getMessage('{0} script include: The "{1}" property is set to "false", therefore the Alert Rules Management Scoped application is inactive. In order to make it active, activate the "Event Management - Automated migration to Alert Management Scoped app" scheduled job.', [this.getScriptName(), 'evt_mgmt.alert_management_scoped_active']);

          gs.warn(message);
      }
  },

  getScriptName: function() {
      return this.type;
  },

  getQueryJobLastRun: function(groupingHashTime) {
      var hashGr = this.evtMgmtCommons.getHashGr(this.QUERY_JOB_LAST_RUN);
      if ((hashGr.next())) {
          var lastQueryRunTime = new GlideDateTime(hashGr.getValue('hash'))
          return lastQueryRunTime.getNumericValue();
      }
      //if the hash wasn't found check the last update of the query job
      var jobGr = new GlideRecord("sys_trigger");
      jobGr.addQuery("name", "Service Analytics group alerts using RCA");
      jobGr.query();
      if (jobGr.next()) {
          var lastQueryRunTime = new GlideDateTime(jobGr.getValue('sys_updated_on'));
          return lastQueryRunTime.getNumericValue();
      }
      return groupingHashTime.getNumericValue();
  },

};

Sys ID

6ffbfa12b75920107c038229ce11a9b8

Offical Documentation

Official Docs: