47. EPMO Open Source Coordination Office Redaction File Detail Report

Produced by Araxis Merge on 10/4/2017 8:04:34 AM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.

47.1 Files compared

# Location File Last Modified
1 rdk.zip\rdk\product\production\rdk\src\resources\cds-metrics metrics.js Fri Aug 25 15:36:55 2017 UTC
2 rdk.zip\rdk\product\production\rdk\src\resources\cds-metrics metrics.js Tue Oct 3 17:16:28 2017 UTC

47.2 Comparison summary

Description Between
Files 1 and 2
Text Blocks Lines
Unchanged 2 3352
Changed 1 2
Inserted 0 0
Removed 0 0

47.3 Comparison options

Whitespace
Character case Differences in character case are significant
Line endings Differences in line endings (CR and LF characters) are ignored
CR/LF characters Not shown in the comparison detail

47.4 Active regular expressions

No regular expressions were active.

47.5 Comparison detail

  1   'use stric t';
  2  
  3   var rdk =  require('. ./../core/ rdk');
  4   var _ = re quire('lod ash');
  5   var config Import = r equire('./ config');
  6  
  7   // set up  the packag es we need
  8   var metric DbName = c onfigImpor t.metricDb Name;
  9   var defini tionList =  configImp ort.define dMetricDef initions;
  10   var groupL ist = conf igImport.d efinedMetr icGroups;
  11  
  12   // Databas e
  13   var Object ID = requi re('mongod b').Object ID;
  14  
  15   var defini tionName =  [];
  16   var defini tionId = [ ];
  17  
  18   var messag eBodyError  = 'Messag e body can not be emp ty and mus t contain  valid JSON ';
  19   var idPara meterError  = 'Argume nt passed  in must be  a single  String of  12 bytes o r a string  of 24 hex  character s';
  20   var notFou ndError =  'Not Found ';
  21  
  22  
  23   function c reateInitD efinitions (logger) {
  24       return  function  initDefini tions(dbCo nnection)  {
  25  
  26           // Clear out  the existi ng definit ions and r e-seed the m
  27           db Connection .collectio n('definit ions').rem ove({}, fu nction(err or, result ) {
  28                if (erro r) {
  29                    logg er.warn({
  30                         error: err or,
  31                         result: re sult
  32                    });
  33                }
  34           }) ;
  35  
  36           _. each(defin itionList,  function( definition , index) {
  37                dbConnec tion.colle ction('def initions') .update({
  38                    _id:  definitio n._id
  39                }, defin ition, {
  40                    upse rt: true
  41                }, funct ion(error,  result) {
  42                    if ( error) {
  43                         logger.err or({
  44                             error:  error
  45                         });
  46                    }
  47                });
  48                definiti onName[def inition.na me] = inde x;
  49                definiti onId[defin ition._id]  = index;
  50           }) ;
  51  
  52           _. each(group List, func tion(group ) {
  53                dbConnec tion.colle ction('gro ups').upda te({
  54                    name : group.na me
  55                }, group , {
  56                    upse rt: true
  57                }, funct ion(error,  result) {
  58                    if ( error) {
  59                         logger.err or({
  60                             error:  error
  61                         });
  62                    }
  63                });
  64           }) ;
  65       };
  66   }
  67  
  68  
  69   // Checks  if a strin g, such as  a message  body, is  a valid JS ON object
  70   function i sJsonStrin g(inputStr ing) {
  71       try {
  72           JS ON.parse(i nputString );
  73       } catc h (e) {
  74           re turn false ;
  75       }
  76       return  true;
  77   }
  78  
  79  
  80   /*
  81    * Validat e the the  required p arameters  are passed  and that  the parame ters passe d are corr ect
  82    */
  83   function i nvalidMetr icSearchPa rameters(r eq) {
  84       req.lo gger.debug ('Validate  metric se arch param eters: ' +  req.query .metricId) ;
  85  
  86       if (_. isUndefine d(req.quer y.metricId )) {
  87           re turn 'Erro r: You mus t enter a  valid metr icId';
  88       }
  89       if (_. isUndefine d(req.quer y.startPer iod)) {
  90           re turn 'Erro r: You mus t enter a  valid star tPeriod';
  91       }
  92  
  93       var me tricIdRege x = /^.{1, }$/; // mi nimum 3 ch ars? /^\d+ $/;     ei ther a nam e or an id
  94       var da teTimeRege x = /^\d+$ /;
  95       var gr anularityR egex = /^\ d+$/;
  96       var or iginRegex  = /^.{1,}$ /; // mini mum 1 char s?;
  97       var in vocationTy peRegex =  /^.{1,}$/;  // minimu m 1 chars? ;
  98  
  99       // jus t a string  for the d emo
  100       if (!m etricIdReg ex.test(re q.query.me tricId)) {
  101           re turn 'Metr ic id cont ains illeg al charact ers.';
  102       }
  103       if (!d ateTimeReg ex.test(re q.query.st artPeriod) ) {
  104           re turn 'Star t time con tains ille gal charac ters.';
  105       }
  106       if (re q.query.en dPeriod != = undefine d && !date TimeRegex. test(req.q uery.endPe riod)) {
  107           re turn 'End  time conta ins illega l characte rs.';
  108       }
  109       if (re q.query.gr anularity  !== undefi ned && !gr anularityR egex.test( req.query. granularit y)) {
  110           re turn 'A gr anularity  is a whole  number in  milliseco nds.';
  111       }
  112       if (re q.query.or igin !== u ndefined & & !originR egex.test( req.query. origin)) {
  113           re turn 'orig in contain s illegal  characters .';
  114       }
  115       if (!i nvocationT ypeRegex.t est(req.qu ery.invoca tionType))  {
  116           re turn 'invo cationType  contains  illegal ch aracters.' ;
  117       }
  118       return  false;
  119   }
  120  
  121  
  122   /*
  123    * Creates  an aggreg ating quer y pipeline  for Mongo DB. Granul arity is a  required
  124    * value f or this ty pe of quer y.
  125    */
  126   function c reateAggre gatedQuery (query) {
  127       var ma tch = {
  128           $m atch: {
  129                'time':  {
  130                    $gt:  query.sta rtPeriod
  131                }
  132           }
  133       };
  134  
  135       if (qu ery.endPer iod) {
  136           ma tch.$match .time.$lt  = query.en dPeriod;
  137       }
  138       if (qu ery.origin ) {
  139           ma tch.$match .origin =  query.orig in;
  140       }
  141       if (qu ery.type)  {
  142           ma tch.$match .type = qu ery.type;
  143       }
  144       if (qu ery.invoca tionType)  {
  145           ma tch.$match .invocatio nType = qu ery.invoca tionType;
  146       }
  147       if (qu ery.event  === undefi ned) {
  148           ma tch.$match .name = qu ery.name;
  149       } else  {
  150           ma tch.$match .event = q uery.event ;
  151       }
  152  
  153       if (!q uery.granu larity) {
  154           qu ery.granul arity = 1;
  155       }
  156       // if  we're roun ding the g rouping ba sed on gra nularity,  we should  also round  the start  period ma tch
  157       match. $match.tim e.$gt = ro undToGranu larity(que ry.startPe riod, quer y.granular ity);
  158  
  159       var gr oup = {
  160           '$ group': {
  161                '_id': {
  162                    'tim e': {
  163                         '$subtract ': [
  164                             '$time ', {
  165                                 '$ mod': ['$t ime', Numb er(query.g ranularity )]
  166                             } // g ranularity
  167                             // in
  168                             // ms. ..
  169                         ]
  170                    }
  171                },
  172           }
  173       };
  174  
  175       var ag gregation  = query.ag gregation;
  176  
  177       _.each (aggregati on, functi on(aggrega te) {
  178           gr oup.$group [aggregate ] = {};
  179           if  (aggregat e === 'cou nt') {
  180                //             grou p.$group[a ggregate][ '$sum'] =  1;
  181                group.$g roup[aggre gate].$sum  = 1;
  182           }  else {
  183                group.$g roup[aggre gate]['$'  + aggregat e] = '$' +  query.pro perty;
  184           }
  185       });
  186  
  187       var so rt = {
  188           $s ort: {
  189                '_id.tim e': -1
  190           }
  191       }; //  descending  chronolog ical
  192       // ord er
  193       var li mit = {
  194           $l imit: 500
  195       }; //  500 record  max, per  documentat ion.
  196       var pr oject = {
  197           $p roject: {
  198                _id: 0,
  199                datetime : '$_id.ti me',
  200                count: 1 ,
  201                min: 1,
  202                max: 1,
  203                avg: 1,
  204                sum: 1
  205           }
  206       };
  207  
  208       //     req.logger .debug({
  209       //         match_ $gt: toISO String(mat ch.$match. time.$gt),
  210       //         match_ $lt: toISO String(mat ch.$match. time.$lt)
  211       //     }, 'Create  Aggregate d Query');
  212  
  213       return  [match, g roup, sort , limit, p roject];
  214   }
  215  
  216  
  217   /*
  218    * Creates  an count  query pipe line for M ongoDB
  219    */
  220   function c reateQuery (query) {
  221       var ma tch = {
  222           $m atch: {
  223                'time':  {
  224                    $gt:  query.sta rtPeriod
  225                }
  226           }
  227       };
  228  
  229       if (qu ery.endPer iod) {
  230           ma tch.$match .time.$lt  = query.en dPeriod;
  231       }
  232       if (qu ery.origin ) {
  233           ma tch.$match .origin =  query.orig in;
  234       }
  235       if (qu ery.type)  {
  236           ma tch.$match .type = qu ery.type;
  237       }
  238       if (qu ery.invoca tionType)  {
  239           ma tch.$match .invocatio nType = qu ery.invoca tionType;
  240       }
  241       if (qu ery.event  === undefi ned) {
  242           ma tch.$match .name = qu ery.name;
  243       } else  {
  244           ma tch.$match .event = q uery.event ;
  245       }
  246  
  247       var gr oup = {};
  248       if (qu ery.granul arity) {
  249           //  if we're  rounding t he groupin g based on  granulari ty, we sho uld also r ound the s tart perio d match
  250           ma tch.$match .time.$gt  = roundToG ranularity (query.sta rtPeriod,  query.gran ularity);
  251           gr oup = {
  252                '$group' : {
  253                    '_id ': {
  254                         'time': {
  255                             '$subt ract': [
  256                                 '$ time', {
  257                                      '$mod':  ['$time',  Number(que ry.granula rity)]
  258                                 }
  259                             ]
  260                         }
  261                    },
  262                    'cou nt': {
  263                         '$sum': 1
  264                    }
  265                }
  266           };
  267       }
  268  
  269       var so rt = {
  270           $s ort: {
  271                '_id.tim e': -1
  272           }
  273       };
  274       var li mit = {
  275           $l imit: 500
  276       };
  277       var pr oject = {
  278           $p roject: {
  279                _id: 0,
  280                count: 1 ,
  281                datetime : '$_id.ti me'
  282           }
  283       };
  284  
  285       if (qu ery.granul arity) {
  286           re turn [matc h, group,  sort, limi t, project ];
  287       }
  288       return  [match, s ort, limit , project] ;
  289   }
  290  
  291  
  292   function g etMetricDe finition(m etricId) {
  293       try {
  294           if  (isNaN(me tricId)) {
  295                return d efinitionL ist[defini tionName[m etricId]];
  296           }
  297           re turn defin itionList[ definition Id[metricI d]];
  298       } catc h (e) {
  299           re turn null;
  300       }
  301   }
  302  
  303  
  304   /**
  305    * Adds th e missing  time inter val metric s results  with null  values for  a given t ime range.
  306    *
  307    * @param  startPerio d {Number}  Epoch tim e represen tation of  the start  of the tim e period.
  308    * @param  endPeriod  {Number} E poch time  representa tion of th e end of t he time pe riod.
  309    * @param  granularit y {Number}  The time  step size  in millise conds.
  310    * @param  list {Arra y} The lis t of metri c items to  check for  missing t ime steps.
  311    * @return s {Array}  A list of  metrics pa dded with  null value s for the  missing ti me steps.
  312    */
  313   function p adMissingV alues(star tPeriod, e ndPeriod,  granularit y, list) {
  314       list =  list || [ ];
  315  
  316       // rou nd start/e nd periods  to line u p with gra nularity
  317       var ro undedStart Time = rou ndToGranul arity(star tPeriod, g ranularity );
  318       var ro undedEndTi me = round ToGranular ity(endPer iod, granu larity);
  319  
  320       // the  last time  slot shou ld happen  before the  end perio d
  321       var ti meSlot = r oundedEndT ime < endP eriod ? ro undedEndTi me : (endP eriod - gr anularity) ;
  322       var li stIndex =  0;
  323       var pa ddedList =  [];
  324  
  325       // The  list of m etrics is  sorted dec reasing ti me. We sta rt
  326       // at  the end an d work our  way backw ards to th e start of  the time  range.
  327       while  (timeSlot  >= rounded StartTime)  {
  328           va r item = l istIndex <  list.leng th ? list[ listIndex]  : null;
  329  
  330           if  (!item ||  timeSlot  > item.dat etime) {
  331                paddedLi st.push({
  332                    coun t: null,
  333                    min:  null,
  334                    max:  null,
  335                    avg:  null,
  336                    sum:  null,
  337                    date time: time Slot,
  338                    isoD ate: toISO String(tim eSlot)
  339                });
  340           }  else {
  341                item.iso Date = toI SOString(i tem.dateti me);
  342                paddedLi st.push(it em);
  343                listInde x++;
  344           }
  345           ti meSlot -=  granularit y;
  346       }
  347       return  paddedLis t;
  348   }
  349  
  350  
  351   /**
  352    * Rounds  a given ep och to ali gn with a  given gran ularity.
  353    *
  354    * @param  {Number} e poch Epoch  (unix tim e).
  355    * @param  {Number} g ranularity  Granulari ty in mill iseconds.
  356    * @return s {Number}  Returns a n epoch th at aligns  with the g iven granu larity.
  357    */
  358   function r oundToGran ularity(ep och, granu larity) {
  359       return  epoch - ( epoch % gr anularity) ;
  360   }
  361  
  362  
  363   /**
  364    * Convert s an epoch  time to i ts corresp onding UTC  ISO 8601  string.
  365    *
  366    * @param  {Number} e poch Unix  epoch time  to conver t.
  367    * @return s {String}
  368    */
  369   function t oISOString (epoch) {
  370       return  (new Date (epoch)).t oISOString ();
  371   }
  372  
  373  
  374   /**
  375    * @api {g et} /resou rce/cds/me trics/metr ics Get Me trics
  376    * @apiNam e GetMetri cs
  377    * @apiGro up Metrics
  378    * @apiDes cription R eturns a l ist of met ric data p oints. Poi nts will c ontain a s equence of  values
  379    * over ti me which c an be turn ed into a  chart.
  380    * @apiPar am {String } metricId  The id of  the type  of metric  to be disp layed
  381    * @apiPar am {long}  startPerio d the begg ining rang e of when  a queried  metric is  captured ( Unix time  in millise conds)
  382    * @apiPar am {long}  [endPeriod ] the end  range of w hen a quer ied metric  is captur ed (Unix t ime in mil liseconds)
  383    * @apiPar am {long}  [granulari ty] the le ngth of ti me in mill iseconds i n which me trics are  aggregated
  384    * @apiPar am {String } [origin]  Used to f ilter by u sing the n ame of the  source fr om where a  metric or iginated
  385    * @apiPar am {String ="Direct", "Backgroun d"} [invoc ationType]  describes  how a met ric is gen erated
  386    * @apiExa mple {js}  Example us age:
  387    * curl -i  http:// IP                /resource/ metrics/me trics?metr icId=1&sta rtPeriod=1 4316079470 79&endPeri od=1431636 747079&gra nularity=3 600000&ori gin=System A&invocati onType=Dir ect
  388    * @apiErr orExample  {json} Err or-Respons e:
  389    *     HTT P/1.1 400  Bad Reques t
  390    *     {
  391    *      "s tatus": "4 00"
  392    *       " error": "U ndefined M etric Requ ested."
  393    *     }
  394    * @apiSuc cess {json } data Jso n object c ontaining  a list of  all datapo int values
  395    * @apiSuc cessExampl e {json} G etMetrics- Response
  396    * {
  397    *  "statu s": "200"
  398    *  "data" : [
  399    *    {
  400    *      "d atetime":  1431633600 000,
  401    *      "c ount": 19,
  402    *      "m in": 0.0,
  403    *      "m ax": 0.0,
  404    *      "s um": 0.0
  405    *    }
  406    *   ]
  407    * }
  408    */
  409   function g etMetricSe arch(req,  res) {
  410       req.lo gger.debug ('metrics. getMetricS earch()');
  411  
  412       if (_. isUndefine d(req.app. subsystems .cds)) {
  413           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  414       }
  415  
  416       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  417           if  (error) {
  418                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  419           }
  420           re q.logger.d ebug('Metr ics GET ge tMetricSea rch called ');
  421  
  422           va r message  = invalidM etricSearc hParameter s(req);
  423           if  (message)  {
  424                res.stat us(rdk.htt pstatus.ba d_request) .rdkSend(m essage);
  425                return;
  426           }
  427  
  428           va r metricId  = req.que ry.metricI d;
  429           va r query =  getMetricD efinition( metricId);
  430           if  (!query)  {
  431                message  = 'Undefin ed Metric  Requested. ';
  432                res.stat us(400).se nd({
  433                    stat us: 400,
  434                    erro r: message
  435                });
  436                return;
  437           }
  438  
  439           qu ery.startP eriod = +r eq.query.s tartPeriod ;
  440           qu ery.endPer iod = null ;
  441           qu ery.granul arity = nu ll;
  442           qu ery.origin  = null;
  443           qu ery.invoca tionType =  null;
  444  
  445           if  (req.quer y.endPerio d) {
  446                query.en dPeriod =  +req.query .endPeriod ;
  447           }
  448           if  (req.quer y.granular ity) {
  449                if (+req .query.gra nularity >  0) {
  450                    quer y.granular ity = +req .query.gra nularity;
  451                }
  452           }
  453           if  (req.quer y.origin)  {
  454                query.or igin = req .query.ori gin;
  455           }
  456           if  (req.quer y.invocati onType) {
  457                query.in vocationTy pe = req.q uery.invoc ationType;
  458           }
  459  
  460           va r pipeline ;
  461           //  this assu mes that ' event type  call metr ics' defin ed as only  having th e count de fined.
  462           if  (query.ag gregation. length > 1 ) {
  463                pipeline  = createA ggregatedQ uery(query );
  464           }  else {
  465                pipeline  = createQ uery(query );
  466           }
  467  
  468           re q.logger.d ebug('Exec uting: db. collection (query.col lection).a ggregate(p ipeline)') ;
  469           re q.logger.d ebug('coll ection: '  + query.co llection);
  470           re q.logger.d ebug(pipel ine, 'Pipe line: \n') ;
  471  
  472           db Connection .collectio n(query.co llection). aggregate( pipeline,  function(e rror, resu lt) {
  473                if (erro r) {
  474                    req. logger.war n({
  475                         error: err or
  476                    });
  477                    retu rn res.sta tus(404).s end({
  478                         status: 40 4,
  479                         error: err or
  480                    });
  481                }
  482                req.logg er.debug(' Result cou nt: ' + (r esult ? re sult.lengt h : 0));
  483                return r es.status( 200).send( {
  484                    stat us: 200,
  485                    data : padMissi ngValues(q uery.start Period, qu ery.endPer iod, query .granulari ty, result )
  486                });
  487           }) ;
  488       });
  489   }
  490  
  491  
  492   // DASHBOA RD ....
  493  
  494   /**
  495    * @api {g et} /resou rce/cds/me trics/dash boards/:us erIdParam  Get All Da shboards
  496    * @apiNam e GetDashb oards
  497    * @apiGro up Dashboa rds
  498    * @apiDes cription G ets a list  of dashbo ards that  were saved  by an ass ociated us er. A dash board is a n object w hich conta ins settin gs
  499    * for cha rts which  can be dis played vis ually. Thi s list wil l only con tain dashb oard metad ata, and w ill not st ore chart  details. T his is
  500    * useful  for popula ting a sel ection lis t of dashb oards.  To  load an e ntire dash board, see  @GetDashb oard
  501    * @apiPar am {String } userIdPa ram The id  of the ty pe of metr ic to be d isplayed
  502    * @apiErr orExample  {json} Err or-Respons e:
  503    *     HTT P/1.1 404  Not Found
  504    *     {
  505    *       " status": " 404"
  506    *       " error": "N ot Found"
  507    *     }
  508    * @apiSuc cess {json } data Jso n object c ontaining  a list of  all user d ashboards
  509    * @apiSuc cessExampl e {json} G etDashboar ds-Respons e:
  510    * {
  511    *  "statu s": "200"
  512    *  "data" : {
  513    *   "_id" : "5554c5f 4e17664dc3 1573ae9",
  514    *    "use rId": "tes tuser",
  515    *    "nam e": "New D ashboard",
  516    *    "des cription":  "This is  a dashboar d example" ,
  517    *    "das hboardSett ings": {
  518    *      "s tartPeriod ": 0,
  519    *      "e ndPeriod":  0,
  520    *      "p eriodSelec ted": fals e,
  521    *      "g ranularity Selected":  false
  522    *    }
  523    *  }
  524    * }
  525    */
  526   function g etUserDash Boards(req , res) {
  527       req.lo gger.debug ('metrics. getUserDas hBoards()' );
  528  
  529       if (_. isUndefine d(req.app. subsystems .cds)) {
  530           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  531       }
  532  
  533       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  534           if  (error) {
  535                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  536           }
  537           re q.logger.d ebug('Metr ics GET ge tDashboard s called') ;
  538  
  539           //  TODO: get  the authe nticated u ser
  540           //     var ui d = req.pa ram('userI dParam');
  541           //     var ui d = req.se ssion.user .username;  //getKeyV alue(req.s ession.use r.duz);
  542           //     if (re q.query.us erId !== u ndefined)  {
  543           //         ui d = req.qu ery.userId ;
  544           //     }
  545  
  546           va r userId =  req.param ('userIdPa ram');
  547           if  (userId = == 'all')  {
  548                dbConnec tion.colle ction('das hboards'). find().toA rray(funct ion(error,  result) {
  549                    hand leToArrayR esult(req,  res, erro r, result) ;
  550                });
  551           }  else {
  552                dbConnec tion.colle ction('das hboards'). find({
  553                    user Id: userId
  554                }).toArr ay(functio n(error, r esult) {
  555                    hand leToArrayR esult(req,  res, erro r, result) ;
  556                });
  557           }
  558       });
  559   }
  560  
  561  
  562   function h andleToArr ayResult(r eq, res, e rror, resu lt) {
  563       var re sponseObje ct;
  564       if (er ror) {
  565           re sponseObje ct = {
  566                status:  404,
  567                error: e rror
  568           };
  569           re q.logger.d ebug(respo nseObject) ;
  570           re turn res.s tatus(404) .rdkSend(r esponseObj ect);
  571       }
  572       if (!r esult) {
  573           re sponseObje ct = {
  574                status:  404,
  575                error: n otFoundErr or
  576           };
  577           re q.logger.d ebug(respo nseObject) ;
  578           re turn res.s tatus(404) .rdkSend(r esponseObj ect);
  579       }
  580       respon seObject =  {
  581           st atus: 200,
  582           da ta: result
  583       };
  584       req.lo gger.debug (responseO bject);
  585       return  res.statu s(200).rdk Send(respo nseObject) ;
  586   }
  587  
  588  
  589   /**
  590    * @api {g et} /resou rce/cds/me trics/dash board/:das hboardId G et Dashboa rd
  591    * @apiNam e GetDashb oard
  592    * @apiGro up Dashboa rds
  593    * @apiDes cription G ets a comp lete dashb oard that  was saved  by an asso ciated use r.  A dash board serv es as a co ntainer fo r
  594    * visual  informatio n - collec ted metric s that can  be displa yed as a c hart
  595    * @apiPar am {String } dashboar dId The id  of the ty pe of metr ic to be d isplayed
  596    * @apiErr orExample  {json} Err or-Respons e:
  597    *     HTT P/1.1 400  Bad Reques t
  598    *     {
  599    *       " status": " 400"
  600    *       " error": "A rgument pa ssed in mu st be a si ngle Strin g of 12 by tes or a s tring of 2 4 hex char acters"
  601    *     }
  602    * @apiErr orExample  {json} Err or-Respons e:
  603    *     HTT P/1.1 404  Not Found
  604    *     {
  605    *       " status": " 404"
  606    *       " error": "N ot Found"
  607    *     }
  608    * @apiSuc cess {json } data Jso n object c ontaining  a list of  all user d ashboards
  609    * @apiSuc cessExampl e {json} G etDashboar d-Response
  610    * {
  611    *     "st atus": 200 ,
  612    *     "da ta": [
  613    *     {
  614    *      "_ id": "5554 c5f4e17664 dc31573ae9 ",
  615    *      "u serId": "t estuser",
  616    *      "n ame": "New  Dashboard ",
  617    *      "d escription ": "This i s a dashbo ard exampl e",
  618    *      "d ashboardSe ttings": {
  619    *           "startPe riod": 143 1534434120 ,
  620    *           "endPeri od": 14316 20834120,
  621    *           "periodS elected":  true,
  622    *           "granula ritySelect ed": true,
  623    *           "period" : "D1",
  624    *           "granula rity": "H8 ",
  625    *           "hours":  "1",
  626    *           "minutes ": "00",
  627    *           "amPm":  "AM"
  628    *      },
  629    *           "charts" : [
  630    *           {
  631    *               "tit le": "Sess ion Count  Chart",
  632    *               "per iod": "D1" ,
  633    *               "sta rtPeriod":  143153443 4113,
  634    *               "end Period": 1 4316208341 13,
  635    *               "gra nularity":  "H8",
  636    *               "met ricGroupId ": "Sessio nCount",
  637    *               "sel ectedMetaD efinitions ": [
  638    *               {
  639    *                    "name": "S essionCoun t",
  640    *                    "methodNam e": "avg",
  641    *                    "definitio nId": "1"
  642    *               },
  643    *               {
  644    *                    "name": "S essionCoun t",
  645    *                    "methodNam e": "count ",
  646    *                    "definitio nId": "1"
  647    *                }
  648    *               ],
  649    *               "cha rtType": " COMBO",
  650    *               "liv eUpdates":  false,
  651    *               "hou rs": "1",
  652    *               "min utes": "00 ",
  653    *               "amP m": "AM"
  654    *            }
  655    *          ]
  656    *     }
  657    *]
  658    *}
  659    */
  660   function g etDashBoar d(req, res ) {
  661       req.lo gger.debug ('metrics. getDashBoa rd()');
  662  
  663       if (_. isUndefine d(req.app. subsystems .cds)) {
  664           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  665       }
  666  
  667       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  668           if  (error) {
  669                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  670           }
  671           //     var me ssage = in validDashb oardParame ters(req);
  672           //     if (me ssage) {
  673           //         re s.status(r dk.httpsta tus.bad_re quest).rdk Send(messa ge);
  674           //     } else  {
  675  
  676           va r id = req .param('da shboardId' );
  677           if  (ObjectID .isValid(i d) === fal se) {
  678                return r es.status( 400).send( {
  679                    stat us: 400,
  680                    erro r: idParam eterError
  681                });
  682           }
  683  
  684           db Connection .collectio n('dashboa rds').find One({
  685                _id: new  ObjectID( id)
  686           },  function( error, res ult) {
  687                if (erro r) {
  688                    retu rn res.sta tus(404).s end({
  689                         status: 40 4,
  690                         error: err or
  691                    });
  692                }
  693                if (!res ult) {
  694                    retu rn res.sta tus(404).s end({
  695                         status: 40 4,
  696                         error: not FoundError
  697                    });
  698                }
  699                return r es.status( 200).send( {
  700                    stat us: 200,
  701                    data : result
  702                });
  703           }) ;
  704       });
  705   }
  706  
  707  
  708   /**
  709    * @api {p ost} /reso urce/cds/m etrics/das hboard Cre ate Dashbo ard
  710    * @apiNam e CreateDa shboard
  711    * @apiGro up Dashboa rds
  712    * @apiDes cription C reates a n ew dashboa rd.  Once  a dashboar d is creat ed, it can  be update d to have  charts ass igned to i t.
  713    * @apiPar amExample  {json} Das hboard-Exa mple:
  714    * {
  715    *     "us erId": "te stuser",
  716    *     "na me": "New  Dashboard" ,
  717    *     "de scription" : "This is  a dashboa rd example ",
  718    * }
  719    * @apiSuc cess (201)  {json} da ta the das hboard how  it exists  after it  was initia lized (id  created) a nd persist ed
  720    * @apiSuc cessExampl e {json} C reateDashb oard-Respo nse
  721    *{
  722    *    "sta tus": "201 "
  723    *    "dat a": [
  724    *         {
  725    *             "userI d": "testu ser",
  726    *             "name" : "New Das hboard",
  727    *             "descr iption": " This is a  dashboard  example",
  728    *             "_id":  "5567648f 4ecbd1dcf1 8df799"
  729    *         }
  730    *    ]
  731    *}
  732    * @apiErr orExample  {json} Err or-Respons e:
  733    *     HTT P/1.1 400  Bad Reques t
  734    *     {
  735    *       " status": " 400"
  736    *       " error": "M essage bod y cannot b e empty an d must con tain valid  JSON"
  737    *     }
  738    */
  739   function c reateDashb oard(req,  res) {
  740       req.lo gger.debug ('metrics. createDash board()');
  741  
  742       if (_. isUndefine d(req.app. subsystems .cds)) {
  743           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  744       }
  745  
  746       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  747           if  (error) {
  748                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  749           }
  750           re q.logger.d ebug('Metr ics POST c reateDashb oard calle d');
  751  
  752           va r dashboar d = req.bo dy;
  753           if  (dashboar d === null  || Object .keys(dash board).len gth === 0)  {
  754                return r es.status( 400).send( {
  755                    stat us: 400,
  756                    erro r: message BodyError
  757                });
  758           }
  759  
  760           db Connection .collectio n('dashboa rds').inse rt(dashboa rd, functi on(error,  result) {
  761                if (erro r) {
  762                    retu rn res.sta tus(404).s end({
  763                         status: 40 4,
  764                         error: err or
  765                    });
  766                }
  767                return r es.status( 201).send( {
  768                    stat us: 201,
  769                    data : result.o ps
  770                });
  771           }) ;
  772       });
  773   }
  774  
  775  
  776   /**
  777    * @api {p ut} /resou rce/cds/me trics/dash board/:das hboardId U pdate Dash board
  778    * @apiNam e UpdateDa shboard
  779    * @apiGro up Dashboa rds
  780    * @apiDes cription U pdates an  existing d ashboard
  781    * @apiPar am {String } dashboar dId the id  of the da shboard to  be update d
  782    * @apiPar amExample  {json} Upd ateDashboa rd-PutBody
  783    * {
  784    * "_id":  "5554c5f4e 17664dc315 73ae9",
  785    * "userId ": "testus er",
  786    * "name":  "New Dash board",
  787    * "descri ption": "T his is a d ashboard e xample",
  788    * "dashbo ardSetting s": {
  789    *    "sta rtPeriod":  143153443 4120,
  790    *    "end Period": 1 4316208341 20,
  791    *    "per iodSelecte d": true,
  792    *    "gra nularitySe lected": t rue,
  793    *     "pe riod": "D1 ",
  794    *     "gr anularity" : "H8",
  795    *     "ho urs": "1",
  796    *     "mi nutes": "0 0",
  797    *      "a mPm": "AM"
  798    *  },
  799    *  "chart s": [
  800    *    {
  801    *      "t itle": "Se ssion Coun t Chart",
  802    *      "p eriod": "D 1",
  803    *      "s tartPeriod ": 1431534 434113,
  804    *      "e ndPeriod":  143162083 4113,
  805    *      "g ranularity ": "H8",
  806    *      "m etricGroup Id": "Sess ionCount",
  807    *      "s electedMet aDefinitio ns": [
  808    *         {
  809    *           "name":  "SessionCo unt",
  810    *           "methodN ame": "avg ",
  811    *           "definit ionId": "1 "
  812    *         },
  813    *         {
  814    *           "name":  "SessionCo unt",
  815    *           "methodN ame": "cou nt",
  816    *          "definiti onId": "1"
  817    *         }
  818    *      ],
  819    *      "c hartType":  "COMBO",
  820    *      "l iveUpdates ": false,
  821    *      "h ours": "1" ,
  822    *      "m inutes": " 00",
  823    *      "a mPm": "AM"
  824    *    }
  825    *  ]
  826    *}
  827    * @apiErr orExample  {json} Err or-Respons e:
  828    *     HTT P/1.1 400  Bad Reques t
  829    *     {
  830    *       " status": " 400"
  831    *       " error": "A rgument pa ssed in mu st be a si ngle Strin g of 12 by tes or a s tring of 2 4 hex char acters"
  832    *     }
  833    * @apiErr orExample  {json} Err or-Respons e:
  834    *     HTT P/1.1 400  Bad Reques t
  835    *     {
  836    *       " status": " 400"
  837    *       " error": "M essage bod y cannot b e empty an d must con tain valid  JSON"
  838    *     }
  839    * @apiErr orExample  {json} Err or-Respons e:
  840    *     HTT P/1.1 404  Not Found
  841    *     {
  842    *       " status": " 404"
  843    *       " error": "N ot Found"
  844    *     }
  845    * @apiSuc cess {json } data the  integer v alue of 1
  846    * @apiSuc cessExampl e {json} U pdateDashb oard-Respo nse
  847    *{
  848    * "data":  {
  849    *    "res ult": "1"
  850    *  },
  851    *  "statu s": "200"
  852    *}
  853    */
  854   function u pdateDashb oard(req,  res) {
  855       req.lo gger.debug ('metrics. updateDash board()');
  856  
  857       if (_. isUndefine d(req.app. subsystems .cds)) {
  858           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  859       }
  860  
  861       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  862           if  (error) {
  863                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  864           }
  865           re q.logger.d ebug('Metr ics PUT up dateDashbo ard called ');
  866  
  867           va r id = req .param('da shboardId' );
  868           if  (ObjectID .isValid(i d) === fal se) {
  869                res.stat us(400).se nd({
  870                    stat us: 400,
  871                    erro r: idParam eterError
  872                });
  873                return;
  874           }
  875  
  876           va r dashboar d = req.bo dy;
  877           if  (dashboar d === null  || Object .keys(dash board).len gth === 0  || isJsonS tring(dash board)) {
  878                return r es.status( 400).send( {
  879                    stat us: 400,
  880                    erro r: message BodyError
  881                });
  882           }
  883  
  884           de lete dashb oard._id;
  885           db Connection .collectio n('dashboa rds').upda te({
  886                _id: new  ObjectID( id)
  887           },  dashboard , {}, func tion(err,  result) {
  888                if (err)  {
  889                    retu rn res.sta tus(404).s end({
  890                         status: 40 4,
  891                         error: err
  892                    });
  893                }
  894                if (!res ult || res ult === 0)  {
  895                    retu rn res.sta tus(404).s end({
  896                         status: 40 4,
  897                         error: not FoundError
  898                    });
  899                }
  900                return r es.status( 200).send( {
  901                    stat us: 200,
  902                    data : {
  903                         result: re sult
  904                    }
  905                });
  906           }) ;
  907       });
  908   }
  909  
  910  
  911   /**
  912    * @api {d elete} /re source/cds /metrics/d ashboard/: dashboardI d Delete D ashboard
  913    * @apiNam e DeleteDa shboard
  914    * @apiGro up Dashboa rds
  915    * @apiDes cription D eletes a d ashboard
  916    * @apiPar am {String } dashboar dId The id  of the da shboard to  be delete d
  917    * @apiErr orExample  {json} Err or-Respons e:
  918    *     HTT P/1.1 400  Bad Reques t
  919    *     {
  920    *       " status": " 400"
  921    *       " error": "A rgument pa ssed in mu st be a si ngle Strin g of 12 by tes or a s tring of 2 4 hex char acters"
  922    *     }
  923    * @apiErr orExample  {json} Err or-Respons e:
  924    *     HTT P/1.1 404  Not Found
  925    *     {
  926    *       " status": " 404"
  927    *       " error": "N ot Found"
  928    *     }
  929    * @apiSuc cess {json } data An  integer va lue of 1
  930    * @apiSuc cessExampl e {json} D eleteDashb oard-Respo nse
  931    *{
  932    * "data":  {
  933    *    "res ult": "1"
  934    *  },
  935    *  "statu s": "200"
  936    *}
  937    */
  938   function d eleteDashb oard(req,  res) {
  939       req.lo gger.debug ('metrics. deleteDash board()');
  940  
  941       if (_. isUndefine d(req.app. subsystems .cds)) {
  942           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  943       }
  944  
  945       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  946           if  (error) {
  947                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  948           }
  949           re q.logger.d ebug('Metr ics DELETE  deleteDas hboard cal led');
  950  
  951           va r id = req .param('da shboardId' );
  952           if  (ObjectID .isValid(i d) === fal se) {
  953                return r es.status( 400).send( {
  954                    stat us: 400,
  955                    erro r: idParam eterError
  956                });
  957           }
  958  
  959           db Connection .collectio n('dashboa rds').remo ve({
  960                _id: new  ObjectID( id)
  961           },  function( error, res ult) {
  962                if (erro r) {
  963                    retu rn res.sta tus(404).s end({
  964                         status: 40 4,
  965                         error: err or
  966                    });
  967                }
  968                if (!res ult || res ult === 0)  {
  969                    retu rn res.sta tus(404).s end({
  970                         status: 40 4,
  971                         error: not FoundError
  972                    });
  973                }
  974                return r es.status( 200).send( {
  975                    stat us: 200,
  976                    data : {
  977                         result: re sult
  978                    }
  979                });
  980           }) ;
  981       });
  982   }
  983  
  984  
  985   // GROUPS  ...
  986  
  987   /**
  988    * @api {g et} /resou rce/cds/me trics/grou ps Get Gro ups
  989    * @apiNam e GetGroup s
  990    * @apiGro up Groups
  991    * @apiDes cription G ets a list  of metric  groups.   Groups fun ctions are  for conve nience. Me tric clien ts can cho ose
  992    * how to  use these  groups, if  at all
  993    * @apiSuc cess {json } data Jso n object c ontaining  a list of  all groups
  994    * @apiSuc cessExampl e {json} G etGroups-R esponse
  995    * {
  996    * "status ": "200"
  997    * "data":  [
  998    *    {
  999    *      "_ id": "54d4 6c139bb12b c802bb92cc ",
  1000    *      "n ame": "All  Metrics",
  1001    *      "d escription ": "A list  of all me tric defin itions cur rently ava ilable",
  1002    *      "m etricList" : [
  1003    *         "SessionCo unt",
  1004    *         "Execution _Begin",
  1005    *         "Invocatio n_Begin",
  1006    *         "Summary_T otal"
  1007    *      ]
  1008    *    }
  1009    *  ]
  1010    *}
  1011    */
  1012   function g etMetricGr oups(req,  res) {
  1013       req.lo gger.debug ('metrics. getMetricG roups()');
  1014  
  1015       if (_. isUndefine d(req.app. subsystems .cds)) {
  1016           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1017       }
  1018  
  1019       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1020           if  (error) {
  1021                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1022           }
  1023           re q.logger.d ebug('Metr ics GET ge tMetricGro ups called ');
  1024  
  1025           db Connection .collectio n('groups' ).find().t oArray(fun ction(erro r, result)  {
  1026                handleTo ArrayResul t(req, res , error, r esult);
  1027           }) ;
  1028       });
  1029   }
  1030  
  1031  
  1032   /**
  1033    * @api {p ost} /reso urce/cds/m etrics/gro ups Create  Group
  1034    * @apiNam e CreateGr oups
  1035    * @apiGro up Groups
  1036    * @apiDes cription C reates a n ew metric  group
  1037    * @apiPar amExample  {json} Cre ateGroup-P ostBody
  1038    *{
  1039    *  "name" : "test Me trics grou p",
  1040    *  "descr iption": " This group  contains  test metri cs",
  1041    *               "met ricList":  [
  1042    *                 "S essionCoun t",
  1043    *                 "E xecution_B egin",
  1044    *                 "I nvocation_ Begin",
  1045    *                 "S ummary_Tot al"
  1046    *             ]
  1047    *}
  1048    * @apiErr orExample  {json} Err or-Respons e:
  1049    *     HTT P/1.1 400  Bad Reques t
  1050    *     {
  1051    *       " status": " 400"
  1052    *       " error": "M essage bod y cannot b e empty an d must con tain valid  JSON"
  1053    *     }
  1054    * @apiSuc cess (201)  {json} da ta the gro up how it  exists aft er it gets  initializ ed (id cre ated) and  persisted
  1055    * @apiSuc cessExampl e {json} C reateGroup -Response
  1056    *{
  1057    *  "statu s": "201"
  1058    *    "dat a": [
  1059    *         {
  1060    *             "name" : "test Me trics grou p",
  1061    *             "descr iption": " This group  contains  test metri cs",
  1062    *             "metri cList": [
  1063    *                 "S essionCoun t",
  1064    *                 "E xecution_B egin",
  1065    *                 "I nvocation_ Begin",
  1066    *                 "S ummary_Tot al"
  1067    *             ],
  1068    *             "_id":  "55676320 4ecbd1dcf1 8df798"
  1069    *         }
  1070    *    ]
  1071    *}
  1072    */
  1073   function c reateMetri cGroup(req , res) {
  1074       req.lo gger.debug ('metrics. createMetr icGroup()' );
  1075  
  1076       if (_. isUndefine d(req.app. subsystems .cds)) {
  1077           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1078       }
  1079  
  1080       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1081           if  (error) {
  1082                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1083           }
  1084           re q.logger.d ebug('Metr ics POST c reateMetri cGroup cal led');
  1085  
  1086           //  TODO:  AD MIN FUNCTI ON ONLY -  check user  using aut h
  1087           //  req.sessi on.user.vi staKeys[]
  1088  
  1089           va r group =  req.body;
  1090           if  (group == = null ||  Object.key s(group).l ength ===  0) {
  1091                return r es.status( 400).send( {
  1092                    erro r: message BodyError
  1093                });
  1094           }
  1095  
  1096           db Connection .collectio n('groups' ).insert(g roup, func tion(error , result)  {
  1097                if (erro r) {
  1098                    retu rn res.sta tus(404).s end({
  1099                         status: 40 4,
  1100                         error: err or
  1101                    });
  1102                }
  1103                if (!res ult) {
  1104                    retu rn res.sta tus(404).s end({
  1105                         status: 40 4,
  1106                         error: not FoundError
  1107                    });
  1108                }
  1109                return r es.status( 201).send( {
  1110                    stat us: 201,
  1111                    data : result.o ps
  1112                });
  1113           }) ;
  1114       });
  1115   }
  1116  
  1117  
  1118   /**
  1119    * @apiIgn ore 1) thi s is an ad min functi on 2) the  implementa tion is mi ssing on C DSInvocati on 3) as a  workaroun d a group  can be del eted and r ecreated
  1120    * @api {p ost} /reso urce/cds/m etrics/gro ups Update  Group
  1121    * @apiNam e UpdateGr oups
  1122    * @apiGro up Groups
  1123    * @apiDes cription U pdates a m etric grou p
  1124    * @apiPar amExample  {json} Upd ateGroup-P ostBody
  1125    * {
  1126    *  "_id":  4
  1127    *  "name" : "Example  Group",
  1128    *  "descr iption": " This is an  example g roup",
  1129    *  "metri cList": [
  1130    *    "0",
  1131    *    "1",
  1132    *    "2"
  1133    *  ]
  1134    * }
  1135    * @apiErr or (400) E rrorMessag e bad requ est
  1136    * @apiErr or (404) E rrorMessag e not foun d
  1137    * @apiErr orExample  {json} Err or-Respons e:
  1138    *     HTT P/1.1 400  Bad Reques t
  1139    *     {
  1140    *       " status": " 400"
  1141    *       " error": "M essage bod y cannot b e empty an d must con tain valid  JSON"
  1142    *     }
  1143    * @apiSuc cess {json } data Jso n object c ontaining  a list of  all groups
  1144    * @apiSuc cess {json } data the  integer v alue of 1
  1145    * @apiSuc cessExampl e {json} U pdateGroup -Response
  1146    *{
  1147    * "data":  {
  1148    *    "res ult": "1"
  1149    *  },
  1150    *  "statu s": "200"
  1151    *}
  1152    */
  1153   function u pdateMetri cGroup(req , res) {
  1154       req.lo gger.debug ('updateMe tricGroup  PUT update MetricGrou p called -  method no t implemen ted');
  1155       res.st atus(501). send({
  1156           st atus: 501,
  1157           er ror: 'Meth od not imp lemented'
  1158       });
  1159   }
  1160  
  1161  
  1162   /**
  1163    * @api {d elete} /re source/cds /metrics/g roups/:met ricGroupId  Delete Gr oup
  1164    * @apiNam e DeleteGr oup
  1165    * @apiGro up Groups
  1166    * @apiDes cription D elete Grou p
  1167    * @apiPar am {String } metricGr oupId the  id of the  group to b e deleted
  1168    * @apiErr or (400) E rrorMessag e bad requ est
  1169    * @apiErr or (404) E rrorMessag e not foun d
  1170    * @apiSuc cess {json } data An  integer va lue of 1
  1171    * @apiSuc cessExampl e {json} D eleteGroup -Response
  1172    *{
  1173    * "data":  {
  1174    *    "res ult": "1"
  1175    *  },
  1176    *  "statu s": "200"
  1177    *}
  1178    */
  1179   function d eleteMetri cGroup(req , res) {
  1180       req.lo gger.debug ('metrics. deleteMetr icGroup()' );
  1181  
  1182       if (_. isUndefine d(req.app. subsystems .cds)) {
  1183           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1184       }
  1185  
  1186       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1187           if  (error) {
  1188                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1189           }
  1190           re q.logger.d ebug('Metr ics DELETE  deleteMet ricGroup c alled');
  1191  
  1192           //  TODO:  AD MIN FUNCTI ON ONLY -  check user  using aut h
  1193           //  req.sessi on.user.?? ?
  1194  
  1195           va r id = req .param('me tricGroupI d');
  1196           if  (ObjectID .isValid(i d) === fal se) {
  1197                res.stat us(400).se nd({
  1198                    stat us: 400,
  1199                    erro r: idParam eterError
  1200                });
  1201                return;
  1202           }
  1203  
  1204           id  = new Obj ectID(id);
  1205           db Connection .collectio n('groups' ).remove({
  1206                _id: id
  1207           },  function( error, res ult) {
  1208                if (erro r) {
  1209                    res. status(404 ).send({
  1210                         status: 40 4,
  1211                         error: err or
  1212                    });
  1213                }
  1214                if (!res ult || res ult === 0)  {
  1215                    res. status(404 ).send({
  1216                         status: 40 4,
  1217                         error: not FoundError
  1218                    });
  1219                }
  1220                res.stat us(200).se nd({
  1221                    stat us: 200,
  1222                    data : {
  1223                         result: re sult
  1224                    }
  1225                });
  1226           }) ;
  1227       });
  1228   }
  1229  
  1230  
  1231   // DEFINIT IONS ...
  1232  
  1233   /**
  1234    * @api {g et} /resou rce/cds/me trics/defi nitions Ge t Definiti ons
  1235    * @apiNam e GetDefin itions
  1236    * @apiGro up Definit ions
  1237    * @apiDes cription R eturns a s tatic list  of the me trics that  are suppo rted by th is service , along wi th additio nal clarif ying infor mation,
  1238    * includi ng a descr iption of  that metri c and the  attributes  of the ty pe of char ts that it  can suppo rt. The re ason they  are
  1239    * static  is because  unique, b ack end lo gic must b e written  to capture  and proce ss each me tric
  1240    * @apiSuc cess {json } data Jso n object c ontaining  a list of  all metric  definitio ns
  1241    * @apiSuc cessExampl e {json} G etDefiniti ons-Respon se
  1242    * {
  1243    *  "statu s": "200"
  1244    *  "data" : [
  1245    *    {
  1246    *      "_ id": "8",
  1247    *      "n ame": "Sum mary_Total ",
  1248    *      "d escription ": "Summar y, total t imings rep ort.",
  1249    *      "u nitOfMeasu re": "Coun t",
  1250    *      "u pdateInter val": 1500 0,
  1251    *      "a ggregation ": [
  1252    *         "count",
  1253    *         "min",
  1254    *         "max",
  1255    *         "avg",
  1256    *         "sum"
  1257    *      ],
  1258    *      "o rigins": [
  1259    *         "EngineOne ",
  1260    *         "SystemB"
  1261    *      ],
  1262    *      "i nvocationT ypes": [
  1263    *         "Direct",
  1264    *         "Backgroun d"
  1265    *      ],
  1266    *      "t ype": "inv oke",
  1267    *      "e vent": "su mmary",
  1268    *      "p roperty":  "timings.t otal",
  1269    *      "c ollection" : "metrics "
  1270    *    }
  1271    *  ]
  1272    *}
  1273    */
  1274   function g etMetricDe finitions( req, res)  {
  1275       req.lo gger.debug ('metrics. getMetricD efinitions ()');
  1276  
  1277       if (_. isUndefine d(req.app. subsystems .cds)) {
  1278           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1279       }
  1280  
  1281       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1282           if  (error) {
  1283                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1284           }
  1285           re q.logger.d ebug('Metr ics GET ge tMetricDef initions c alled');
  1286  
  1287           db Connection .collectio n('definit ions').fin d().toArra y(function (error, re sult) {
  1288                handleTo ArrayResul t(req, res , error, r esult);
  1289           }) ;
  1290       });
  1291   }
  1292  
  1293  
  1294   /**
  1295    * @apiIgn ore - TODO : restrict  method ac cess to so me sort of  admin rol e
  1296    * @api {p ost} /reso urce/cds/m etrics/def initions C reate Defi nition
  1297    * @apiNam e CreateDe finitions
  1298    * @apiGro up Definit ions
  1299    * @apiDes cription C reate
  1300    * @apiSuc cess (201)  {json} da ta the gen ereated id  of the ne w definiti on
  1301    * @apiSuc cessExampl e {json} C reateDefin ition-Resp onse
  1302    * {
  1303    *  "data" :<new_defi nition_id>
  1304    * }
  1305    *     HTT P/1.1 400  Bad Reques t
  1306    *     {
  1307    *       " status": " 400"
  1308    *       " error": "A rgument pa ssed in mu st be a si ngle Strin g of 12 by tes or a s tring of 2 4 hex char acters"
  1309    *     }
  1310    * @apiErr orExample  {json} Err or-Respons e:
  1311    *     HTT P/1.1 404  Not Found
  1312    *     {
  1313    *       " status": " 404"
  1314    *       " error": "N ot Found"
  1315    *     }
  1316    */
  1317   function c reateMetri cDefinitio ns(req, re s) {
  1318       req.lo gger.debug ('metrics. createMetr icDefiniti ons()');
  1319  
  1320       if (_. isUndefine d(req.app. subsystems .cds)) {
  1321           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1322       }
  1323  
  1324       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1325           if  (error) {
  1326                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1327           }
  1328           re q.logger.d ebug('Metr ics POST c reateDefin ition call ed');
  1329  
  1330           va r metDef =  req.body;
  1331           if  (metDef = == null ||  Object.ke ys(metDef) .length == = 0) {
  1332                res.stat us(400).se nd({
  1333                    stat us: 400,
  1334                    erro r: message BodyError
  1335                });
  1336                return;
  1337           }
  1338  
  1339           db Connection .collectio n('definit ions').ins ert(metDef , function (error, re sult) {
  1340                if (erro r) {
  1341                    res. status(404 ).send({
  1342                         status: 40 4,
  1343                         error: err or
  1344                    });
  1345                }
  1346                return r es.status( 201).send( {
  1347                    stat us: 201,
  1348                    data : result.o ps
  1349                });
  1350           }) ;
  1351       });
  1352   }
  1353  
  1354  
  1355   /**
  1356    * @apiIgn ore - TODO : restrict  method ac cess to so me sort of  admin rol e
  1357    * @api {d elete} /re source/cds /metrics/d efinitions /:definiti onId Delet e Definiti on
  1358    * @apiNam e DeleteDe finitions
  1359    * @apiGro up Definit ions
  1360    * @apiDes cription
  1361    *     HTT P/1.1 400  Bad Reques t
  1362    *     {
  1363    *       " status": " 400"
  1364    *       " error": "A rgument pa ssed in mu st be a si ngle Strin g of 12 by tes or a s tring of 2 4 hex char acters"
  1365    *     }
  1366    * @apiErr orExample  {json} Err or-Respons e:
  1367    *     HTT P/1.1 404  Not Found
  1368    *     {
  1369    *       " status": " 404"
  1370    *       " error": "N ot Found"
  1371    *     }
  1372    * @apiSuc cess {json } data 1
  1373    * @apiSuc cessExampl e {json} C reateDefin ition-Resp onse
  1374    *{
  1375    * "data":  {
  1376    *    "res ult": "1"
  1377    *  },
  1378    *  "statu s": "200"
  1379    *}
  1380    */
  1381   function d eleteMetri cDefinitio n(req, res ) {
  1382       req.lo gger.debug ('metrics. deleteMetr icDefiniti on()');
  1383  
  1384       if (_. isUndefine d(req.app. subsystems .cds)) {
  1385           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1386       }
  1387  
  1388       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1389           if  (error) {
  1390                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1391           }
  1392           re q.logger.d ebug('Metr ics POST d eleteDefin ition call ed');
  1393  
  1394           // FUTURE-TOD O - standa rdize the  way IDs ar e used for  definitio ns
  1395           va r id = req .param('de finitionId ');
  1396           if  (ObjectID .isValid(i d) === fal se) {
  1397                return r es.status( 400).send( {
  1398                    stat us: 400,
  1399                    erro r: idParam eterError
  1400                });
  1401           }
  1402  
  1403           id  = new Obj ectID(id);
  1404           db Connection .collectio n('definit ions').rem ove({
  1405                _id: id
  1406           },  function( error, res ult) {
  1407                if (erro r) {
  1408                    retu rn res.sta tus(404).s end({
  1409                         status: 40 4,
  1410                         error: err or
  1411                    });
  1412                }
  1413                if (!res ult || res ult.result .ok === 0)  {
  1414                    retu rn res.sta tus(404).s end({
  1415                         status: 40 4,
  1416                         error: not FoundError
  1417                    });
  1418                }
  1419                return r es.status( 200).send( {
  1420                    stat us: 200,
  1421                    data : {
  1422                         result: re sult
  1423                    }
  1424                });
  1425           }) ;
  1426       });
  1427   }
  1428  
  1429  
  1430   // ROLES . ..
  1431  
  1432   /**
  1433    * @api {g et} /resou rce/cds/me trics/role s Get Role s
  1434    * @apiNam e GetRoles
  1435    * @apiGro up Roles
  1436    * @apiDes cription G ets a list  of roles
  1437    * @apiSuc cess {json } data Jso n object c ontaining  a list of  all roles
  1438    * @apiSuc cessExampl e {json} G etRoles-Re sponse
  1439    * {
  1440    *  "statu s": "200"
  1441    *  "data" : [
  1442    *    {
  1443    *      "_ id": "8",
  1444    *      "n ame": "Adm in",
  1445    *      "d escription ": "Admin  has unrest ricted pri vilege"
  1446    *    }
  1447    *  ]
  1448    * }
  1449    */
  1450   function g etRoles(re q, res) {
  1451       req.lo gger.debug ('metrics. getRoles() ');
  1452  
  1453       if (_. isUndefine d(req.app. subsystems .cds)) {
  1454           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1455       }
  1456  
  1457       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1458           if  (error) {
  1459                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1460           }
  1461           re q.logger.d ebug('Metr ics GET ge tRoles cal led');
  1462  
  1463           db Connection .collectio n('roles') .find().to Array(func tion(error , result)  {
  1464                handleTo ArrayResul t(req, res , error, r esult);
  1465           }) ;
  1466       });
  1467   }
  1468  
  1469  
  1470   /**
  1471    * @apiIgn ore Has no t been ful ly scoped  and implem ented
  1472    * @api {p ost} /reso urce/cds/m etrics/rol es Update  Role
  1473    * @apiNam e UpdateRo les
  1474    * @apiGro up Roles
  1475    * @apiDes cription G ets a list  of roles  supported  by this sy stem
  1476    *     HTT P/1.1 400  Bad Reques t
  1477    *     {
  1478    *       " status": " 400"
  1479    *       " error": "A rgument pa ssed in mu st be a si ngle Strin g of 12 by tes or a s tring of 2 4 hex char acters"
  1480    *     }
  1481    * @apiErr orExample  {json} Err or-Respons e:
  1482    *     HTT P/1.1 404  Not Found
  1483    *     {
  1484    *       " status": " 404"
  1485    *       " error": "N ot Found"
  1486    *     }
  1487    * @apiPar amExample
  1488    * {
  1489    *  "statu s": 200,
  1490    *  "data" : [
  1491    *    {
  1492    *      "_ id": "8",
  1493    *      "n ame": "Adm in",
  1494    *      "d escription ": "Admin  has unrest ricted pri vilege"
  1495    *    }
  1496    *  ]
  1497    * }
  1498    */
  1499   function u pdateRoles (req, res)  {
  1500       req.lo gger.debug ('metrics. updateRole s()');
  1501  
  1502       if (_. isUndefine d(req.app. subsystems .cds)) {
  1503           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1504       }
  1505  
  1506       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1507           if  (error) {
  1508                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1509           }
  1510           re q.logger.d ebug('Metr ics GET ge tRoles cal led');
  1511  
  1512           //  TODO: CDS  Invocatio n did not  have an up dateRoles  method, th is method  appears to  insert a  list of ro les instea d.
  1513           //  This will  need to b e tested i f a requir ement for  dashboard  roles emer ges
  1514           va r roles =  req.body;
  1515           if  (roles == = null ||  Object.key s(roles).l ength ===  0) {
  1516                return r es.status( 400).send( {
  1517                    stat us: 400,
  1518                    erro r: message BodyError
  1519                });
  1520           }
  1521  
  1522           db Connection .collectio n('roles') .insert(ro les, funct ion(error,  result) {
  1523                if (erro r) {
  1524                    retu rn res.sta tus(404).s end({
  1525                         status: 40 4,
  1526                         error: err or
  1527                    });
  1528                }
  1529                return r es.status( 201).send( {
  1530                    stat us: 201,
  1531                    data : result.o ps
  1532                });
  1533           }) ;
  1534       });
  1535   }
  1536  
  1537  
  1538   // USER RO LES ...
  1539  
  1540   /**
  1541    * @apiIgn ore Has no t been ful ly scoped  and implem ented
  1542    * @api {g et} /resou rce/cds/me trics/user Roles/:use rId Get Ro les
  1543    * @apiNam e GetUserR oles
  1544    * @apiGro up UserRol es
  1545    * @apiDes cription G ets a list  of roles  associated  to a part icular use r
  1546    * @apiPar am {String } userId T he id of t he type of  metric to  be displa yed
  1547    * @apiErr orExample  {json} Err or-Respons e:
  1548    *     HTT P/1.1 404  Not Found
  1549    *     {
  1550    *       " status": " 404"
  1551    *       " error": "N ot Found"
  1552    *     }
  1553    */
  1554   function g etUserRole s(req, res ) {
  1555       req.lo gger.debug ('metrics. getUserRol es()');
  1556  
  1557       if (_. isUndefine d(req.app. subsystems .cds)) {
  1558           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1559       }
  1560  
  1561       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1562           if  (error) {
  1563                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1564           }
  1565           re q.logger.d ebug('Metr ics GET ge tRoles cal led');
  1566           //  TODO: thi s method w ill also n eed to be  tested / e xamined mo re closely  should re quirements  for user  based role s emerge
  1567  
  1568           va r id = req .param('us erId');
  1569           db Connection .collectio n('userRol es').findO ne({
  1570                userId:  id
  1571           },  function( error, res ult) {
  1572                if (erro r) {
  1573                    retu rn res.sta tus(404).s end({
  1574                         status: 40 4,
  1575                         error: err or
  1576                    });
  1577                }
  1578                if (!res ult) {
  1579                    retu rn res.sta tus(404).s end({
  1580                         status: 40 4,
  1581                         error: not FoundError
  1582                    });
  1583                }
  1584                return r es.status( 200).send( {
  1585                    stat us: 200,
  1586                    data : result
  1587                });
  1588           }) ;
  1589       });
  1590   }
  1591  
  1592  
  1593   /**
  1594    * @apiIgn ore Has no t been ful ly scoped  and implem ented
  1595    * @api {p ost} /reso urce/cds/m etrics/use rRoles Upd ate Roles
  1596    * @apiNam e GetUserR oles
  1597    * @apiGro up UserRol es
  1598    * @apiDes cription U pdates rol es associa ted with a  user
  1599    *     HTT P/1.1 400  Bad Reques t
  1600    *     {
  1601    *       " status": " 400"
  1602    *       " error": "A rgument pa ssed in mu st be a si ngle Strin g of 12 by tes or a s tring of 2 4 hex char acters"
  1603    *     }
  1604    * @apiErr orExample  {json} Err or-Respons e:
  1605    *     HTT P/1.1 404  Not Found
  1606    *     {
  1607    *       " status": " 404"
  1608    *       " error": "N ot Found"
  1609    *     }
  1610    * @apiSuc cess {json } data Jso n object c ontaining  a list of  all roles
  1611    */
  1612   function u pdateUserR oles(req,  res) {
  1613       req.lo gger.debug ('metrics. updateUser Roles()');
  1614  
  1615       if (_. isUndefine d(req.app. subsystems .cds)) {
  1616           re turn res.s tatus(rdk. httpstatus .service_u navailable ).rdkSend( 'CDS metri cs resourc e is unava ilable.');
  1617       }
  1618  
  1619       req.ap p.subsyste ms.cds.get CDSDB(req. logger, me tricDbName , createIn itDefiniti ons(req.lo gger), fun ction(erro r, dbConne ction) {
  1620           if  (error) {
  1621                return r es.status( rdk.httpst atus.servi ce_unavail able).rdkS end('CDS p ersistence  store is  unavailabl e.');
  1622           }
  1623           re q.logger.d ebug('Metr ics GET up dateRoles  called');
  1624  
  1625           //  TODO: thi s method w ill also n eed to be  tested / e xamined mo re closely  should re quirements  for user  based role s emerge
  1626           va r userRole  = req.bod y;
  1627           if  (userRole  === null  || Object. keys(userR ole).lengt h === 0) {
  1628                return r es.status( 400).send( {
  1629                    stat us: 400,
  1630                    erro r: 'Messag e body can not be emp ty and mus t contain  valid JSON '
  1631                });
  1632           }
  1633  
  1634           db Connection .collectio n('userRol es').updat e({
  1635                userId:  userRole.u serId
  1636           },  userRole,  {
  1637                upsert:  true
  1638           },  function( error, res ult) {
  1639                if (erro r) {
  1640                    retu rn res.sta tus(404).s end({
  1641                         status: 40 4,
  1642                         error: err or
  1643                    });
  1644                }
  1645                if (!res ult) {
  1646                    retu rn res.sta tus(404).s end({
  1647                         status: 40 4,
  1648                         error: not FoundError
  1649                    });
  1650                }
  1651                return r es.status( 200).send( {
  1652                    stat us: 200,
  1653                    data : result
  1654                });
  1655           }) ;
  1656       });
  1657   }
  1658  
  1659  
  1660   module.exp orts.creat eInitDefin itions = c reateInitD efinitions ;
  1661   module.exp orts.getMe tricSearch  = getMetr icSearch;
  1662   module.exp orts.getUs erDashBoar ds = getUs erDashBoar ds;
  1663   module.exp orts.getDa shBoard =  getDashBoa rd;
  1664   module.exp orts.creat eDashboard  = createD ashboard;
  1665   module.exp orts.updat eDashboard  = updateD ashboard;
  1666   module.exp orts.delet eDashboard  = deleteD ashboard;
  1667   module.exp orts.getMe tricGroups  = getMetr icGroups;
  1668   module.exp orts.creat eMetricGro up = creat eMetricGro up;
  1669   module.exp orts.updat eMetricGro up = updat eMetricGro up;
  1670   module.exp orts.delet eMetricGro up = delet eMetricGro up;
  1671   module.exp orts.getMe tricDefini tions = ge tMetricDef initions;
  1672   module.exp orts.creat eMetricDef initions =  createMet ricDefinit ions;
  1673   module.exp orts.delet eMetricDef inition =  deleteMetr icDefiniti on;
  1674   module.exp orts.getRo les = getR oles;
  1675   module.exp orts.updat eRoles = u pdateRoles ;
  1676   module.exp orts.getUs erRoles =  getUserRol es;
  1677   module.exp orts.updat eUserRoles  = updateU serRoles;