<commit_before>// @export Log
Log = function () {
  return Log.info.apply(this, arguments);
};

var intercept = 0;
var interceptedLines = [];

// Intercept the next 'count' calls to a Log function. The actual
// lines printed to the console can be cleared and read by calling
// Log._intercepted().
Log._intercept = function (count) {
  intercept += count;
};
Log._intercepted = function () {
  var lines = interceptedLines;
  interceptedLines = [];
  return lines;
};

// XXX file, line, package
var RESTRICTED_KEYS = ['time', 'timeInexact', 'level'];

_.each(['debug', 'info', 'warn', 'error'], function (level) {
  Log[level] = function (arg) {
    var intercepted;
    if (intercept) {
      intercept--;
      intercepted = true;
    }

    var obj = (typeof arg === 'string') ? {message: arg} : arg;

    _.each(RESTRICTED_KEYS, function (key) {
      if (obj[key])
        throw new Error("Can't set '" + key + "' in log message");
    });

    obj.time = new Date();
    obj.level = level;
    // XXX file, line, package

    // XXX allow you to enable 'debug', probably per-package
    if (level === 'debug')
      return;

    if (intercepted) {
      interceptedLines.push(EJSON.stringify(obj));
    } else if (Meteor.isServer) {
      console.log(EJSON.stringify(obj));
    } else {
      // XXX Some levels should be probably be sent to the server
      // XXX Uses of Meteor._debug should probably be replaced by Log.debug or
      //     Log.info, and we should have another name for "do your best to
      //     call call console.log".
      Meteor._debug(Log.format(obj));
    }
  };
});

// tries to parse line as EJSON. returns object if parse is successful, or null if not
Log.parse = function (line) {
  var obj = null;
  if (line && line[0] === '{') { // might be json generated from calling 'Log'
    try { obj = EJSON.parse(line); } catch (e) {}
  }
  return obj;
};

var LEVEL_COLORS = {
  debug: 'blue',
  info: 'cyan',
  warn: 'yellow',
  error: 'red'
};

// formats a log object into colored human and machine-readable text
Log.format = function (obj, options) {
  options = options || {};

  var time = obj.time;<commit_msg>Better client logs<commit_after>// @export Log
Log = function () {
  return Log.info.apply(this, arguments);
};

var intercept = 0;
var interceptedLines = [];

// Intercept the next 'count' calls to a Log function. The actual
// lines printed to the console can be cleared and read by calling
// Log._intercepted().
Log._intercept = function (count) {
  intercept += count;
};
Log._intercepted = function () {
  var lines = interceptedLines;
  interceptedLines = [];
  return lines;
};

var LEVEL_COLORS = {
  debug: 'blue',
  info: 'cyan',
  warn: 'yellow',
  error: 'red'
};

// XXX file, line, package
var RESTRICTED_KEYS = ['time', 'timeInexact', 'level'];

var logOnClient = function (obj) {
  var str = Log.format(obj);

  // XXX Some levels should be probably be sent to the server
  var level = obj.level;

  if ((typeof console !== 'undefined') && console[level]) {
    console[level](str);
  } else {
    // XXX Uses of Meteor._debug should probably be replaced by Log.debug or
    //     Log.info, and we should have another name for "do your best to
    //     call call console.log".
    Meteor._debug(str);
  }
};

_.each(['debug', 'info', 'warn', 'error'], function (level) {
  Log[level] = function (arg) {
    var intercepted;
    if (intercept) {
      intercept--;
      intercepted = true;
    }

    var obj = (typeof arg === 'string') ? {message: arg} : arg;

    _.each(RESTRICTED_KEYS, function (key) {
      if (obj[key])
        throw new Error("Can't set '" + key + "' in log message");
    });

    obj.time = new Date();
    obj.level = level;
    // XXX file, line, package

    // XXX allow you to enable 'debug', probably per-package
    if (level === 'debug')
      return;

    if (intercepted) {
      interceptedLines.push(EJSON.stringify(obj));
    } else if (Meteor.isServer) {
      console.log(EJSON.stringify(obj));
    } else {
      logOnClient(obj);
    }
  };
});

// tries to parse line as EJSON. returns object if parse is successful, or null if not
Log.parse = function (line) {
  var obj = null;
  if (line && line[0] === '{') { // might be json generated from calling 'Log'
    try { obj = EJSON.parse(line); } catch (e) {}
  }
  return obj;
};

// formats a log object into colored human and machine-readable text
Log.format = function (obj, options) {
  obj = EJSON.clone(obj); // don't mutate the argument
  options = options || {};

  var time = obj.time;
{'fraction_non_alphanumeric': 0.1455182993644532, 'fraction_numerical': 0.0008766162612316459, 'mean_word_length': 2.851476793248945, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3800178', 'n_tokens_mistral': 1479, 'n_tokens_neox': 1429, 'n_words': 487}