whole_func_string: function(metric, records) {
    var returnValue = {message: 'no stats available', name: metric.displayName};
    if (records && records.length > 0) {
      returnValue = _.chain(records).map(function(recordStr) {
        return JSON.parse(recordStr);
      }).groupBy(function(record) {
        return record.tags[metric.groupByTag];
      }).reduce(function(reduced, groupRecords, groupKey) {
        groupRecords = _.sortBy(groupRecords, 'ts');
        var processedData = _.reduce(groupRecords, function(memo, groupRecord) {
          var value = groupRecord.fields[metric.valueField];
          memo.current = value;
          memo.numberOfRecords++;
          memo.total += value;
          memo.max = Math.max(value, memo.max);
          memo.min = Math.min(value, memo.min);
          memo.from = Math.min(groupRecord.ts, memo.from);
          memo.end = Math.max(groupRecord.ts, memo.end);
          return memo;
        }, {max: 0, min: MAX_NUMBER, current: 0, numberOfRecords: 0, total: 0, from: MAX_NUMBER, end: 0});
        reduced[groupKey] = {
          current: metric.dataFormatter(processedData.current),
          max: metric.dataFormatter(processedData.max),
          min: metric.dataFormatter(processedData.min),
          average: metric.dataFormatter(processedData.total / processedData.numberOfRecords),
          numberOfRecords: processedData.numberOfRecords,
          from: new Date(processedData.from).toISOString(),
          end: new Date(processedData.end).toISOString()
        };
        return reduced;
      }, {}).value();
    }
    return returnValue;
  }
func_code_string: function(metric, records) {
    var returnValue = {message: 'no stats available', name: metric.displayName};
    if (records && records.length > 0) {
      returnValue = _.chain(records).map(function(recordStr) {
        return JSON.parse(recordStr);
      }).groupBy(function(record) {
        return record.tags[metric.groupByTag];
      }).reduce(function(reduced, groupRecords, groupKey) {
        groupRecords = _.sortBy(groupRecords, 'ts');
        var processedData = _.reduce(groupRecords, function(memo, groupRecord) {
          var value = groupRecord.fields[metric.valueField];
          memo.current = value;
          memo.numberOfRecords++;
          memo.total += value;
          memo.max = Math.max(value, memo.max);
          memo.min = Math.min(value, memo.min);
          memo.from = Math.min(groupRecord.ts, memo.from);
          memo.end = Math.max(groupRecord.ts, memo.end);
          return memo;
        }, {max: 0, min: MAX_NUMBER, current: 0, numberOfRecords: 0, total: 0, from: MAX_NUMBER, end: 0});
        reduced[groupKey] = {
          current: metric.dataFormatter(processedData.current),
          max: metric.dataFormatter(processedData.max),
          min: metric.dataFormatter(processedData.min),
          average: metric.dataFormatter(processedData.total / processedData.numberOfRecords),
          numberOfRecords: processedData.numberOfRecords,
          from: new Date(processedData.from).toISOString(),
          end: new Date(processedData.end).toISOString()
        };
        return reduced;
      }, {}).value();
    }
    return returnValue;
  }
func_documentation_string: Compute the max, min, current, average values from the records
  @param {Object} metric some meta data about the metric
  @param {Array} records