Name

global.MetricsTimeline

Description

Display a timeline view of metric instance durations

Script

// Class Imports
var TimelineItem = GlideTimelineItem;

var ERROR_TITLE = 'Error';
var GANTT_REQUIREMENT = 'This is required for displaying a timeline.';
var ERROR_NO_TASK_ID = 'No "sysparm_task_id" specified in the original Url. ' + GANTT_REQUIREMENT;
var ERROR_NO_GR_TASK = 'Unable to find a matching task record with the specified system id.';
var START_LABEL = gs.getMessage('Start');
var END_LABEL = gs.getMessage('End');
var MESSAGES = [ ERROR_TITLE, ERROR_NO_TASK_ID ];

var MetricsTimeline = Class.create();
MetricsTimeline.prototype = Object.extendsObject(AbstractTimelineSchedulePage, {

  // ////////////////////////////////////////////////////////////////////////////////////////////////
  // GET_ITEMS
  // ////////////////////////////////////////////////////////////////////////////////////////////////

  getItems : function() {
  	// this starts everything
  	this._getParameters();
  	this._getRecord();
  	if(this.record === null)
  		return;
  	this.setPageTitle(sn_i18n.Message.getMessage("global", "{displayValue} Metrics", {
  		displayValue: String(GlideStringUtil.escapeHTML(this.record.getDisplayValue()))
  	}));
  	this._getDefinitions();
  	this._processMetrics();
  },

  _getParameters : function() {
  	this.table = this.getParameter("sysparm_timeline_table");
  	this.table_id = this.getParameter("sysparm_timeline_id");
  },

  _getRecord : function() {
  	var gr = new GlideRecordSecure(this.table);
  	if (!gr.get(this.table_id)) {
  		gs.addErrorMessage(gs.getMessage('User does not have role required to access the specified timeline table.'));
  		return;
  	}
  	this.record = gr;
  },

  _getDefinitions : function() {
  	var def = new GlideRecordSecure("metric_definition");
  	//Check for metric definitions on tables that are parents of this.table as well as the this.table itself
  	var tablesInHierarchy = GlideDBObjectManager.get().getTables(this.table.toString());
  	def.addQuery('table', tablesInHierarchy);
  	def.addQuery("timeline", true);
  	def.addActiveQuery();
  	def.query();
  	this.definitions = def;
  },

  _processMetrics : function() {
  	var def = this.definitions;
  	while (def.next()) {
  		var defItem = new TimelineItem("metric_definition", def.getUniqueValue());
  		defItem.setLeftLabelText(def.getDisplayValue());
  		var valueInstances = {};

  		var dur = new GlideDuration();
  		var totalDuration;
  		var durationAgg = new GlideAggregate("metric_instance");
  		durationAgg.addQuery("definition", def.getUniqueValue());
  		durationAgg.addQuery("table", this.table);
  		durationAgg.addQuery("id", this.table_id);
  		durationAgg.addAggregate("SUM", "duration");
  		durationAgg.groupBy("definition");
  		durationAgg.query();
  		if (durationAgg.next()) {
  			dur.setValue(durationAgg.getAggregate("SUM", "duration"));
  			totalDuration = dur.getNumericValue();

  		}

  		// create value spans
  		var instance = new GlideRecordSecure("metric_instance");
  		instance.addQuery("definition", def.getUniqueValue());
  		instance.addQuery("table", this.table);
  		instance.addQuery("id", this.table_id);
  		instance.orderBy("start");
  		instance.query();
  		var predecessor = null;
  		while (instance.next()) {
  			var value = instance.value;
  			if (value == "")
  				value = gs.getMessage("(empty)");
  			var instanceID = instance.getUniqueValue();
  			gs.print("instanceID: " + instanceID);
  			var instanceItem = valueInstances[value];
  			if (!instanceItem) {
  				instanceItem = new TimelineItem("metric_instance", value);
  				instanceItem.setParent(def.getUniqueValue());
  				instanceItem.setLeftLabelText(value);
  				valueInstances[value] = instanceItem;
  			}
  			//DEF0184798
  			var instanceSpan = instanceItem.createTimelineSpan("metric_instance", instanceID);
  			instanceSpan.setSpanText(value);
  			if (predecessor)
  				instanceSpan.addPredecessor(predecessor);

  			predecessor = instanceID;

  			var start = instance.start.getGlideObject().getNumericValue();
  			var end = instance.end.getGlideObject().getNumericValue();
  			var duration = instance.duration.getGlideObject().getNumericValue();
  			var durationPercent = Math.round(duration / totalDuration * 100);

  			if (start == 0)
  				continue;

  			if (end > 0) {
  				// span start and end
  				instanceSpan.setTimeSpan(start, end);
  				instanceSpan.setTooltip(instance.value + " (" + instance.duration.getDisplayValue() + " - " + durationPercent + "%)");
  			} else {
  				// still open, use point instead of span
  				instanceSpan.setTimeSpan(start, start);
  				instanceSpan.setPointIconClass("green_circle");
  				instanceSpan.setTooltip("current value");
  			}
  		}

  		for ( var i in valueInstances)
  			this.add(valueInstances[i]);

  		this.add(defItem);
  	}
  },

  _noSpanTaskId : function() {
  	return this.setStatusError(gs.getMessage(ERROR_TITLE), gs.getMessage(ERROR_NO_GR_TASK));
  }

});

Sys ID

68be25e2ff111000dadaebcfebffad9a

Offical Documentation

Official Docs: