The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Mark Roethof
Tera Patron
Tera Patron

Hi there,

Instance Scan Scan Checks are singular focused rules that detect anomalies or opportunities in an instance. These checks can run against tables, records, or metadata. There are four different types of Scan Checks: Table Check, Column Type Check, Script Only Check, and Linter Check.

While the four types of Scan Checks are described on the ServiceNow Docs, especially getting started with the Linter Check can be quite hard. I did wrote an article a few months back exploring Linter Checks. Linter Checks is also explained by Daniel Draes in the Platform Foundation Academy.

With this article I'll be providing some more examples of Linter Checks.


Linter Check versus Column Type Check

Before sharing a few Linter Check examples, let's provide a bit more background. Why would you use Linter Check instead of Column Type Check? Well not because it's easier, when starting with Linter Checks it takes a while to get going.
There are numerous reasons for using Linter Checks, though the reasons which stand out for me most are:
- Linter Checks can be used for more complex checks within scripts;
- With Linter Check you can make your script more robust;
- Commented code is ignored.


Linter Check examples

Consider using getXMLAnswer instead of getXML

Description
getXMLAnswer only retrieves the Answer which we are actually after. getXML retrieves the whole XML document. In most cases, we are not interested in the whole XML document, though only in the Answer.

Documentation
https://community.servicenow.com/community?id=community_article&sys_id=1c10a1fedbbd4890feb1a851ca961909

Script

(function (engine) {

	// Perform Linter Check
	engine.rootNode.visit(function(node) {
		if(node.getTypeName() === "NAME" &&
		   node.getNameIdentifier() === "getXML" &&
		   node.getParent().getTypeName() === "GETPROP") {
			// Create scan finding
			engine.finding.incrementWithNode(node);
		}
	});

})(engine);


Scripts should not contain debugging statements in production

Description
The "gs.log()", "gs.debug()", "console.log()", etc. statements can be used to write information to the system log, while the "gs.print()", etc. statements also sends it as output to the screen. It is generally used when debugging. Using "gs.log()", "gs.debug()", "console.log()", etc. statements on a production instance will pollute the system log, while it is never used as you do not perform debugging on a production instance.

Script

(function(engine) {

	engine.rootNode.visit(function(node) {
		// gs.log, gs.info, gs.debug, gs.print
		if(node.getTypeName() === "GETPROP") {
			var gs_found = false;
			var method_found = false;

			node.visit(function(childnode) {
				if(childnode.getTypeName() != "NAME") {
					return;
				}

				if(childnode.getNameIdentifier() === "log" || childnode.getNameIdentifier() === "info" || childnode.getNameIdentifier() === "debug" || childnode.getNameIdentifier() === "print") {
					method_found = true;
					return;
				}

				if(childnode.getNameIdentifier() === "gs") {
					gs_found = true;
					return;
				}
			});

			// Create scan finding
			if(gs_found && method_found) {
				engine.finding.incrementWithNode(node);
			}
		}

		// console.log
		if(node.getTypeName() === "GETPROP") {
			var console_found = false;
			var log_found = false;

			node.visit(function(childnode) {
				if(childnode.getTypeName() != "NAME") {
					return;
				}

				if(childnode.getNameIdentifier() === "log") {
					log_found = true;
					return;
				}

				if(childnode.getNameIdentifier() === "console") {
					console_found = true;
					return;
				}
			});

			// Create scan finding
			if(console_found && log_found) {
				engine.finding.incrementWithNode(node);
			}
		}

		// jslog
		if(node.getNameIdentifier() && node.getTypeName() === 'NAME' && node.getNameIdentifier() === 'jslog' && node.getParent().getTypeName() === 'CALL') {
			// Create scan finding
			engine.finding.incrementWithNode(node);
		}

	});

})(engine);


Don't use new Object()

Description
In general, you should use the object literal notation when possible. It is easier to read, it gives the compiler a chance to optimize your code, and it's mostly faster too.

Documentation
https://www.java67.com/2014/08/difference-between-string-literal-and-new-String-object-Java.html

Script

(function (engine) {

	// Perform Linter Check
	engine.rootNode.visit(function(node) {
		if(node.getTypeName() === "NAME" &&
		   node.getNameIdentifier() === "Object" &&
		   node.getParent().getTypeName() === "NEW") {
			// Create scan finding
			engine.finding.incrementWithNode(node);
		}
	});

})(engine);


GitHub example-instancescan-checks

The example Linter Checks mentioned in this article can also be found on the "example-instancescan-checks" GitHub repository. Also other Scan Checks can be found there which have been contributed by several people.

---


And that's it actually. Hope you like it. If any questions or remarks, let me know!

👍
If this post helped you in any way, I would appreciate it if you hit bookmark or mark it as helpful.

Interested in more articles, blogs, videos, and Share projects on Instance Scan I published?
Instance Scan


Kind regards,
Mark
2020-2021 ServiceNow Community MVP
2020-2021 ServiceNow Developer MVP

---

LinkedIn

Comments
Sascha Wildgru1
ServiceNow Employee
ServiceNow Employee

The CodeSanity app contains a set of Instance Scan checks aimed at improving source code and application quality. Developers should run them before shipping a new application version.

Check it out for more linter check examples 😉

Vote to make it part of the platform OOTB!

https://community.servicenow.com/community?id=view_idea&sysparm_idea_id=23716958db25d514904fa9fb1396...

Or install it right away:

https://www.wildgrube.com/servicenow-codesanity

Version history
Last update:
‎10-17-2021 09:19 PM
Updated by: