rulesChecker.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. var extend = require('util')._extend;
  2. var debug = require('debug')('ylt:ruleschecker');
  3. var RulesChecker = function() {
  4. 'use strict';
  5. this.check = function(data, policies) {
  6. /*jshint loopfunc:true */
  7. var results = {};
  8. debug('Starting checking rules');
  9. for (var metricName in policies) {
  10. var policy = policies[metricName];
  11. var rule;
  12. if (policy.tool &&
  13. data.toolsResults[policy.tool] &&
  14. data.toolsResults[policy.tool].metrics &&
  15. (data.toolsResults[policy.tool].metrics[metricName] || data.toolsResults[policy.tool].metrics[metricName] === 0)) {
  16. rule = {
  17. value: data.toolsResults[policy.tool].metrics[metricName],
  18. policy: extend({}, policy) // Clone object policy instead of reference
  19. };
  20. // Deal with offenders
  21. if (policy.hasOffenders) {
  22. var offenders = [];
  23. // Take DOMqueriesAvoidable's offenders from DOMqueriesDuplicated, for example.
  24. if (policy.takeOffendersFrom) {
  25. var fromList = policy.takeOffendersFrom;
  26. // takeOffendersFrom option can be a string or an array of strings.
  27. if (typeof fromList === 'string') {
  28. fromList = [fromList];
  29. }
  30. fromList.forEach(function(from) {
  31. if (data.toolsResults[policy.tool] &&
  32. data.toolsResults[policy.tool].offenders &&
  33. data.toolsResults[policy.tool].offenders[from]) {
  34. offenders = offenders.concat(data.toolsResults[policy.tool].offenders[from]);
  35. }
  36. });
  37. data.toolsResults[policy.tool].offenders[metricName] = offenders;
  38. } else if (data.toolsResults[policy.tool] &&
  39. data.toolsResults[policy.tool].offenders &&
  40. data.toolsResults[policy.tool].offenders[metricName]) {
  41. offenders = data.toolsResults[policy.tool].offenders[metricName];
  42. }
  43. var offendersObj = {};
  44. // It is possible to declare a transformation function for the offenders.
  45. // The function should take an array of strings as single parameter and return a string.
  46. if (policy.offendersTransformFn) {
  47. try {
  48. offendersObj = policy.offendersTransformFn(offenders, rule);
  49. } catch(err) {
  50. debug('Error while transforming offenders for %s', metricName);
  51. debug(err);
  52. }
  53. delete rule.policy.offendersTransformFn;
  54. } else {
  55. offendersObj = {
  56. count: offenders.length,
  57. list: offenders
  58. };
  59. }
  60. rule.offendersObj = offendersObj;
  61. }
  62. rule.bad = rule.value > policy.isOkThreshold;
  63. rule.abnormal = policy.isAbnormalThreshold && rule.value >= policy.isAbnormalThreshold;
  64. // A value between 0 (bad) and 100 (very good).
  65. var score = (policy.isBadThreshold - rule.value) * 100 / (policy.isBadThreshold - policy.isOkThreshold);
  66. rule.score = Math.min(Math.max(Math.round(score), 0), 100);
  67. // A value between 0 (abnormal) and negative-infinity (your website is a blackhole)
  68. var abnormalityScore = (policy.isAbnormalThreshold - rule.value) * 100 / (policy.isAbnormalThreshold - policy.isOkThreshold);
  69. rule.abnormalityScore = Math.min(Math.round(abnormalityScore), 0);
  70. results[metricName] = rule;
  71. debug('Metric %s calculated. Score: %d', metricName, rule.score);
  72. } else if (policy.scoreFn) {
  73. debug('Custom score function for %s', metricName);
  74. // Custom score function
  75. rule = policy.scoreFn(data);
  76. // Check returned values (if the result is null, just don't save)
  77. if (rule) {
  78. rule.policy = {
  79. label: policy.label,
  80. message: policy.message,
  81. hasOffenders: policy.hasOffenders || false
  82. };
  83. results[metricName] = rule;
  84. debug('Metric %s calculated. Score: %d', metricName, rule.score);
  85. } else {
  86. debug('Metric %s is null. Ignored.', metricName);
  87. }
  88. } else {
  89. debug('Metric %s not found for tool %s', metricName, policy.tool);
  90. }
  91. }
  92. debug('Rules checking finished');
  93. return results;
  94. };
  95. };
  96. module.exports = new RulesChecker();