ServiceNow Random Incident Sampling

A Python script to randomize 30 incidents from ServiceNow's incident database from the past 7 days.

This guide outlines the process of configuring a Python script to generate a selection of 30 randomized incidents from within the last week.

The goal of the sampling is to review incidents in a truly random pattern for their accuracy, process following and outcome analysis. This approach ensures that the review process is unbiased and covers a wide range of incidents, helping identify systemic issues and areas for improvement.

By implementing a random sampling method, we can mitigate the risk of any conscious or unconscious bias in incident selection. This unbiased approach fosters a more comprehensive understanding of our processes and outcomes, ultimately enhancing the efficacy of our incident management system. By reviewing incidents across various categories and severity levels, we can pinpoint recurring issues and trends that may require targeted interventions or policy adjustments.

Requirements

The following is required for this project:

  • ServiceNow API access: You will need access to ServiceNow's API to access the incident database and extract the sample.
  • Excel or alternatives: The output generates a CSV that will be automatically opened with Excel, though another FOSS alternative can be used with a CSV association.
  • Python

Script

  • Replace values in curly brackets {} with actual values:
import requests
import random
from datetime import datetime, timedelta
import csv
import os

instance_url = 'https://{instance}.service-now.com'
api_endpoint = '/api/now/table/incident'
user = '{[email protected]}'
pwd = '{password}'
today_date = datetime.now().strftime('%Y-%m-%d')

date_7_days_ago = (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d %H:%M:%S')

params = {
    'sysparm_fields': 'number,opened_at,short_description,category,assignment_group',
    'sysparm_query': f'assignment_groupSTARTSWITH{ASSIGNMENT GROUP PREFIX} ^stateIN1,2,6^ORstate=1^sys_updated_on>={date_7_days_ago}',
    'sysparm_display_value': 'true',
    'sysparm_limit': 200
}

response = requests.get(f'{instance_url}{api_endpoint}', auth=(user, pwd), params=params)

response.raise_for_status()

tickets = response.json().get('result', [])
filtered_tickets = [
    {
        'Todays Date': today_date,
        'Incident Opened On': ticket['opened_at'],
        'Incident Number': ticket['number'],
        'Incident Short Description': ticket['short_description'],
        'Incident Category': ticket['category'] if isinstance(ticket['category'], str) else ticket['category'].get('display_value', 'N/A'),
        'Assignment Group': ticket.get('assignment_group', {}).get('display_value', 'N/A')
    }
    for ticket in tickets if 'assignment_group' in ticket and isinstance(ticket['assignment_group'], dict) and ticket['assignment_group'].get('display_value', '').startswith('{ASSIGNMENT GROUP PREFIX}')
    and ticket['category'] != '{EXCLUDED CATEGORY}'  # exclude incidents within a specific category where review is not required
]

random_tickets = random.sample(filtered_tickets, min(len(filtered_tickets), 30))

csv_file = 'sample.csv'
csv_columns = ['Todays Date', 'Opened On', 'Number', 'Short Description', 'Category', 'Assignment Group']

try:
    with open(csv_file, 'w', newline='') as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=csv_columns)
        writer.writeheader()
        for data in random_tickets:
            writer.writerow(data)
    print(f"Data has been exported to {csv_file}")
    os.startfile(csv_file)
except IOError:
    print("I/O error during CSV export")