The CreatorCon Call for Content is officially open! Get started here.

Report on tickets 'touched' or 'handled' by an Assignment Group

elbow
Giga Contributor

Hi All,

I've read several similar questions and been through the answers. Needless to say I'm left needing to ask my own question.

I want to use the OOTB Reporting module (version=helsinki) to report on all tickets assigned to a group (I'll actually use a Parent group, and pivot the results by each child group), which have specifically been 'touched' or 'handled' by another particular team. Let's call that team "Team Z"

I can confirm that Team Z will actually add a Work Note such as "Assigned to Team A" to every ticket they 'touch' or 'handle'. So not only will they have an entry in the History table, it also appears in Notes. This may assist in your ideas/responses.

So lets say last month there were a total of 200 tickets assigned to, and closed by Team A.

I want to be able to tell how many of them had passed through the Team Z queue prior.

I know there is a reassignment count also, but not sure it's going to help me out in this case. I'm presently fiddling using the 'keyword' function but I've read the Notes table is not indexed so I could potentially create a vortex if I continue. And of course, I've noticed I can't 'layer' keyword criteria in a single query, or use the AND function. (I take it this is a known limitation?)

Any help is appreciated. I should repeat that I need to run this in the gui itself. That said, if the only way the above can be achieved is by direct query then don't hold back!

And if you need me to clarify anything, or add information please let me know.

Thanks in advance,

Scott

1 ACCEPTED SOLUTION

Hey Scott, this should get you what you're looking for.



Create a metric called something like Incident Touched.   Use the following settings:


  • Name: Incident Touched
  • Table: Incident [incident]
  • Field: Assignment group
  • Type: Script calculation
  • Timeline: (leave blank)
  • Active: True (checked)
  • Description: Creates a metric to record that an assignment group touched an incident. Does not create duplicate metrics if an incident is assigned to an assignment group multiple times.
  • Script: See below


Script:


/**


* Creates a metric to record that an assignment group touched an incident.


* Does not create duplicate metrics if an incident is assigned to an


* assignment group multiple times.


*


* Parameters


*   These parameters are passed into all metric definition scripts.


*


*   current


*       The current record that triggered the metric definition


*


*   definition


*       The metric definition being triggered


*


*   mi


*       A MetricInstance object (see the MetricInstance script include for more


*       information and documentation). I'm not a big fan of using the mi object


*       because it doesn't really contain complete functionality or the ability


*       to customize metrics to the extent that a custom script normally


*       demands.


*


* Created by Dennis R


* 2017-08-16: Initial creation


*/


(function calculateMetric(current, definition, mi) {


      // Check to see if a metric instance already exists for this ticket


      // assigned to this assignment group


      var grMetric = new GlideRecord('metric_instance');


      grMetric.addQuery('id', current.getValue('sys_id'));


      grMetric.addQuery('definition', definition.getValue('sys_id'));


      grMetric.addQuery('value', current.getDisplayValue('assignment_group'));


      grMetric.query();




      if (grMetric.hasNext()) {


              // If so, then this ticket has already been counted for this assignment


              // group and there's no need to do anything.


      }


      else {


              // If not, create one


              var now = new GlideDateTime();


              var instant = new GlideDuration(0);


           


              grMetric = new GlideRecord('metric_instance');


              grMetric.initialize();


              grMetric.setValue('table', current.getRecordClassName());


              grMetric.setValue('id', current.getValue('sys_id'));


              grMetric.setValue('definition', definition.getValue('sys_id'));


              grMetric.setValue('field', definition.getValue('field'));


              grMetric.setValue('value', current.getDisplayValue('assignment_group'));


              grMetric.setValue('duration', instant);


              grMetric.setValue('business_duration', instant);


              grMetric.setValue('calculation_complete', true);


              grMetric.setValue('start', now);


              grMetric.setValue('end', now);


              grMetric.insert();


      }


})(current, definition, mi);


(You won't hurt my feelings too much if you leave it unattributed to me; that's just a standard header I put on all my scripts.)



Save the metric definition.   This is a screenshot of what your settings should look like on the definition:


Metric Def.png



Now create the report.   Run it against the Incident Metric [incident_metric] database view.   Make sure you add the following filter conditions:


  • Definition is Incident Touched
  • Value is Team Z (note that because Value is a text field, you'll have to type this in instead of selecting it)


If you don't want tickets that ultimately ended up in Team Z's queue (for example, only tickets that ended up in the queue of Team A, Team B, or etc.), then add a filter for:


  • Assignment group is not Team Z


If you want tickets that ONLY ended up in a queue of Team A, Team B, or etc. (that is, that didn't end up in some outside queue), add a filter such as:


  • Assignment group is Team A OR
    • Assignment Group is Team B OR
    • Assignment Group is Team C OR
    • ...


Personally, I would save this filter as a report source so that if you decide you want to filter it further by other criteria, you don't have to keep adding those filters first.   After that, you can add whatever other filters you want, such as created between, updated after, or whatever.



When that report is run, you will get a list of tickets without duplicates that were touched by Team Z at some point and, if you added the assignment group is not Team Z filter, ended up in some other team's queue.



If you just want a count and not a list of tickets, change your report time from List to Single Score.   (But I'd leave it as list at least initially to validate that you're getting back the records you're looking for.)   And as a side note, the time that the ticket was initially assigned to Team Z will be in the Start field of the Incident Metric view.



Hope this helps, and let me know if you have any trouble,


--Dennis R


View solution in original post

54 REPLIES 54

Bonus time!   Assuming the definition above works, I already know what your next question is going to be, so I went ahead and wrote a script to retroactively populate the metric_instance table with data from existing tickets before the new metric definition was created.   The script is below.   Be aware that it will probably take a while to run if you already have a lot of incidents.   If it gets killed due to its run time, you can safely run it multiple times, since it will detect if a metric instance already exists for a given incident and assignment group combination.



You'll need admin access to the instance for this to work correctly since it hits against the audit table.   It should be run as a background script or, optionally, as a fix script.



Here's the source:



/**


* Retroactively backfill incident metrics for tickets touched by teams


*


* Created by Dennis R


* 2017-08-16: Initial creation


*/


(function() {


      // Set this to the name of your metric definition name


      var metric_definition_name = 'Incident Touched';


     


      /**


        * Everything below this line is business logic


        */


       


      // Find out the metric definition id


      var grMetricDef = new GlideRecord('metric_definition');


      if (!grMetricDef.get('name', metric_definition_name)) {


              gs.log('--->populateMetrics: Cannot find metric definition name ' +


                              metric_definition_name);


              return;


      }


     


      // Iterate over all existing incidents


      var grIncident = new GlideRecord('incident');


      grIncident.query();


      while (grIncident.next()) {


              // Look up changes in assignment group in the audit history.


              // NOTE: ServiceNow usually STRONGLY discourages running queries


              // against the audit table due to its size. It is indexed by


              // documentkey, however, so we are not performing full table scans.


              // This is kosher.


              var grAudit = new GlideRecord('sys_audit');


              grAudit.addQuery('documentkey', grIncident.getValue('sys_id'));


              grAudit.addQuery('fieldname', 'assignment_group');


              grAudit.orderBy('sys_created_on');


              grAudit.query();


             


              var groupMap = { }; // Associative array to avoid unnecessary queries


                                                      // to the database after an assignment to this


                                                      // group has been found


              while (grAudit.next()) {


                     


                      var groupId = grAudit.getValue('newvalue');


                      var groupName = '';


                     


                      // Don't make unnecessary queries to the database if possible.


                      if (groupId in groupMap) {


                              // We've already encountered an assignment to this group, so


                              // we already know there's no need to create a new metric.


                              continue;


                      }


                      else {


                              // Find out the name of the group


                              var grGroup = new GlideRecord('sys_user_group');


                              if (grGroup.get('sys_id', groupId)) {


                                      groupName = grGroup.getValue('name');


                                      groupMap[groupId] = true;


                              }


                              else {


                                      gs.log('--->populateMetrics: Cannot resolve group ' +


                                                      'sys_id ' + groupId + '; group has likely been ' +


                                                      'deleted and metric cannot be stored.');


                                      continue;


                              }


                      }


                     


                      // Check to see if metric for this ticket and assignment group


                      // exists


                      var grMetric = new GlideRecord('metric_instance');


                      grMetric.addQuery('id', grIncident.getValue('sys_id'));


                      grMetric.addQuery('definition', grMetricDef.getValue('sys_id'));


                      grMetric.addQuery('value', groupName);


                      grMetric.query();


                     


                      if (grMetric.hasNext()) {


                              // If so, then this ticket has already been counted for this


                              // assignment group and there's no need to do anything.


                              // Although we check for this in the groupMap above, this


                              // might still happen if we're running this script after the


                              // metric definition has been configured and new metric


                              // instances have been created.


                              continue;


                      }


                      else {


                              // If not, create a metric instance


                              var instant = new GlideDuration(0);


                             


                              grMetric = new GlideRecord('metric_instance');


                              grMetric.initialize();


                              grMetric.setValue('table', grIncident.getRecordClassName());


                              grMetric.setValue('id', grIncident.getValue('sys_id'));


                              grMetric.setValue('definition', grMetricDef.getValue('sys_id'));


                              grMetric.setValue('field', 'assignment_group');


                              grMetric.setValue('value', groupName);


                              grMetric.setValue('duration', instant);


                              grMetric.setValue('business_duration', instant);


                              grMetric.setValue('calculation_complete', true);


                              grMetric.setValue('start', grAudit.getValue('sys_created_on'));


                              grMetric.setValue('end', grAudit.getValue('sys_created_on'));


                              grMetric.insert();


                      }


              }


      }


})();


Hello !
At first thank you for all your work !

I have got the same issue as matth, and I'm only getting a metric created for the initial creation of an Incident - no new metrics with subsequent assignments.

Do you have an idea ?

Thank you in advance !

Jérémy

Hello Guys, 

 

I just saw this post and was wondering how do we get the Retroactively backfill script to run in order to populate the data?

 

Thank you,

 

Osvaldo 

This is amazing.



I have been spending the last few weeks trying to devise this exact script for my own Help Desk and was going crazy trying to calculate the distinct count of incidents that were "touched" by an assignment group.



In addition, this can have new filter conditions layered on top as a report source and could be re-purposed to make a "touched by tech" metric for even more granular analysis.



Thanks Dennis both of these scripts are a home run!


Hey Dennis,

This is exactly what I need, but i seem to be running a newer version of ServiceNow that is asking me to create Assessment, Type and Category for the Metric. Would you have any examples of what I need o setup to make it work? Thanks so much!