Get an incident audit log using GlideRecord API Scripting

Sujit Karn
Tera Contributor

An incident audit log

function resolveReference(table, sysId) {
    if (!sysId) return "";
    var gr = new GlideRecord(table);
    if (gr.get(sysId)) {
        return gr.getDisplayValue(); // returns the display value of the record
    }
    return sysId; // fallback if not found
}

function resolveChoice(tableName, fieldName, rawVal) {
    if (!rawVal && rawVal !== 0) return "";

    // 1) Try on the given table (incident)
    var label = _getChoiceLabel(tableName, fieldName, rawVal);
    if (label) return label;

    // 2) Fall back to task for inherited fields
    label = _getChoiceLabel('task', fieldName, rawVal);
    return label || (rawVal + ""); // fallback to raw value if not found
}

function _getChoiceLabel(name, element, value) {
    var ch = new GlideRecord('sys_choice');
    ch.addQuery('name', name);
    ch.addQuery('element', element);
    ch.addQuery('value', value + "");           // ensure string compare
    ch.addQuery('inactive', false);             // avoid inactive choices
    // Optional: match current language; omit to use instance default
    // ch.addQuery('language', gs.getSession().getLanguage());
    ch.setLimit(1);
    ch.query();
    if (ch.next()) return ch.getValue('label');
    return "";
}

function formatDuration(seconds) {
    if (!seconds) return "";
    var total = parseInt(seconds, 10);
    var hrs = Math.floor(total / 3600);
    var mins = Math.floor((total % 3600) / 60);
    var secs = total % 60;
    return (hrs.toString().padStart(2, '0') + ":" +
            mins.toString().padStart(2, '0') + ":" +
            secs.toString().padStart(2, '0'));
}

//resolve a null value like an object error.
function safeStr(val) {
    return (val ? val.toString() : "");
}

var incGR = new GlideRecord('incident');
if (incGR.get('INC0010194')) {
	gs.info("=== Unified Timeline for Incident: " + incGR.getValue('number') + " ===\n");
	var timeline = [];

	// --- Audit log entries ---
    var auditGR = new GlideRecord('sys_audit');
    auditGR.addQuery('documentkey', incGR.getUniqueValue());
    auditGR.orderBy('sys_created_on');
    auditGR.query();

    while (auditGR.next()) {
        var fieldName = auditGR.getValue('fieldname');
        var oldVal    = auditGR.getValue('oldvalue');
        var newVal    = auditGR.getValue('newvalue');
        var user      = auditGR.getDisplayValue('user');
        var timestamp = auditGR.getDisplayValue('sys_created_on');

		// Map incident fields to their reference tables
		var refMap = {
			"assignment_group": "sys_user_group",
			"caller_id": "sys_user",
			"assigned_to": "sys_user",
			"resolved_by": "sys_user",
			"location": "cmn_location",
			"company": "core_company",
			"cmdb_ci": "cmdb_ci", 
			"business_service": "cmdb_ci_service",
			"service_offering": "service_offering"
		};
		// Map choice fields to be resolved via sys_choice
		var choiceFields = ["state", "incident_state", "priority", "impact", "urgency", "category", "subcategory"];

		var displayOld = oldVal;
		var displayNew = newVal;

		if (refMap[fieldName]) {
			displayOld = resolveReference(refMap[fieldName], oldVal);
			displayNew = resolveReference(refMap[fieldName], newVal);
		}else if (choiceFields.indexOf(fieldName) > -1) {
			displayOld = resolveChoice('incident', fieldName, oldVal);
			displayNew = resolveChoice('incident', fieldName, newVal);
		}
		timeline.push({
            type: "Audit",
            field: safeStr(fieldName),
            oldVal: safeStr(displayOld),
            newVal: safeStr(displayNew),
            user: safeStr(auditGR.getDisplayValue('user')),
            time: safeStr(auditGR.getDisplayValue('sys_created_on'))
        });
	}
		// --- Journal entries ---
		var journalGR = new GlideRecord('sys_journal_field');
		journalGR.addQuery('element_id', incGR.getUniqueValue());
		journalGR.addQuery('element', 'IN', 'work_notes,comments_and_work_notes');
		journalGR.query();
		while (journalGR.next()) {
			timeline.push({
            type: "Journal",
            field: safeStr(journalGR.getDisplayValue('element')),
            oldVal: "",
            newVal: safeStr(journalGR.getValue('value')),
            user: safeStr(journalGR.getDisplayValue('sys_created_by')),
            time: safeStr(journalGR.getDisplayValue('sys_created_on'))
        });
    }
    
		// --- Sort by timestamp ---
    timeline.sort(function(a, b) {
        return new GlideDateTime(a.time).getNumericValue() - new GlideDateTime(b.time).getNumericValue();
    });

    // --- Calculate max widths ---
    var widths = {type:4, field:5, oldVal:8, newVal:8, user:4, time:9};
    timeline.forEach(function(e) {
        widths.type   = Math.max(widths.type, e.type.length);
        widths.field  = Math.max(widths.field, e.field.length);
        widths.oldVal = Math.max(widths.oldVal, e.oldVal.length);
        widths.newVal = Math.max(widths.newVal, e.newVal.length);
        widths.user   = Math.max(widths.user, e.user.length);
        widths.time   = Math.max(widths.time, e.time.length);
    });

    // --- Print header ---
    gs.info(
        safeStr("Type").padEnd(widths.type) + " | " +
        safeStr("Field").padEnd(widths.field) + " | " +
        safeStr("Old Value").padEnd(widths.oldVal) + " | " +
        safeStr("New Value").padEnd(widths.newVal) + " | " +
        safeStr("User").padEnd(widths.user) + " | " +
        safeStr("Timestamp").padEnd(widths.time)
    );
    gs.info("-".repeat(widths.type + widths.field + widths.oldVal + widths.newVal + widths.user + widths.time + 15));

    // --- Print rows ---
    timeline.forEach(function(e) {
        gs.info(
            safeStr(e.type).padEnd(widths.type) + " | " +
            safeStr(e.field).padEnd(widths.field) + " | " +
            safeStr(e.oldVal).padEnd(widths.oldVal) + " | " +
            safeStr(e.newVal).padEnd(widths.newVal) + " | " +
            safeStr(e.user).padEnd(widths.user) + " | " +
            safeStr(e.time).padEnd(widths.time)
        );
    });

	// Print SLA timings
    gs.info("\n=== SLA Timings format (HH:MM:SS) ===");
    gs.info("Business Resolve Time: " + formatDuration(incGR.getValue('business_stc')));
    gs.info("Calendar Resolve Time: " + formatDuration(incGR.getValue('calendar_stc')));

}
2 REPLIES 2

lpruit2
Kilo Sage

Greetings @Sujit Karn . Did you have a particular question about your script that we could help with? 

Sujit Karn
Tera Contributor

It is a complete answer of question. Run this script in background script and just pass an incident number to see all audited fields in single view.