Some Impacted Services/CIs are missing on the list

MandyMaseyM
Giga Contributor

Hi guys, I need help on what seems to be the problem with our UI Action Refresh Impacted Services.

 

Some Impacted Services/CIs of the Affected CI are missing on the list whenever we click the Refresh Impacted Services.

 

For example, In this screenshot, it supposed to have 14 records, but only 9 are added.

 

CI 1.jpg

 

var CI_rel_Utils = Class.create();
CI_rel_Utils.prototype = Object.extendsObject(CIUtils, {

    /*
     * Refresh impacted services by analyzing affected CIs.
     * This will only considers in scope classess on Affected CI when analyzing the impacted Services
     */

	// This is the function that will be called once the Refresh Impacted Services button was clicked
    refreshImpactedServicesAffectedCIs: function(current) {
        this.removeImpactedServices(current.sys_id); // Clear Existing Impacted Services

        // Call the system property: CMDB_Scope_CI
        var inScopeProp = gs.getProperty('CMDB_Scope_CI, '');

		// Convert the sys_propertyto an array to extract all the in scope classes and use it in the logic to make sure only in scope Affected CI will be included when it refresh the impacted services
        var inScopeClasses = inScopeProp.split(',').map(function(cls) {
            return cls.trim(); 
        });

		// Initiate the Array to store later the impacted Services
        var impactedServices = [];

        // Fetch affected CIs from task_ci table
        var affectedCI = new GlideRecord('task_ci');
        affectedCI.addQuery('task', current.sys_id);
        affectedCI.query();

		// Loop through the affected CI's and decide which affected CI's will be included to be analyzed
        while (affectedCI.next()) {
            var ci = affectedCI.ci_item;
            var ciName = ci.name.toString();
            var ciClass = ci.sys_class_name.toString();

			// If the aFfected CI is not included in the in scope classes, then skip it
            if (inScopeClasses.indexOf(ciClass) === -1) {
                gs.info('[Excluded CI - Not in Scope] ' + ciName + ' [' + ciClass + ']');
                continue; // This Skips the Affected CI if it is not included in the in scope classes
            }

            // Fetch all the Services that are impacted by the Affected CI
			// Calls the function _getRelevantRelatedCIs and pass the affected CI sys_id as a parameter
            var relatedCIs = this._getRelevantRelatedCIs(ci.sys_id); 

			// Set the Returned result of the function to impacted Services
            impactedServices = relatedCIs; 
        }

        // Remove any duplicate Impcated Service
		// Use the ArrayUtil to call the functiOn unique to remove the duplicate services
        var arrayUtil = new ArrayUtil();

		// This has now the array or storage of the unique Impacted Services
        var uniqueServices = arrayUtil.unique(impactedServices);

        // Remove services already linked
        var existing = new GlideRecord('task_cmdb_ci_service');
        existing.addQuery('task', current.sys_id);
        existing.query();
        while (existing.next()) {
            var sid = existing.cmdb_ci_service.toString();
            var index = uniqueServices.indexOf(sid);
            if (index > -1) {
                uniqueServices.splice(index, 1);
                gs.info('[Excluded Service - Already Linked] ' + existing.cmdb_ci_service.name);
            }
        }

        if (uniqueServices.length > 0) {
            this.addImpactedServices(current.sys_id, uniqueServices);

            // Show Log for debugging purposes while making the code
			// This will show all the Impacted Services that are added
            var svcNames = [];
            var svcGR = new GlideRecord('cmdb_ci_service');
            svcGR.addQuery('sys_id', 'IN', uniqueServices.join(','));
            svcGR.query();
            while (svcGR.next()) {
                svcNames.push(svcGR.name.toString());
            }
            gs.info('[Included Services] ' + svcNames.join(', '));
            gs.addInfoMessage('Impacted services added: ' + uniqueServices.length);
        } else {
            gs.addInfoMessage('No new impacted services to add.');
        }
    },

    /**
     * Identify relevant CIs by following specific upstream relationships:
     * - Depends on::Used by (child = affected CI)
     * - Contains::Contained by (child = affected CI)
     * - Virtualized by::Virtualizes (parent = affected CI)
     *   → then find upstream (Used by / Contained by) of the virtualized CI
     */
    _getRelevantRelatedCIs: function(ciSysId) {
        gs.info("SYSID OF CiSysId" + ciSysId); 
        var relevant = [];

        // Handle the Mapped Application Service and Service Offering
		// This will handle the analization as well as inclusion of the Impacted Services for Mapped Application Service and Service Offering
        var upstreamRel = new GlideRecord('cmdb_rel_ci');
        upstreamRel.addEncodedQuery(
            'child.sys_id=' + ciSysId +
			// Include Service Offering and Mapped Application Service
            '^parent.sys_class_name=cmdb_ci_service_offering' + 
			'^ORparent.sys_class_name=cmdb_ci_service_discovered' + 
			// Exclude the windows server for now as this needs to be handled in a different approach
            '^ORparent.sys_class_name!=cmdb_ci_win_server' + 
			// exclude anything related to VM
            '^child.sys_class_name!=cmdb_ci_vmware_instance' + 
            '^ORchild.sys_class_name!=cmdb_ci_vcenter_dv_port_group' + 
            '^ORchild.sys_class_name!=cmdb_ci_vcenter_vm_group' + 
			// Relationship Type provided by::provides and members::member of
	    '^type.sys_id!=4afd799338a02000c186b817' + 
            '^type.sys_id!=55c913d3c0a8010e012d6050' 
        );
        upstreamRel.query();
		// As sys_id cannot be used due to cmdb_rel_ci has a different sys_id from the cmdb_ci_service so the name was used instead
        while (upstreamRel.next()) {
			// Query the cmdb_ci_service using the name to get the real sys_id of the impacted Service
            var getCmdbServiceSysId = new GlideRecord('cmdb_ci_service');
            getCmdbServiceSysId.addEncodedQuery(
				// Name of the Parent of the Affected CI
                'name=' + upstreamRel.parent.name 
            );
            getCmdbServiceSysId.query();
            if (getCmdbServiceSysId.next()) {
				// Store the Impacted Service Offering or Mapped Application Service Services
                relevant.push(getCmdbServiceSysId.sys_id);
                gs.info('[Final Relevant CI - Upstream] ' + getCmdbServiceSysId.name + ' (' + getCmdbServiceSysId.sys_id + ') via ' + upstreamRel.type.name);
            } else {
                gs.warn('No cmdb_ci_service found with name=' + upstreamRel.parent.name);
            }
        }

        // Handle the Windows Server/Virtualized by::Virtualizes
        var virtRel = new GlideRecord('cmdb_rel_ci');
        virtRel.addEncodedQuery(
            'child.sys_id=' + ciSysId +
			// exclude VM Instance
            '^child.sys_class_name!=cmdb_ci_vmware_instance' + 
			// exclude vcenter port group
            '^ORchild.sys_class_name!=cmdb_ci_vcenter_dv_port_group' + 
			// exclude bm group
            '^ORchild.sys_class_name!=cmdb_ci_vcenter_vm_group' + 
			// Include all Windows Server
            '^parent.sys_class_name=cmdb_ci_win_server' + 
			// Include Virtualized by::Virtualizes type
            '^type.sys_id=d93304fb0a0a6081a72ef08444' 
        );
        virtRel.query();
        while (virtRel.next()) {
			// As sys_id cannot be used due to cmdb_rel_ci has a different sys_id from the cmdb_ci_win_server so the name was used instead
            var getCmdb = new GlideRecord('cmdb_ci_win_server');
            getCmdb.addEncodedQuery(
                'name=' + virtRel.parent.name
            );
            getCmdb.query();
			// Log the Windows Server Parent of the Affected CI
            if (getCmdb.next()) {
                gs.info('[Relevant CI - Upstream VM] ' + getCmdb.name + ' (' + getCmdb.sys_id + ') via ' + virtRel.type.name + 'name in relationship is' + virtRel.parent.name);
            } else {
                gs.warn('No cmdb_ci_service found with name=' + virtRel.parent.name);
            }
            // Set the correct sys_id of the Window Server Parent to a new variable
            var vmId = getCmdb.sys_id; 

            // Since we already have the correct sys_id of the Windows Server Parent, We will now query the Parent and get the Impacted Services
            var vmUpstream = new GlideRecord('cmdb_rel_ci');
            vmUpstream.addEncodedQuery(
                'child.sys_id=' + vmId +
				// Exclude the Service Offering and Mapped Application Services since they are already handled completely and has a different approach to get
                '^parent.sys_class_name!=cmdb_ci_service_offering' +
                '^ORparent.sys_class_name!=cmdb_ci_service_discovered' +
				// Exclude anything related to VM
                '^child.sys_class_name!=cmdb_ci_vmware_instance' +
                '^ORchild.sys_class_name!=cmdb_ci_vcenter_dv_port_group' +
                '^ORchild.sys_class_name!=cmdb_ci_vcenter_vm_group' +
				// Include only Parents that are Windows Server
                '^parent.sys_class_name!=cmdb_ci_win_server'
            );
            vmUpstream.query();
            while (vmUpstream.next()) {
				// Query the cmdb_ci_service to get the correct sys_id of the Impacted Services as the cmdb_rel_ci has a different sys_id
                var getWindowsServerCmdbServiceSysId = new GlideRecord('cmdb_ci_service');
                getWindowsServerCmdbServiceSysId.addEncodedQuery(
                    'name=' + vmUpstream.parent.name // name of parent in cmdb_rel_ci
                );
                getWindowsServerCmdbServiceSysId.query();
				// Store the Impacted Services
                if (getWindowsServerCmdbServiceSysId.next()) {
                    relevant.push(getWindowsServerCmdbServiceSysId.sys_id);
                    gs.info('[FINAL Relevant CI for Windows Server] ' + getWindowsServerCmdbServiceSysId.name + ' (' + getWindowsServerCmdbServiceSysId.sys_id + ') via ' + vmUpstream.type.name);
                } else {
                    gs.warn('No cmdb_ci_service found with name=' + vmUpstream.parent.name);
                }
            }
        }

        gs.info('Final Relevant CI Sys IDs: ' + JSON.stringify(relevant));
        gs.info('Final Relevant CI Sys IDs: ' + relevant);
        return new ArrayUtil().unique(relevant);
    },

    type: 'CI_rel_Utils'
});
1 REPLY 1

AJ-TechTrek
Giga Sage
Giga Sage

Hi @MandyMaseyM ,

 

As per my understanding Likely Root Causes:


1. Missing or Incorrect CI Relationships
The “Refresh Impacted Services” button relies on CI Relationship data (e.g., Depends on, Used by) in the cmdb_rel_ci table.
* If 5 services are missing, check if:
* The affected CIs have proper downstream relationships to the missing services.
* Relationships are of the correct type (should be “Impacts”, “Depends on”, etc., not generic ones like “Installed on”).
Fix: Go to the CI Relationship Editor (CI Form > Related Items > Relationships) and ensure missing services are properly linked to their upstream CIs.

 

2. Impact Analysis Rules Misconfiguration
The Refresh button logic is driven by Impact Analysis Rules (cmdb_impact_analysis_rule).
* These rules determine how to traverse relationships to find related services.
* If the rule excludes certain relationship types or CI classes, then some services won’t be picked up.
Fix: Review the rules under "Impact Analysis Rules":
* Navigate to: CMDB > Impact Analysis > Rules
* Look for the rule associated with your CI class (e.g., Server, Application Service)
* Ensure it's not overly restrictive

 

3. Change Request/Task Not Linked to Parent CI Properly
* If the task or change is associated with a CI, and that CI isn’t a part of the service hierarchy, the impact refresh may not identify all downstream services.
Fix: Double-check that the primary Affected CI belongs to or is related to the full service structure.

 

4. Scripted Logic Behind the UI Action is Customized or Broken
If your instance has custom logic in the Refresh UI Action, it may not cover all relationship types or CI types.
Fix:
* Check the script behind the "Refresh Impacted Services" UI Action.
* Compare it with OOTB (Out-of-the-box) version if customization is suspected.
* Script may use a GlideRecord loop that skips certain records.

 

5. CI Relationship Direction is Inverted
* Discovery or manual data entry might create relationships in reverse direction.
* Example: Web Server depends on Application, but Discovery may create Application → Depends on → Web Server — breaking the expected chain.
Fix: Use CI Relationship Viewer to visualize and correct relationship direction.

 

Diagnostic Steps Checklist:
Checkpoint How
Validate CI Relationships = Open affected CI → Relationships tab → Review downstream services
 Review Impact Rules = CMDB → Impact Analysis Rules → Check class and relationship rules
Test Refresh Script = Debug the Refresh Impacted Services UI Action script
 Compare Record Counts =  Use script to simulate expected records (see below)

 

Optional Script to Compare Expected vs Actual:
var gr = new GlideRecord('cmdb_rel_ci');
gr.addQuery('parent.name', 'Infrastructure Jump server'); // Replace with your affected CI name
gr.query();
while (gr.next()) {
gs.print('Related CI: ' + gr.child.name + ', Type: ' + gr.type.name);
}

 

Final Recommendation:
1. Run the above script to find what’s missed.
2. Check if any missing records are due to relationship misconfig.
3. If all looks correct, check the business rules or customizations done to the UI Action logic.
4. Consider running the CMDB Health Dashboard → Relationship Compliance to spot inconsistencies.

 

 

Please appreciate the efforts of community contributors by marking appropriate response as Mark my Answer Helpful or Accept Solution this may help other community users to follow correct solution in future.
 

Thank You
AJ - TechTrek with AJ - ITOM Trainer
LinkedIn:- https://www.linkedin.com/in/ajay-kumar-66a91385/
YouTube:- https://www.youtube.com/@learnitomwithaj
Topmate:- https://topmate.io/aj_techtrekwithaj (Connect for 1-1 Session)
ServiceNow Community MVP 2025