rulesChecker.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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. var offenders = [];
  21. // Take DOMqueriesAvoidable's offenders from DOMqueriesDuplicated, for example.
  22. if (policy.takeOffendersFrom) {
  23. var fromList = policy.takeOffendersFrom;
  24. // takeOffendersFrom option can be a string or an array of strings.
  25. if (typeof fromList === 'string') {
  26. fromList = [fromList];
  27. }
  28. fromList.forEach(function(from) {
  29. if (data.toolsResults[policy.tool] &&
  30. data.toolsResults[policy.tool].offenders &&
  31. data.toolsResults[policy.tool].offenders[from]) {
  32. offenders = offenders.concat(data.toolsResults[policy.tool].offenders[from]);
  33. }
  34. });
  35. data.toolsResults[policy.tool].offenders[metricName] = offenders;
  36. } else if (data.toolsResults[policy.tool] &&
  37. data.toolsResults[policy.tool].offenders &&
  38. data.toolsResults[policy.tool].offenders[metricName]) {
  39. offenders = data.toolsResults[policy.tool].offenders[metricName];
  40. }
  41. // It is possible to declare a transformation function for the offenders.
  42. // The function should take an array of strings as single parameter and return a string.
  43. if (policy.offendersTransformFn) {
  44. rule.offendersCount = offenders.length;
  45. try {
  46. offenders = policy.offendersTransformFn(offenders);
  47. } catch(err) {
  48. debug('Error while transforming offenders for %s', metricName);
  49. debug(err);
  50. }
  51. delete rule.policy.offendersTransformFn;
  52. }
  53. if (offenders && offenders.length > 0) {
  54. rule.offenders = offenders;
  55. }
  56. rule.bad = rule.value > policy.isOkThreshold;
  57. rule.abnormal = policy.isAbnormalThreshold && rule.value >= policy.isAbnormalThreshold;
  58. // A value between 0 (bad) and 100 (very good).
  59. var score = (policy.isBadThreshold - rule.value) * 100 / (policy.isBadThreshold - policy.isOkThreshold);
  60. rule.score = Math.min(Math.max(Math.round(score), 0), 100);
  61. // A value between 0 (abnormal) and negative-infinity (your website is a blackhole)
  62. var abnormalityScore = (policy.isAbnormalThreshold - rule.value) * 100 / (policy.isAbnormalThreshold - policy.isOkThreshold);
  63. rule.abnormalityScore = Math.min(Math.round(abnormalityScore), 0);
  64. results[metricName] = rule;
  65. debug('Metric %s calculated. Score: %d', metricName, rule.score);
  66. } else if (policy.scoreFn) {
  67. debug('Custom score function for %s', metricName);
  68. // Custom score function
  69. rule = policy.scoreFn(data);
  70. // Check returned values (if the result is null, just don't save)
  71. if (rule) {
  72. rule.policy = {
  73. label: policy.label,
  74. message: policy.message
  75. };
  76. results[metricName] = rule;
  77. debug('Metric %s calculated. Score: %d', metricName, rule.score);
  78. } else {
  79. debug('Metric %s is null. Ignored.', metricName);
  80. }
  81. } else {
  82. debug('Metric %s not found for tool %s', metricName, policy.tool);
  83. }
  84. }
  85. debug('Rules checking finished');
  86. return results;
  87. };
  88. };
  89. module.exports = new RulesChecker();