
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
NOTE: MY POSTINGS REFLECT MY OWN VIEWS AND DO NOT NECESSARILY REPRESENT THE VIEWS OF MY EMPLOYER, ACCENTURE.
DIFFICULTY LEVEL: INTERMEDIATE
Assumes having taken the class SSNF and has good intermediate level of knowledge and/or familiarity with Scripting in ServiceNow.
In my Scripting classes I have demonstrated some techniques concerning the more advanced side of server-side logging and debugging that is available to ServiceNow scripters. It is interesting how little is written about these capabilities, and how few are the examples on how to actually use some of the cooler features. I thought I would try to bring together a few examples of these techniques into a single location.
All of the following examples can be tested using Scripts - Background. If you are interested in what these are you might want to first read my article contrasting the two methods.
Before getting started with the following examples, you might consider reading these articles on logging:
Scripting Alert, Info, and Error messages
So, first thing to do is set up some test data to use in our logging tests:
var location = 'BS:Logging Testing';
var spuriousText = 'Danger';
// go grab a single most recent incident record.
// I used "current" as a variable name for later
// use in a Business Rule
var current = new GlideRecord('incident');
current.addActiveQuery();
current.setLimit(1);
current.orderByDesc('number');
current.query();
current.next();
var number = current.number;
var caller = current.caller_id.getDisplayValue();
var category = current.category.getDisplayValue();
var impact = current.getValue('impact');
var priority = current.getValue('priority');
var urgency = current.getValue('urgency');
Now that we have our test data, for each of our examples, let's get started!
Let's look at a GlideSystem method called: getMessage. getMessage was how we used to do variable substitution in gs.log before we were given the new gs.info, error, and warn message capability. Here is an example:
var message = gs.getMessage('--->[{2}] GETMESSAGE: \n\tNumber: {0} \n\tCaller: {1}',
[number, caller, location]);
gs.log(message); // location embedded in message
This gives you something like the following results:
*** Script: --->[BS:Logging Testing] GETMESSAGE: Number: INC0009009 Caller: David Miller
Notice that variables are placed inside an array. This is how getMessage variable substitution works. Otherwise, with no array brackets, it will only use the first variable and ignore the rest. Only two parameters allowed you see. Notice the variable substitution order? It is zero based (just like the array).
gs.log is unique in that it allows us to pass the source (location) in as a parameter. So we can migrate it from our gs.getMessage, and pass it to the log call.
var messageSansLoc = gs.getMessage('---> GETMESSAGE: \n\tNumber: {0} \n\tCaller: {1}', [number, caller]);
gs.log(messageSansLoc, location); // location as source
Here is the result. Notice where the location ends up?
BS:Logging Testing: --->; GETMESSAGE: Number: INC0009009 Caller: David Miller
gs.log is a really now an out-dated bit of ServiceNow functionality and is not Scope safe. In other words: it does not work in a scoped application and will throw an error. It works fine in the Global scope, but nowhere else. So, we have been given a new set of functions to replace it in Scoped, and Global applications (the idea, as I understand it, is to refrain from using gs.log moving forward). These new functions are: gs.info, gs.warn, and gs.error. These three functions have built-in variable substitution, but with limitations and quirks.
With all three you have "raw" variable substitution up to five values. After which you have to move to an array like in gs.getMessage. And like with getMessage, if you go beyond the maximum number the remainder will be ignored.
Here is an example using up to five values; which works fine.
// values listed - maximum number before array
gs.info('--->[{4}] MAX B4 ARRAY: \n\tNumber:\t\t{0} \n\tCaller:\t\t{1} \n\tCategory:\t{2} \n\tImpact:\t\t{3}',
number, caller, category, impact, location);
My results:
*** Script: --->[BS:Logging Testing] MAX B4 ARRAY: Number: INC0009009 Caller: David Miller Category: Inquiry / Help Impact: 3
If you move to six values you will notice that the last is ignored and the variable substitution fails for the last value.
// values listed - no-array demonstration (>5)
gs.info('--->[{5}] MAX EXCEEDED: \n\tNumber:\t\t{0} \n\tCaller:\t\t{1} \n\tCategory:\t{2} \n\tImpact:\t\t{3}\n\tPriority:\t{4}',
number, caller, category, impact, priority, location);
My results:
*** Script: --->[{5}] MAX EXCEEDED: Number: INC0009009 Caller: David Miller Category: Inquiry / Help Impact: 3 Priority: 4
If you then go with the array brackets, and rerun - it will work fine; just like with gs.getMessage.
// values listed - array demonstration (>5)
gs.info('--->[{5}] ARRAY: \n\tNumber:\t\t{0} \n\tCaller:\t\t{1} \n\tCategory:\t{2} \n\tImpact:\t\t{3}\n\tPriority:\t{4}',
[number, caller, category, impact, priority, location]);
My results:
*** Script: --->[BS:Logging Testing] ARRAY: Number: INC0009009 Caller: David Miller Category: Inquiry / Help Impact: 3 Priority: 4
So, I decided to see if it would handle something strange. Namely, using an array in the last parameter slot. This did not work. It failed to recognize the extra variables and break them out. Instead, the array was ignored altogether. Therefore, all variables must be inside the array. Notice how it choked on the array? You can see this in what was placed in the Priority value.
// values listed - weird array demonstration (>6)
gs.info('--->[{6}] WEIRD ARRAY: \n\tNumber:\t\t{0} \n\tCaller:\t\t{1} \n\tCategory:\t{2} \n\tImpact:\t\t{3}\n\tPriority:\t{4}\n\tUrgency:\t{5}',
number, caller, category, impact, [priority, urgency, location]);
My results:
*** Script: --->[{6}] WEIRD ARRAY: Number: INC0009009 Caller: David Miller Category: Inquiry / Help Impact: 3 Priority: org.mozilla.javascript.NativeArray@13d48f3 Urgency: {5}
Here is an example of using the gs.warn with an array. Really it is pretty much the same as the gs.info except that instead of a level of Info in the System Log you get a Warning.
// values listed - warning - array demonstration (>6)
gs.warn('--->[{6}] WARNING: \n\tNumber:\t\t{0} \n\tCaller:\t\t{1} \n\tCategory:\t{2} \n\tImpact:\t\t{3}\n\tPriority:\t{4}\n\tUrgency:\t{5}',
[number, caller, category, impact, priority, urgency, location]);
My results:
*** Script: --->[BS:Logging Testing] WARNING: Number: INC0009009 Caller: David Miller Category: Inquiry / Help Impact: 3 Priority: 4 Urgency: 2
And the same with the gs.error. No surprises.
// values listed - error - array demonstration (>6)
gs.error('--->[{6}] ERROR: \n\tNumber:\t\t{0} \n\tCaller:\t\t{1} \n\tCategory:\t{2} \n\tImpact:\t\t{3}\n\tPriority:\t{4}\n\tUrgency:\t{5}\n',
[number, caller, category, impact, priority, urgency, location]);
My results:
*** Script: --->[BS:Logging Testing] ERROR: Number: INC0009009 Caller: David Miller Category: Inquiry / Help Impact: 3 Priority: 4 Urgency: 2
The nice thing about variables substitution is that you can repeat the same variable without having to do much of anything special.
// repeating value substitution
gs.warn('--->[{1}] REPEAT: {0}, {0}, {0} Will Robinson!', spuriousText, location);
My results:
*** Script: --->[BS:Logging Testing] REPEAT: Danger, Danger, Danger Will Robinson!
Variable replacement also allows for mixing the order up with ease.
// rearranged substitution order
gs.info('--->[{5}] REARRANGE: \n\tNumber:\t\t{0} \n\tImpact:\t\t{3} \n\tPriority:\t{4} \n\tCategory:\t{2} \n\tCaller:\t\t{1} ',
[number, caller, category, impact, priority, location]);
My results:
*** Script: --->[BS:Logging Testing] REARRANGE: Number: INC0009009 Impact: 3 Priority: 4 Category: Inquiry / Help Caller: David Miller
Now, let me introduce you to a bit of the real power available with variable substitution. This works fine btw with gs.getMessage as well.
We can turn the variable substitution string into a pattern variable and pull it out of the logging statement for easier maintenance. We can also do the same with the array.
// pattern and array variable demonstration
var pattern = '--->[{5}] PATTERN: \n\tNumber:\t\t{0} \n\tCaller:\t\t{1} \n\tCategory:\t{2} \n\tImpact:\t\t{3}\n\tPriority:\t{4}';
var values = [number, caller, category, impact, priority, location];
gs.info(pattern, values);
My results:
*** Script: --->[BS:Logging Testing] PATTERN: Number: INC0009009 Caller: David Miller Category: Inquiry / Help Impact: 3 Priority: 4
Pretty cool, huh? So, let's take that to the next level! We can dynamically create the array, AND the pattern to adjust for the creation of a different message depending on changing situations in the code. Imagine the various array pushes actually being inside condition statements and you will get the idea.
// dynamic pattern and array population example
var dynamicValues = [];
dynamicValues.push(location);
dynamicValues.push(number);
dynamicValues.push(caller);
dynamicValues.push(category);
dynamicValues.push(impact);
dynamicValues.push(priority);
var max = dynamicValues.length - 1;
pattern = '--->[{' + (max) + '}] DYNAMIC: ';
for (var i=max-1; i > -1; i--) {
pattern += '{' + i + '},';
}
pattern = pattern.slice(0, -1); // get rid of last comma
gs.print(pattern);
gs.info(pattern, values);
My results:
*** Script: --->[{5}] DYNAMIC: {4},{3},{2},{1},{0}
*** Script: --->[BS:Logging Testing] DYNAMIC: 4,3,Inquiry / Help,David Miller,INC0009009
So, there you have it! You now are in possession of examples on how to use various types of server-side debugging and logging available with GlideSystem, and variable substitution tricks-and-tips.
I want to highly recommend taking the ServiceNow Scripting training class should you get the opportunity.
Enjoy!
Steven Bell.
If you find this article helps you, don't forget to log in and mark it as "Helpful"!
Originally published on: 07-06-2016 06:41 AM
I updated the code and brought the article into alignment with my new formatting standard.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.