Script not working as expected

pardhiv
Tera Contributor

I am trying to create 3 reports,
1. To show servers that are in scope (Operational status = operation AND install status = installed, Environment=Production) (Count 1424)

2. Servers that are in scope mapped to a application , (used sysId is one of and called a Script include) - 559 seems realistic

3. Servers that are in Scope and not mapped to a application (used sysId is one of and called a Script include) -Number is more than servers that are in Scope

 

unMappedSrvr: function() {

        var unMapdServer = [];
        var inScopeQuery = gs.getProperty('inscope.server.app.mapping');// Used same property for Mapped servers too
        var grSer2 = new GlideRecord('cmdb_ci_server');
        //grSer2.addEncodedQuery(inScopeQuery ); //Seems like this failing , return count shows more thanCIs as per below scope , returns 9000~
        grSer2.addEncodedQuery('install_status=1^environment=Production^operational_status=1'); //This is same filter as property, count is within scope, returns 751
        grSer2.query();
        while (grSer2.next()) {
            var grCrel = new GlideRecord('cmdb_rel_ci');
            grCrel.addQuery('child', grSer2.sys_id);
            grCrel.addQuery('parent.sys_class_name', 'INSTANCEOF', 'cmdb_ci_service_discovered');
            grCrel.query();
            if (!grCrel.next()) {
                unMapdServer.push(grSer2.sys_id.toString());
            }
            while (grCrel.next()) {
                var grDrel = new GlideRecord('cmdb_rel_ci');
                grDrel.addQuery('child', grCrel.parent);
                grDrel.addQuery('parent.sys_class_name', 'cmdb_ci_business_app');
                grDrel.query();
                if (!grDrel.next()) {
                    unMapdServer.push(grSer2.sys_id.toString());
                }
            }
        }
        return unMapdServer.join(',');
    },

 

pardhiv_0-1767848029986.png

pardhiv_1-1767848101035.png

 

 

 

1 ACCEPTED SOLUTION

SIVASANKARIS
Mega Guru

Hi @pardhiv ,

 I can see that there is some logic issues in the code, which may cause the mismatching in count

First One: You are using two grCrel.next() function along with if and while here 

 

  " if (!grCrel.next()) { ...

         while (grCrel.next()) {"  which is wrong because consider below scenarios

 

Scenario 1: When Server has NO relations, it will work fine

Step                                  What happens
grCrel.next()returns FALSE
IF blockruns → push server
while(grCrel.next())returns FALSE → loop skipped

BUT

Scenario 2:Server HAS relations (example: 2 relations) Rel1, Rel2

IFCondition: !grCrel.next()here our rel1 is checked and cursor is moved to rel2.

while(grCrel.next()) here in the while loop rel2 is checked, so rel1 will always be skipped

 

Second One: You are pushing server inside the loop which is causing the duplicates

 in this code portion: 

while(..){

{if (!grDrel.next())

{ unMapdServer.push(grSer2.sys_id.toString()); }}

 

Consider: If server 1 has 3 discovered service, none of these services are linked to business application means the same server will be pushed 3 times in the array

 

So the corrected code is...

unMappedSrvr: function() {

    var unMapdServer = [];
    var inScopeQuery = gs.getProperty('inscope.server.app.mapping'); 
    var grSer2 = new GlideRecord('cmdb_ci_server');

    grSer2.addEncodedQuery('install_status=1^environment=Production^operational_status=1');
    grSer2.query();

    while (grSer2.next()) {

        var isUnmapped = false;

        var grCrel = new GlideRecord('cmdb_rel_ci');
        grCrel.addQuery('child', grSer2.sys_id);
        grCrel.addQuery('parent.sys_class_name', 'INSTANCEOF', 'cmdb_ci_service_discovered');
        grCrel.query();

        // 1 If NO discovered service relation
        if (!grCrel.hasNext()) {
            isUnmapped = true;
        }

        // 2 If discovered services exist, check business app mapping
        while (!isUnmapped && grCrel.next()) {

            var grDrel = new GlideRecord('cmdb_rel_ci');
            grDrel.addQuery('child', grCrel.parent);
            grDrel.addQuery('parent.sys_class_name', 'cmdb_ci_business_app');
            grDrel.query();

            // If service NOT linked to business app
            if (!grDrel.hasNext()) {
                isUnmapped = true;
                break; // stop checking further services
            }
        }

        // 3 Push only once
        if (isUnmapped) {
            unMapdServer.push(grSer2.sys_id.toString());
        }
    }

    return unMapdServer.join(',');
}

 

Fix I applied

1) hasNext() ==> if (!grCrel.hasNext()) { ... } -> only checks if record exists, will not move the cursor to next record.

2)Handled duplicates ==> I avoided pushing the server inside the loop. Instead, I used a flag to mark the server as unmapped and immediately broke out of the loop when the condition was met. After exiting the loop, I pushed the server only once, which prevents duplicate entries.

 

I have made lot of efforts for this , if you find these useful please mark it as helpful and please accept my solution...

Best Regards,

SIVASANKARI S

ITOM Engineer

View solution in original post

5 REPLIES 5

Chaitanya ILCR
Mega Patron

Hi @pardhiv ,

 

Are you getting results when you call the script in the background script?if yes 

 

There is a checkbox called Sandbox Enabled on the script include table make it true and try 

 

 

Regards 

Chaitanya 

Ankur Bawiskar
Tera Patron

@pardhiv 

-> gs.getProperty() won't work in client callable script include when it's called from a reporting filter condition as it will be executed on client side.

I have faced similar challenge earlier and was surprised to know this drawback.

Instead you can query sys_properties table with that property name and get the value and then use

I shared solution for this in 2022

Client Callable Script include issue as script filter in reports 

Before: I am using gs.getProperty() and it didn't give result

gs getProperty in script include report filter condition not working.gif

After: I used GlideRecord to query properties and used and it worked

gs getProperty in script include report filter condition working with gliderecord.gif

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

@pardhiv 

Hope you are doing good.

Did my reply answer your question?

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

@pardhiv 

I think the response you marked correct is not valid as that doesn't answer your gs.getProperty() question.

the solution I shared talks about workaround for gs.getProperty() as it doesn't work in script include report filter conditions.

Please mark appropriate response as correct so that it helps future members.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader