felladin
Tera Guru

Again a little code tip for those that may need it. Nothing hard to create yourself, but may be faster this way.

I had to change a metric that was running calculations on the wrong information, which in itself was not problem; what was an issue were the reports that used the metric, as they used incorrect data. So, I needed a way to trigger creation of new metric instances.

I used Scripts - Background to run two different scripts. The first looked for all instances of a specific metric and removed these. The second took all tasks that fit the query and for each triggered the event found in the metric business rule with appropriate parameters.

Before the scripts, here are some points:

  • Metric instances (metric_instance_list.do) has the task sys_id as their "ID", be sure to send this to find appropriate metric instance if needed.
  • It is very easy to dotwalk metric instance, as ID is the task and Definition is the Metric Definition (not sys_id, but a reference).
  • To search for all occurences of a definition in metric instance, use definition.name (if the name is what you use as identifier in your script).
  • To find what parameters trigger a metric, check the Metric System Logs, may help you if the variable information is hard to read.

Script to find all metric instances of a specific definition based on name:

        //Access table with metric instances

var met = new GlideRecord('metric_instance');

        //Get all metric instances created since beginning of this year (GMT)

met.addQuery('sys_created_on', '>', gs.beginningOfThisMonth());

        //Get all metric instances that are created by a metric definition with the word test in the name

met.addQuery('definition.name', 'CONTAINS', 'test');

met.query();

        //Show how many results found

gs.print('Found ' + met.getRowCount());

while (met.next()) {

      //Do what you need to with the metric instances.

}

Script to trigger creation of new metric instance with task ID:

var check = new GlideRecord('task');

      //Get all tasks that were closed this year

check.addQuery('closed_at','>',gs.beginningOfThisYear());

check.query();

gs.print('Found '+check.getRowCount());

while(check.next()){

        //Trigger metric.update with the task, send the trigger parameters

        //These are normally fetched through variables and commands, here we send them with static data

gs.eventQueue('metric.update', check, '[state,active]', check.sys_mod_count, 'metric_update');

}

As always, these are my current findings and only meant to help others resolve their quandaries quicker.

With regards

Anton Lindblad

Comments
Brian Lancaster
Tera Sage

Hello Anton,


I'm note sure I'm following what you are doing here.   I have recently created a new metric that closes out all other metrics like the default one called Open but this runs on the SC task table.   How would I get this to run for everything that was created in the past.   Most likely this year and last year should be good.


felladin
Tera Guru

Hello,



I am not sure what you mean by closing out all other metrics. Are you trying to stop metric creation on sc_task ?


If you need to remove old metrics but only for a specific table (and I can't stress this enough, try it in dev environment first) you should be able to:


var gr = new GlideRecord('metric_instance');


gr.addQuery('table','sc_task');


gr.addQuery('definition_name','!*','part of the name of the only metric that should be left'); //!* should be the same as "Does Not Contain"


gr.query();


while(gr.next()){


gr.deleteMultiple(); //This will delete the metric instance! It will not disable what creates the metric, only old instances of it, which I can't see a reason to do.


}




If you just need to run the new metric on old sc_task tasks, you should be able to use my second script above.


Easiest is to first check sys logs for how and with what the event is triggered that creates your metric.


Then you use that data to create your own manual event trigger as seen on row 09 of my script.


Change the GlideRecord to your table, for example GlideRecord('sc_task') to get all tasks in that table.



Read more here: https://developer.servicenow.com/app.do#!/api_doc?v=helsinki&id=c_GlideRecordScopedAPI



With regards


Anton Lindblad


Brian Lancaster
Tera Sage

No I'm trying to trigger a specific metric called open sc_task that I created.   First I have duration that run on the assigned to but when it comes to the person who is closing that task it does not calculate their duration.   Someone suggested that I copy the open that was against the incident because it has code that when active becomes false it will go in and close out any metrics that are still open the calculated them.   So I created on called open sc_task on the sc_task table with the code and that seemed to work. Now I'm trying to trigger that specific metric to run.   I tried you code above but it did not seem to work.   I was not sure if there was anything else I should change other then the table.


felladin
Tera Guru

In order to find what to add to line 09 in my script, go to System Logs - Events


Find one of the posts you can verify time wise against a working sc_task triggered metric.



You should then be able to change line 09 to:


gs.eventQueue('metric.update', query-variable, 'parm1', 'parm2', 'metric_update');



Also be aware that if the script checks for things in the metric your tasks must fulfill these statements. Our "Open" metric has an if-statement that if not passed will create a metric and if inactive the metric will be finished.


You may need to at first change the script to calculate the time between open (opened_at) and closed (closed_at) for your tasks before reverting the metric back to normal, day to day calculation.


And if you need a proper metric for time from open to close, you need to parse these values to the metric script.


Not done correctly, it may give you a metric with a very long time from open to close that is not correct.


Version history
Last update:
‎03-29-2017 01:53 AM
Updated by: