
- 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.
Have you ever wanted to be able to send errors to the System Log from a Client Script? a UI Action? a UI Policy? Well, in this mini-lab article I will show you a method for doing so.
I had been wanting gs.log/gs.info on the Client (i.e. Browser) for some time when one day it occurred to me that I could write a simple reusable UI Script / Ajax Script Include combo that would give me that capability.
I will be using techniques that I described in my previous two articles:
Pragmatic Patterns: Ajax - Architecting Your Code
Mini-Lab: Using Ajax and JSON to Send Objects to the Server
Requirements
- Ability to write to the system log from a Client Script, UI Action, or UI Policy script.
- Must be re-usable from any of those mechanisms (i.e. emulate gs.log/gs.info on the server side)
Design
- Create an Ajax Script Include with a function that will take a "message" string and write it to the System Log using gs.log, gs.info, gs.debug, gs.error, or gs.warn.
- The gs.log part will be straight forward, we simply do something like log(string, location) and translate that on the server side to gs.log(string, location).
- The gs.info et. al. part is a bit trickier. Here we will have to be a bit innovative. Something like logextended(string, [array of values], type) may need to be done.
- Create a UI Script with a function that will take a string and communicate it via Ajax to an Ajax Script Include.
- Make this a Function Library that will be callable similar to gs.
- Write an example onLoad Client Script that will call the UI Script function. This will be used in testing.
NOTE: In examining the design I determined that a Script Include Function Library would be overkill as the number of code lines needed to write to the System Log would be too few to warrant extraction.
Lab 1.1: Writing Log Entries Into The System Log From the Browser
Development
We will start with a bottom up development approach.
Ajax Script Include (Design Element #1)
1. Navigate to System Definition -> Script Includes. This will display the Script Includes list view.
2. Click on the New button. This will display a blank Script Include form.
3. Fill in the form with the following:
- Name: SystemLoggerAjax
- Client Callable: Checked (this will cause the Ajax template to be added to the Script field).
- Accessible from: All application scopes
- Active: checked
- Description: System Logging functions
- Script:
var SystemLoggerAjax = Class.create();
SystemLoggerAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
// simple logging function
systemLog: function() {
var message = this.getParameter('sysparm_message');
var loggingSource = this.getParameter('sysparm_logging_source');
gs.info(message, loggingSource);
},
// complex logging function
systemLogExtended: function() {
var message = this.getParameter('sysparm_message');
// convert the JSON object back to our array
var messageArgs = JSON.parse(this.getParameter('sysparm_args'));
// type of log message to be executed
var messageType = this.getParameter('sysparm_type').toLowerCase();
switch (true) {
case messageType == 'info':
gs.info(message, messageArgs);
break;
case messageType == 'debug':
gs.debug(message, messageArgs);
break;
case messageType == 'warn':
gs.warn(message, messageArgs);
break;
case messageType == 'error':
gs.error(message, messageArgs);
break;
}
},
type: 'SystemLoggerAjax'
});
Your AJAX Script Include should look like this:
UI Script (Design Element #2)
1. Navigate to System UI -> UI Scripts. This will display the UI Scripts list view.
2. Click on the New button. This will display a blank UI Script form.
3. Fill in the form with the following:
- Name: LoggingUtils
- Global: Checked
- Active: Checked
- Description: System Logging Functions
- Script:
var log = Class.create();
// Simple logging function
log.log = function(message, loggingSource) {
loggingSource = '[BROWSER] ' + loggingSource; // spiff up the source a bit
var systemLogger = new GlideAjax('SystemLoggerAjax');
systemLogger.addParam('sysparm_name','systemLog');
systemLogger.addParam('sysparm_message', message);
systemLogger.addParam('sysparm_logging_source', loggingSource);
systemLogger.getXML(function(result){ }); // no callback action
};
// Complex logging functions - can probably be refactored
log.info = function(message) {
_syslogExt(message, _toArray(arguments), 'info');
};
log.warn = function(message) {
_syslogExt(message, _toArray(arguments), 'warn');
};
log.debug = function(message) {
_syslogExt(message, _toArray(arguments), 'debug');
};
log.error = function(message) {
_syslogExt(message, _toArray(arguments), 'error');
};
// Transmit complex logging task to server side
function _syslogExt(message, messageArgs, messageType) {
message = '[BROWSER] ' + message; // spiff up the message
var systemLogger = new GlideAjax('SystemLoggerAjax');
systemLogger.addParam('sysparm_name','systemLogExtended');
systemLogger.addParam('sysparm_message', message);
// method for transmitting complex objects to the server
systemLogger.addParam('sysparm_args', JSON.stringify(messageArgs));
systemLogger.addParam('sysparm_type', messageType);
systemLogger.getXML(function(result){ }); // no callback action
}
// Simple function to convert "argument" arrays into a true array for manipulation
function _toArray(source) {
var target = [];
// shave off the first argument - this is our message line
for (var i=1; i < source.length; i++) {
target.push(source[i] + '');
}
return target;
}
Your UI Script should look like this:
Client Script (Design Element #3)
1. Navigate to System Definition -> Client Scripts. This will display the Client Script List View.
2. Click on the New button. This will display a blank Client Script form.
3. Fill in the form with the following:
- Name: syslog Example
- Table: Incident
- UI Type: Desktop
- Type: onLoad
- Active: checked
- Inherited: unchecked
- Global: checked
- Description: System Logger Example
- Script:
function onLoad() {
var incidentNumber = g_form.getValue('number');
var userName = g_user.userName;
// Test the simple logging function
log.log('---> The form has finished loading and is ready for user input. Incident: ' + incidentNumber,
'CS:syslog example');
// Test the complex logging function
log.info('---> Test {0}: form has finished. userID = {1}, incident = {2}', '1', userName, incidentNumber);
log.error('---> Test {0}: form has finished. userID = {1}, incident = {2}', '2', userName, incidentNumber);
}
Your Client Script should look like this:
Unit Testing
1. Navigate to Incident -> Open. The Open Incident list view will be displayed.
2. Choose an open Incident (click on the incident number to open the form).
3. Navigate to System Logs -> System Log -> All. The System Log will be displayed.
4. Order by Created Date descending.
5. Filter the Message column with: *--->
6. Note the three new entries. Your results should look something like this:
And there you have it! A way to write entries to the System Log from the Client (browser) side!
Best practices demonstrated:
- Maintainability.
- Extensibility.
- Coding Best Practice: Another method of logging unit test results.
NOTE: If you are working with this example in your PDI and run into issues with the system not working right: There is a problem with the Client Scripts being editable, or your client script runs into an issue in Global. I found that flipping the glide.script.block.client.globals to false and then doing a cache.do seems to clear it all up...after a couple of tries. This seem to fix the problem with the OOB client scripts "Validate Client Script w/o Server Obj" and "Validate Client Script Func Declaration" as well. I had to initially deactivate both just to work on my Client Script. Really weird/odd behavior that I wasn't able to replicate on a real DEV instance. Check out this post if you want to know more as it was illuminating: Isolate Script in London (thanks to Alikutty A for digging this stuff out).
Enjoy!
Steven Bell.
If you find this article helps you, don't forget to log in and mark it as "Helpful"!
Originally published on: 01-28-2016 09:57 AM
I updated the code and brought the article into alignment with my new formatting standard.
- 2,416 Views
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.