Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

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')));

}
0 REPLIES 0