Advanced ServiceNow Configuration - Post Processing
Post Processing is a feature of Creation Rules that allows for incredible flexibility when creating Incidents or Tasks. If the criteria-driven Creation Rules are not enough for your use case, Connection Center can do almost anything to a newly created Task or Incident using Post Processing and JavaScript.
Enabling Post Processing for a Creation Rule
To use Post Processing select the Post Processing checkbox. When checked, you will be provided with a script field where you can flesh out your more complex use cases.
Post Processing includes an example script baked into the product to give you an idea of what it is capable of and how to use the feature.
Variables and Their Use
Post Processing provides you with two variables, scomAlertRecord, and createTask. These provide you with the current alert being processed and the basic new task record created by the Creation Rule respectively. The new task record contains all the details set previously in the Creation Rule UI to allow you to jump straight into customization for your use case. Either of these objects can be updated in the script so you can add to the alert history or change the linked incident (as in the re-opening example below).
This does also mean that you can update or overwrite other alert properties which can be detrimental
To abort the creation of a new Task / Incident entirely, set the createTask cancelCreation property to true as shown in the Re-opening example later.
Variable Properties
These are the default values available on each variable. Customization in ServiceNow may mean that there are more or fewer properties than listed here. By default, if you attempt to assign a value to a property that does not exist the value passed will be dropped.
scomAlertRecord Properties
Property | Equivalent SCOM Alert Property | Additional notes |
---|---|---|
alertid | Id | |
alert_activity | N/A | Any alert history events. An example exists under the Reopening an Incident example below. |
category | Category | |
context | Context | |
customfield1 | CustomField1 | Dependent on BiDirectional Sync and/or Advanced Updates |
customfield10 | CustomField10 | |
customfield2 | CustomField2 | Dependent on BiDirectional Sync and/or Advanced Updates |
customfield3 | CustomField3 | Dependent on BiDirectional Sync and/or Advanced Updates |
customfield4 | CustomField4 | Dependent on BiDirectional Sync and/or Advanced Updates |
customfield5 | CustomField5 | Dependent on BiDirectional Sync and/or Advanced Updates |
customfield6 | CustomField6 | |
customfield7 | CustomField7 | |
customfield8 | CustomField8 | |
customfield9 | CustomField9 | |
description | Description | |
hasscomupdate | N/A | Indicates to AlertSync that there is an update to sync back to SCOM |
incident | TicketId | Dependent on BiDirectional Sync and/or Advanced Updates |
incident_creation_rule | N/A | This is the Creation rule that the alert has matched against. |
ismonitoralert | IsMonitorAlert | |
lastmodified | LastModified | |
managementgroup | ManagementGroup | |
managementpackdisplayname | N/A | Drawn from underlying workflow |
managementpackname | N/A | Drawn from underlying workflow |
monitoringobjectdisplayname | MonitoringObjectDisplayName | |
monitoringobjectfullname | MonitoringObjectFullName | |
monitoringobjectid | MonitoringObjectId | |
monitoringobjectinmaintenancemode | MonitoringObjectInMaintenanceMode | Not so useful on rule based alerts as going into maintenance mode usually closes the alert |
monitoringobjectname | MonitoringObjectName | |
monitoringobjectparentids | N/A | Drawn from underlying object |
monitoringobjectpath | MonitoringObjectPath | |
name | Name | |
netbioscomputername | NetbiosComputerName | |
owner | Owner | Dependent on BiDirectional Sync and/or Advanced Updates |
parameters | Parameters | |
principalname | PrincipalName | |
priority | Priority | |
repeatcount | RepeatCount | |
resolutionstate | ResolutionState | |
resolutionstatename | N/A | |
severity | Severity | |
sitename | SiteName | |
sys_created_by | N/A | ServiceNow property detailing what account created the record (your service account) |
sys_created_on | N/A | ServiceNow property detailing when the record was created (not to be confused with timeraised) |
sys_id | N/A | ServiceNow unique record ID (a guid without the dashes) |
sys_mod_count | N/A | ServiceNow property for modification count |
sys_tags | N/A | |
sys_updated_by | N/A | ServiceNow property showing who last updated the record |
sys_updated_on | N/A | ServiceNow property showing when the record was last updated |
timeraised | TimeRaised | The time/datestamp related to the alert being raised in SCOM |
timeresolved | TimeResolved | |
wait_completed | N/A | Used by AlertSync to indicate if the alert went through a wait rule successfully |
workflowdisplayname | N/A | Drawn from underlying workflow |
workflowname | N/A | Drawn from underlying workflow |
createTask Properties
Property | UI label | Additional notes |
---|---|---|
active | Active | |
activity_due | Activity due | |
additional_assignee_list | Assitional assignee list | |
approval | Approval | |
approval_history | Approval history | Journal type |
approval_set | Approval set | |
assigned_to | Assigned to | Reference to User (sys_user) table |
assignment_group | Assignment group | Reference to Group (sys_user_group) table |
business_duration | Business duration | |
business_service | Service | Reference to Service (cmdb_ci_service) table |
calendar_duration | Duration | |
cancelCreation | N/A | Added temporarily and utilized only by creation rules. |
closed_at | Closed | |
closed_by | Closed by | Reference to User (sys_user) table |
close_notes | Close notes | |
cmdb_ci | Configuration item | Reference to Configuration Item (cmdb_ci) table |
comments | Additional comments | Journal Input type |
comments_and_work_notes | Comments and Work Notes | Journal List type (you probably want either the comments or work_notes properties) |
company | Company | Reference to Company (core_company) table |
contact_type | Contact type | |
contract | Contract | Reference to Contract (ast_contract) table |
correlation_display | Correlation display | |
correlation_id | Correlation ID | |
delivery_plan | Delivery plan | Reference to Execution Plan (sc_cat_item_delivery_plan) table |
delivery_task | Delivery task | Reference to Execution Plan Task (sc_cat_item_delivery_task) table |
description | Description | |
due_date | Due date | |
escalation | Escalation | |
expected_start | Expected start | |
follow_up | Follow up | |
group_list | Group list | List type referencing Group (sys_user_group) table |
impact | Impact | |
knowledge | Knowledge | |
location | Location | Reference to Location (cmn_location) table |
made_sla | Made SLA | |
number | Number | The user friendly task/incident number |
opened_at | Opened | |
opened_by | Opened by | Reference to User (sys_user) table |
order | Order | |
parent | Parent | Reference to Task (task) table |
priortity | Priority | Function of impact and urgency see default example |
reassignment_count | Reassignment count | |
rejection_goto | Rejection goto | Reference to Task (task) table |
route_reason | Route reason | |
service_offering | Service offereing | Reference to Service Offering (service_offering) table |
short_description | Short description | |
sla_due | SLA due | |
state | State | |
sys_class_name | Task type | System Class Name type |
sys_created_by | Created by | |
sys_created_on | Created | |
sys_domain | Domain | Domain ID type - Used with domain separation |
sys_domain_path | Domain Path | Domain Path type - Used with domain separation |
sys_id | Sys ID | Table key |
sys_mod_count | Updates | |
sys_tags | N/A | |
sys_updated_by | Updated by | |
sys_updated_on | Updated | |
task_effective_number | Effective number | |
time_worked | Time worked | |
universal_request | Universal Request | Reference to Task (task) table |
upon_approval | Upon approval | |
upon_reject | Upon reject | |
urgency | Urgenency | |
user_input | User input | |
watch_list | Watch list | List type referencing User (sys_user) table |
wf_activity | Workflow activity | Reference to Workflow Activity (wf_activity) table |
work_end | Actual end | |
work_notes | Work notes | Journal Input type |
work_notes_list | Work notes list | List type referencing User (sys_user) table |
work_start | Actual start |
Example Script (Default)
This script is the one shown initially when enabling Post Processing. It updates a Tasks description based on multiple alert fields and then sets its Impact and Urgency based on the alerts' Severity and Priority. This therefore also sets the Tasks priority as this is based on a Tasks Impact and Urgency.
(function postprocessing(scomAlertRecord, createdTask) { // Use the below code to further update your incident or task and customize the record created. // scomAlertRecord = the inbound SCOM alert from your Management Group, as detailed in the SCOM Alerts table // createdTask = the Incident or Task created from the first tab of your creation rule // createdTask.cancelCreation = a boolean indicating whether this task creation should be canceled // Update the description to be the alert name and the server name createdTask.description = scomAlertRecord.name + 'on server ' + scomAlertRecord.principalname; // Programatically setting Impact and Urgency var scomPriority = scomAlertRecord.getValue('priority'); var scomSeverity = scomAlertRecord.getValue('severity'); if (scomSeverity == 'Error') { if (scomPriority == 'High') { createdTask.impact = 1; createdTask.urgency = 2; } else { createdTask.impact = 2; createdTask.urgency = 2; } } else if (scomSeverity == 'Warning') { if (scomPriority == 'High') { createdTask.impact = 2; createdTask.urgency = 2; } else { createdTask.impact = 2; createdTask.urgency = 3; } } else if (scomSeverity == 'Information') { createdTask.impact = 3; createdTask.urgency = 3; } })(scomAlertRecord, createdTask);
Example Script (Re-open existing task/incident)
This script demonstrates how to re-open a previously resolved Task/Incident that matches our alert and then abort the creation of a new one. It updates a Tasks short description to make it more specific and then searches for resolved tasks that match. If it finds them it puts them to an 'In Progress' state and then links them to our alert and aborts the creation of a new record for the alert.
(function postprocessing(scomAlertRecord, createdTask) { // Use the below code to further update your incident or task and customize the record created. // scomAlertRecord = the inbound SCOM alert from your Management Group, as detailed in the SCOM Alerts table // createdTask = the Incident or Task created from the first tab of your creation rule // createdTask.cancelCreation = a boolean indicating whether this task creation should be canceled // --------------------------------------------- // Re-opening existing task/incident example script // --------------------------------------------- //Figure out what table we are using for this creation rule var Table = createdTask.getTableName(); // Create a GlideRecord object which we'll use for searches var gr = new GlideRecord(Table); // ------------------------------------------------------------------ // Configure the incident values, combinding some SCOM properties // ------------------------------------------------------------------ // We will append the object name to the short description for user convinence createdTask.short_description = scomAlertRecord.name + ' - ' + scomAlertRecord.monitoringobjectfullname; // Short description must match and state must be 6 (Resolved) gr.addQuery('short_description', createdTask.short_description); gr.addQuery('state', 6); // Execute the query and proceed to check for results gr.query(); // ------------------------------------------------------------------ // Create or update a task based on the search results // ------------------------------------------------------------------ if (gr.next()) { // Existing record found, change the status to In Progress gr.state = 2; gr.work_notes = 'Re-opened from SCOM Alert'; gr.update('Re-opened from SCOM Alert'); // Store the existing record to our SCOM record scomAlertRecord.incident = gr.sys_id; // Add note to alert history tab to indicate what happened there as well scomAlertRecord.alert_activity = 'Found existing ' + Table + ' ' + gr.number; // Cancel the creation of new task as we have found an existing one that matches createdTask.cancelCreation = true; } else { // No matching incidents, continue with creation } })(scomAlertRecord, createdTask);
Example Script (Link to webpage/dashboard)
This script demonstrates how to add work notes with links in them to a third-party source. The link is built up using properties pushed up with the alert, so as long as the target is based around something pushed in the alert record you can build this up as you see fit. Examples might be linking to the SCOM web console or a third-party SCOM dashboard should that be desirable (perhaps to quickly get at performance data). Similarly, you could use this to link off to something like SharePoint, Confluence, or an internal Wiki if there would be further context there. Finally, if this is coming from something like an Azure, AWS, something that knows about IPMI, etc. you could potentially link directly to their portal using the monitoring object name or details in the alert context.
(function postprocessing(scomAlertRecord, createdTask) { // Use the below code to further update your incident or task and customize the record created. // scomAlertRecord = the inbound SCOM alert from your Management Group, as detailed in the SCOM Alerts table // createdTask = the Incident or Task created from the first tab of your creation rule // createdTask.cancelCreation = a boolean indicating whether this task creation should be canceled // ------------------------------------------------------------------ // Linking to third party dashboarding example script // ------------------------------------------------------------------ // Set a variable to build up the note in var Worknote; // Set our base addresses so we don't have to repeat ourselves var Address = 'https://monitoring.domain.tld/drilldown'; var AzurePortal = 'https://portal.azure.com#@domain.tld/resource'; // Build up a link to the alert dipping into HTML where required // On click open it in a new window Worknote = 'Alert Dashboard: [code]<a href="' + Address + '/scomalert?id=' + scomAlertRecord.alertid.toString() + ' "target="_blank">' + scomAlertRecord.name.toString() + '</a>[/code]' + '\n'; // Build up a link to the object dipping into HTML where required // On click open it in a new window Worknote = Worknote + 'Object Dashboard: [code]<a href="' + Address + '/scomobject?id=' + scomAlertRecord.monitoringobjectid.toString() + ' "target="_blank">' + scomAlertRecord.monitoringobjectdisplayname.toString() + '</a>[/code]' + '\n'; // If this is from the Azure Management pack link directly to the portal // You would probably make checks like this from the Creation Rule filter // However if there is an indicator in the alert context or CI you would probably make that check here instead if (scomAlertRecord.managementpackname == 'Microsoft.SystemCenter.MicrosoftAzure') { Worknote = Worknote + 'Azure Portal: [code]<a href="' + AzurePortal + scomAlertRecord.monitoringobjectname.toString() + ' "target="_blank">' + scomAlertRecord.monitoringobjectdisplayname.toString().split(' ')[0] + '</a>[/code]' + '\n'; } // Assign the details built above to a worknote on the raised task createdTask.work_notes = Worknote; })(scomAlertRecord, createdTask);
Example Script (Raise a problem on repeated alerts)
This script demonstrates one of the options for raising a problem automatically. We look up all instances of the alert on the object in the last 30 days (using a GlideSystem method) that generated a task/incident. If there are 4 or more existing records we need to make sure a problem exists. If there is an existing problem linked to the newest matching record we simply link to that one. If there is no problem on the newest incident we raise a new problem (assuming the required permissions are present) and link this problem to all records that don’t already have a problem.
(function postprocessing(scomAlertRecord, createdTask) { // Use the below code to further update your incident or task and customize the record created. // scomAlertRecord = the inbound SCOM alert from your Management Group, as detailed in the SCOM Alerts table // createdTask = the Incident or Task created from the first tab of your creation rule var grAlert = new GlideRecord("x_oklt_cookdown_sc_scom_alerts"); // Find alerts from the last 30 days grAlert.addQuery('timeraised', '>=' ,gs.beginningOfLast30Days()); // With the same Object ID grAlert.addQuery('monitoringobjectid',scomAlertRecord.monitoringobjectid); // With the same Rule/Monitor grAlert.addQuery('workflowname',scomAlertRecord.workflowname); // Where a task/incident was raised grAlert.addNotNullQuery('incident'); // Put the first record rasied first grAlert.orderByDesc('timeraised'); // Execute Query grAlert.query(); grAlert.next(); // We assume here that if the newest Task/Incident doesn't have a problem that none of them do // You may need additional logic here if this does not fit your scenario if ((grAlert.getRowCount() >= 4) && (grAlert.incident.getRefRecord().problem_id != '')) { // If this is the 5th (or greater) ticket and there is an existing problem //Log the scenario (pulling details from linked records) scomAlertRecord.alert_activity = "Found " + grAlert.getRowCount().toString() + " matching records and an existing problem: " + grAlert.incident.getRefRecord().problem_id.getRefRecord().number; // We have previously raised a problem, link it to the new Incident/Task createdTask.problem_id = grAlert.incident.getRefRecord().problem_id; } else if (grAlert.getRowCount() >= 4) { // If this is the 5th (or greater) ticket and there is no existing problem //Log the scenario scomAlertRecord.alert_activity = "Found " + grAlert.getRowCount().toString() + " matching records and no existing problem"; // Start work against the problem table var grPrb = new GlideRecord("problem"); // Start the new record grPrb.initialize(); // Short description is mandatory // You may wish to populate other fields, the createdTask properties can be a good reference point as they should line up grPrb.short_description = "Problem raised to deal with repeated " + scomAlertRecord.name + " alerts from " + scomAlertRecord.monitoringobjectdisplayname; // Set the first reported task to the incident raised by the first recorded SCOM alert grPrb.first_reported_by_task = grAlert.incident; // Insert the record and link the task createdTask.problem_id = grPrb.insert(); // Log the created problem number scomAlertRecord.alert_activity = "Raised a new problem: " + grPrb.number; do { // Loop through each alert matching alert // Look up the incident var incident = grAlert.incident.getRefRecord(); // If no existing problem, set the corresponding problem // Despite the assumtions earlier we don't want to clobber other problems if they exist if (! incident.problem_id) { // Set the problem incident.problem_id = createdTask.problem_id; // Update the incident incident.update(); } } while (grAlert.next()); } else { // Log the scenario scomAlertRecord.alert_activity = "Found " + grAlert.getRowCount().toString() + " matching records, not raising a problem"; } // Finish and let the creation rule deal with creating the current incident })(scomAlertRecord, createdTask);
Further Reading and Next Steps
Ultimately scripting in our Creation Rules is very customizable and will therefore require testing to make sure that it fits your requirements. If you haven’t looked at them already we would recommend looking at the Testing, Tips, and Tricks for ServiceNow page, as this has a number of handy shortcuts from our testing, support, and engineering teams that should make this a bit easier!
Hopefully, this all goes smoothly, but you may also wish to familiarize yourself with our Troubleshooting ServiceNow page.
You may also wish to look at the official ServiceNow Documentation on scripting or one of our favorite ServiceNow scripting blogs: The ServiceNow Guru