The Zurich release has arrived! Interested in new features and functionalities? Click here for more

Mark Roethof
Tera Patron
Tera Patron

Articles, Blogs, Videos, Podcasts, Share projects - Experiences from the field

 

Hi there,

 

When talking about Instance Scan, mostly mentioned is the ability to perform checks on code, certain settings on Business Rules, Client Scripts, Script Includes, etcetera. In my opinion: Instance Scan can be utilized for way more! I've shared in the past several thoughts on this, like Sanity checks, Core Configuration checks, and... Data checks!

 

Especially the Data checks I would like to give some attention again. With this article, I will share two nice examples which will bring certain Data issues on production instances to the surface. Data checks that a System Administration should perform regularly, though which can be difficult to perform manually or which can be too time-consuming to perform. Data issues that might be minor, though which could also have serious consequences for related data / reporting / automation / etcetera.

 

Let's have a look at:
- Task records with broken references
- Many-to-many records with broken references

Task records with broken references

The first example I would like to share concerning data checks is a commonly seen issue on production instances: "Task records with broken references". For example task records where the "Assignment group" value or "Configuration item" value is invalid. Invalid as in it has a value, though the record doesn't exist. This can be just a minor issue, though it can also have huge consequences when there's logic based on that reference, when reporting, etcetera.

 

Especially on older instances, you could be faced with thousands of findings. Obviously you need to consider fixing the data, though also searching for the issue which is actually causing this. It might be an incorrect reference in a Flow, Workflow, Business Rule, scripting, integration, etcetera.

 

On larger instances, this check might run longer than the default maximum of 600 seconds and therefore end in a failure. Consider looking into this.

Script Only Check

(function (engine) {

    // Get all task extended tables
    var table_list = new TableUtils('task').getAllExtensions() + '';
    table_list = table_list.replace('[', '').replace(']', '');

    // Define arrays
    var reference_field = [],
        sysid_arr = [];

    // Query reference fields
    var grDictionaryEntry = new GlideRecord('sys_dictionary');
    grDictionaryEntry.addEncodedQuery('internal_type=reference^active=true^nameIN' + table_list);
    grDictionaryEntry._query();

    while(grDictionaryEntry._next()) {
        var getRecord = new GlideRecord(grDictionaryEntry.getValue('name'));
        getRecord.addEncodedQuery(grDictionaryEntry.getValue('element') + 'ISNOTEMPTY^' + grDictionaryEntry.getValue('element') + '.sys_idISEMPTY');
        getRecord.addActiveQuery();
        getRecord._query();

        // Create scan finding
        while(getRecord._next()) {
            if(sysid_arr.indexOf(getRecord.getUniqueValue()) == -1) {
                sysid_arr.push(getRecord.getUniqueValue());

                engine.finding.setCurrentSource(getRecord);
                engine.finding.increment();
            }
        }
    }

})(engine);

 

Many-to-many records with broken references

The second example I would like to share concerning data checks is concerning a situation that I came across at a few customers: "Many-to-many records with broken references". For example many-to-many records which have been created, manually or through scripted logic, where somehow the "from field" value or the "to field" value is invalid. Invalid as in it has a value, though the record doesn't exist. Obviously this could lead to the relationship between both records not working, not being visible, logic based on this which won't work, etcetera.

 

Obviously you need to consider fixing the data, though also searching for the issue which is actually causing this. It might be an incorrect reference in a Flow, Workflow, Business Rule, scripting, integration, etcetera.

Script Only Check

(function (engine) {

    // Query M2M Definition records
    var grM2MDefinition = new GlideRecord('sys_m2m');
    grM2MDefinition.addEncodedQuery('m2m_tableISNOTEMPTY^m2m_to_fieldISNOTEMPTY^m2m_from_fieldISNOTEMPTY');
    grM2MDefinition._query();

    while(grM2MDefinition._next()) {
        if(gs.tableExists(grM2MDefinition.getValue('m2m_table')) && gs.tableExists(grM2MDefinition.getValue('from_table')) && gs.tableExists(grM2MDefinition.getValue('to_table'))) {
            var getRecord = new GlideRecord(grM2MDefinition.getValue('m2m_table'));
            getRecord.addEncodedQuery(grM2MDefinition.getValue('m2m_to_field') + 'ISNOTEMPTY^' + grM2MDefinition.getValue('m2m_to_field') + '.sys_idISEMPTY^NQ' + grM2MDefinition.getValue('m2m_to_field') + 'ISNOTEMPTY^' + grM2MDefinition.getValue('m2m_to_field') + '.sys_idISEMPTY');
            getRecord.addActiveQuery();
            getRecord._query();

            // Create scan finding
            while(getRecord._next()) {
                engine.finding.setCurrentSource(getRecord);
                engine.finding.increment();
            }
        }
    }

})(engine);

---


And that's it! Two examples of data checks, which are hard to perform manually though which are quite important. Data checks which could be perfectly executed using Instance Scan.

I do have to review the code a bit, nested queries... maybe your code good practices Scan Checks will bring this up 🙂

 

 

C

If this content helped you, I would appreciate it if you hit bookmark or mark it as helpful.

 

Interested in more Articles, Blogs, Videos, Podcasts, Share projects I shared/participated in?
- Articles, Blogs, Videos, Podcasts, Share projects - Experiences from the field

 

Kind regards,


Mark Roethof

Independent ServiceNow Consultant
3x ServiceNow Developer MVP

3x ServiceNow Community MVP

---

LinkedIn

Comments
Maik Skoddow
Tera Patron
Tera Patron

Hi @Mark Roethof 

does the code for the M2M broken reference check have an error?

Instead of querying the m2m_to_field two times:

getRecord.addEncodedQuery(
	grM2MDefinition.getValue('m2m_to_field') + 'ISNOTEMPTY^' + 
	grM2MDefinition.getValue('m2m_to_field') + '.sys_idISEMPTY^NQ' + 
	grM2MDefinition.getValue('m2m_to_field') + 'ISNOTEMPTY^' + 
	grM2MDefinition.getValue('m2m_to_field') + '.sys_idISEMPTY'
);

it should be:

getRecord.addEncodedQuery(
	grM2MDefinition.getValue('m2m_to_field') + 'ISNOTEMPTY^' + 
	grM2MDefinition.getValue('m2m_to_field') + '.sys_idISEMPTY^NQ' + 
	grM2MDefinition.getValue('m2m_from_field') + 'ISNOTEMPTY^' + 
	grM2MDefinition.getValue('m2m_from_field') + '.sys_idISEMPTY'
);

 

Version history
Last update:
‎08-08-2024 08:44 AM
Updated by:
Contributors