github.com/nsqio/nsq@v1.3.0/nsqadmin/static/js/lib/handlebars_helpers.js (about)

     1  var $ = require('jquery');
     2  var _ = require('underscore');
     3  var Handlebars = require('hbsfy/runtime');
     4  
     5  var AppState = require('../app_state');
     6  
     7  var formatStatsdKey = function(metricType, key) {
     8      var fullKey = key;
     9      var fmt;
    10  
    11      if (metricType === 'counter') {
    12          fmt = AppState.get('STATSD_COUNTER_FORMAT');
    13          fullKey = fmt.replace(/%s/g, key);
    14      } else if (metricType === 'gauge') {
    15          fmt = AppState.get('STATSD_GAUGE_FORMAT');
    16          fullKey = fmt.replace(/%s/g, key);
    17      }
    18  
    19      return fullKey;
    20  };
    21  
    22  var statsdPrefix = function(host) {
    23      var prefix = AppState.get('STATSD_PREFIX');
    24      var statsdHostKey = host.replace(/[\.:]/g, '_');
    25      prefix = prefix.replace(/%s/g, statsdHostKey);
    26      if (prefix.substring(prefix.length, 1) !== '.') {
    27          prefix += '.';
    28      }
    29      return prefix;
    30  };
    31  
    32  /* eslint-disable key-spacing */
    33  var metricType = function(key) {
    34      return {
    35          'depth':                  'gauge',
    36          'in_flight_count':        'gauge',
    37          'deferred_count':         'gauge',
    38          'requeue_count':          'counter',
    39          'timeout_count':          'counter',
    40          'message_count':          'counter',
    41          'clients':                'gauge',
    42          '*_bytes':                'gauge',
    43          'gc_pause_*':             'gauge',
    44          'gc_runs':                'counter',
    45          'heap_objects':           'gauge',
    46          'e2e_processing_latency': 'gauge'
    47      }[key];
    48  };
    49  /* eslint-enable key-spacing */
    50  
    51  var genColorList = function(typ, key) {
    52      if (typ === 'topic' || typ === 'channel') {
    53          if (key === 'depth' || key === 'deferred_count') {
    54              return 'red';
    55          }
    56      } else if (typ === 'node') {
    57          return 'red,green,blue,purple';
    58      } else if (typ === 'counter') {
    59          return 'green';
    60      }
    61      return 'blue';
    62  };
    63  
    64  // sanitizeGraphiteKey removes special characters from a graphite key
    65  // this matches behavior of bitly/statsdaemon
    66  // eslint-disable-next-line max-len
    67  // https://github.com/bitly/statsdaemon/blob/fc46d9cfe29b674a0c8abc723afaa9370430cdcd/statsdaemon.go#L64-L88
    68  var sanitizeGraphiteKey = function(s) {
    69      return s.replaceAll(' ', '_').replaceAll('/', '-').replaceAll(/[^a-zA-Z0-9-_.]/g, '');
    70  };
    71  
    72  var genTargets = function(typ, node, ns1, ns2, key) {
    73      var targets = [];
    74      var prefix = statsdPrefix(node ? node : '*');
    75      var fullKey;
    76      var target;
    77      if (typ === 'topic') {
    78          fullKey = formatStatsdKey(metricType(key),
    79              prefix + 'topic.' + sanitizeGraphiteKey(ns1) + '.' + key);
    80          targets.push('sumSeries(' + fullKey + ')');
    81      } else if (typ === 'channel') {
    82          fullKey = formatStatsdKey(metricType(key),
    83              prefix + 'topic.' + sanitizeGraphiteKey(ns1) + '.channel.' +
    84              sanitizeGraphiteKey(ns2) + '.' + key);
    85          targets.push('sumSeries(' + fullKey + ')');
    86      } else if (typ === 'node') {
    87          target = prefix + 'mem.' + key;
    88          if (key === 'gc_runs') {
    89              target = 'movingAverage(' + target + ',45)';
    90          }
    91          targets.push(formatStatsdKey(metricType(key), target));
    92      } else if (typ === 'e2e') {
    93          targets = _.map(ns1['percentiles'], function(p) {
    94              var t;
    95              if (ns1['channel'] !== '') {
    96                  t = prefix + 'topic.' + ns1['topic'] + '.channel.' + ns1['channel'] + '.' +
    97                      key + '_' + (p['quantile'] * 100);
    98              } else {
    99                  t = prefix + 'topic.' + ns1['topic'] + '.' + key + '_' + (p['quantile'] * 100);
   100              }
   101              if (node === '*') {
   102                  t = 'averageSeries(' + t + ')';
   103              }
   104              return 'scale(' + formatStatsdKey(metricType(key), t) + ',0.000001)';
   105          });
   106      } else if (typ === 'counter') {
   107          fullKey = formatStatsdKey(metricType(key), prefix + 'topic.*.channel.*.' + key);
   108          targets.push('sumSeries(' + fullKey + ')');
   109      }
   110      return targets;
   111  };
   112  
   113  Handlebars.registerHelper('default', function(x, defaultValue) {
   114      return x ? x : defaultValue;
   115  });
   116  
   117  Handlebars.registerHelper('ifeq', function(a, b, options) {
   118      return (a === b) ? options.fn(this) : options.inverse(this);
   119  });
   120  
   121  Handlebars.registerHelper('unlesseq', function(a, b, options) {
   122      return (a !== b) ? options.fn(this) : options.inverse(this);
   123  });
   124  
   125  Handlebars.registerHelper('ifgteq', function(a, b, options) {
   126      return (a >= b) ? options.fn(this) : options.inverse(this);
   127  });
   128  
   129  Handlebars.registerHelper('iflteq', function(a, b, options) {
   130      return (a <= b) ? options.fn(this) : options.inverse(this);
   131  });
   132  
   133  Handlebars.registerHelper('length', function(xs) {
   134      return xs.length;
   135  });
   136  
   137  Handlebars.registerHelper('lowercase', function(s) {
   138      return s.toLowerCase();
   139  });
   140  
   141  Handlebars.registerHelper('uppercase', function(s) {
   142      return s.toUpperCase();
   143  });
   144  
   145  // this helper is inclusive of the top number
   146  Handlebars.registerHelper('for', function(from, to, incr, block) {
   147      var accum = '';
   148      for (var i = from; i <= to; i += incr) {
   149          accum += block.fn(i);
   150      }
   151      return accum;
   152  });
   153  
   154  // Logical operators as helper functions, which can be useful when used within
   155  // an `if` or `unless` block via the new helper composition syntax, like so:
   156  //
   157  //     {{#if (or step.unlocked step.is_finished)}}
   158  //       Step is unlocked or finished!
   159  //     {{/if}}
   160  //
   161  // Any number of arguments may be given to either helper. NOTE: _.initial() is
   162  // used below because every helper takes an options hash as its last argument.
   163  Handlebars.registerHelper('and', function() {
   164      return _.all(_.initial(arguments));
   165  });
   166  
   167  Handlebars.registerHelper('or', function() {
   168      return _.any(_.initial(arguments));
   169  });
   170  
   171  Handlebars.registerHelper('eq', function(a, b) {
   172      return a === b;
   173  });
   174  
   175  Handlebars.registerHelper('neq', function(a, b) {
   176      return a !== b;
   177  });
   178  
   179  Handlebars.registerHelper('urlencode', function(a) {
   180      return encodeURIComponent(a);
   181  });
   182  
   183  Handlebars.registerHelper('floatToPercent', function(f) {
   184      return Math.floor(f * 100);
   185  });
   186  
   187  Handlebars.registerHelper('percSuffix', function(f) {
   188      var v = Math.floor(f * 100) % 10;
   189      if (v === 1) {
   190          return 'st';
   191      } else if (v === 2) {
   192          return 'nd';
   193      } else if (v === 3) {
   194          return 'rd';
   195      }
   196      return 'th';
   197  });
   198  
   199  Handlebars.registerHelper('commafy', function(n) {
   200      n = n || 0;
   201      return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
   202  });
   203  
   204  function round(num, places) {
   205      var multiplier = Math.pow(10, places);
   206      return Math.round(num * multiplier) / multiplier;
   207  }
   208  
   209  Handlebars.registerHelper('nanotohuman', function(n) {
   210      var s = '';
   211      var v;
   212      if (n >= 3600000000000) {
   213          v = Math.floor(n / 3600000000000);
   214          n = n % 3600000000000;
   215          s = v + 'h';
   216      }
   217      if (n >= 60000000000) {
   218          v = Math.floor(n / 60000000000);
   219          n = n % 60000000000;
   220          s += v + 'm';
   221      }
   222      if (n >= 1000000000) {
   223          n = round(n / 1000000000, 2);
   224          s += n + 's';
   225      } else if (n >= 1000000) {
   226          n = round(n / 1000000, 2);
   227          s += n + 'ms';
   228      } else if (n >= 1000) {
   229          n = round(n / 1000, 2);
   230          s += n + 'us';
   231      } else {
   232          s = n + 'ns';
   233      }
   234      return s;
   235  });
   236  
   237  Handlebars.registerHelper('sparkline', function(typ, node, ns1, ns2, key) {
   238      var q = {
   239          'colorList': genColorList(typ, key),
   240          'height': '20',
   241          'width': '120',
   242          'hideGrid': 'true',
   243          'hideLegend': 'true',
   244          'hideAxes': 'true',
   245          'bgcolor': 'ff000000', // transparent
   246          'fgcolor': 'black',
   247          'margin': '0',
   248          'yMin': '0',
   249          'lineMode': 'connected',
   250          'drawNullAsZero': 'false',
   251          'from': '-' + AppState.get('graph_interval'),
   252          'until': '-1min'
   253      };
   254  
   255      var interval = AppState.get('STATSD_INTERVAL') + 'sec';
   256      q['target'] = _.map(genTargets(typ, node, ns1, ns2, key), function(t) {
   257          return 'summarize(' + t + ',"' + interval + '","avg")';
   258      });
   259  
   260      return AppState.get('GRAPHITE_URL') + '/render?' + $.param(q);
   261  });
   262  
   263  Handlebars.registerHelper('large_graph', function(typ, node, ns1, ns2, key) {
   264      var q = {
   265          'colorList': genColorList(typ, key),
   266          'height': '450',
   267          'width': '800',
   268          'bgcolor': 'ff000000', // transparent
   269          'fgcolor': '999999',
   270          'yMin': '0',
   271          'lineMode': 'connected',
   272          'drawNullAsZero': 'false',
   273          'from': '-' + AppState.get('graph_interval'),
   274          'until': '-1min'
   275      };
   276  
   277      var interval = AppState.get('STATSD_INTERVAL') + 'sec';
   278      q['target'] = _.map(genTargets(typ, node, ns1, ns2, key), function(t) {
   279          if (metricType(key) === 'counter') {
   280              var scale = 1 / AppState.get('STATSD_INTERVAL');
   281              t = 'scale(' + t + ',' + scale + ')';
   282          }
   283          return 'summarize(' + t + ',"' + interval + '","avg")';
   284      });
   285  
   286      return AppState.get('GRAPHITE_URL') + '/render?' + $.param(q);
   287  });
   288  
   289  Handlebars.registerHelper('rate', function(typ, node, ns1, ns2) {
   290      return genTargets(typ, node, ns1, ns2, 'message_count')[0];
   291  });
   292  
   293  Handlebars.registerPartial('error', require('../views/error.hbs'));
   294  Handlebars.registerPartial('warning', require('../views/warning.hbs'));
   295  
   296  Handlebars.registerHelper('basePath', function(p) {
   297      return AppState.basePath(p);
   298  });