• Jump To … +
    ClientController.js ClientRequest.js ExpressServerRequest.js ReactServerAgent.js Cache.js Plugins.js Request.js handlePage.js loggingClient.js ClientRequestSpec.js NormalValuesPage.js NullValuePromisesPage.js NullValuesPage.js reactMiddlewareSpec.js client.js common.js History.js RootContainer.js RootElement.js TheFold.js config.js constants.js Navigator.js RequestContext.js logging.js client.js common.js response.js server.js stats.js renderMiddleware.js server.js ClientCssHelper.js DebugUtil.js PageUtil.js RequestLocalStorage.js StringEscapeUtil.js bundleNameUtil.js navigateTo.js
  • stats.js

  • ¶

    This is a subjective classification of response times into three performance buckets: “fast”, “fine” and “slow”.

    If you’re timing something for which these default thresholds don’t make sense, you can override them either in your call to getLogger or in your call to time or timer itself.

    Example:

    var logger = require(‘./logging’).getLogger(LOGGER({ timing: { fast: 25, fine: 100 } }));

    logger.time(“something”, millseconds, { fast: 50 });

    var timer = logger.timer(“somethingElse”, { fine: 250 });

    var DEFAULT_TIME_THRESHOLDS = {
    	fast: 100,
    	fine: 250,
    }
  • ¶

    This is a subjective classification of gauge values into three buckets: “lo”, “hi” and “ok”.

    If you’re tracking something for which these default thresholds don’t make sense, you can override them in your call to getLogger or in your call to gauge iteself.

    Example:

    var logger = require(‘./logging’).getLogger(LOGGER({ gauge: { lo: 10000, hi: 100000 } }));

    logger.gauge(“something”, value, { hi: 1000000 });

    var DEFAULT_GAUGE_THRESHOLDS = {
    	lo: -1,
    	hi: 101,
    }
    
    var loggers = {};
  • ¶

    Each logger actually has some secondary loggers attached to it for stats. This helper wires them up.

    function wrapLogger(getLoggerForConfig, opts) {
    
    	var mainLogger    = getLoggerForConfig('main',  opts)
    		,   timeLogger    = getLoggerForConfig('time',  opts)
    		,   gaugeLogger   = getLoggerForConfig('gauge', opts)
    		,   classifyTime  = makeTimeClassifier(opts)
    		,   classifyGauge = makeGaugeClassifier(opts)
  • ¶

    These are methods that are exposed on the primary logger. They just dispatch to appropriate log levels on secondary loggers.

    	mainLogger.time  = (token, ms,  opts) => timeLogger [classifyTime (ms,  opts)](token, {ms });
    	mainLogger.gauge = (token, val, opts) => gaugeLogger[classifyGauge(val, opts)](token, {val});
  • ¶

    Expose these.

    	mainLogger.timeLogger  = timeLogger;
    	mainLogger.gaugeLogger = gaugeLogger;
  • ¶

    This is just a convenience wrapper around the time method.

    	mainLogger.timer = (token, opts) => {
    
    		var t0 = new Date // For use by `timer.stop`.
    			,   tt = t0       // For use by `timer.tick`.
    			,   nt = 0        // Number of times `tick` has been called.
    			,   ct = 0        // For storing return values.
    
    		return {
  • ¶

    The stop method logs the total elapsed time since timer creation.

    			stop: () => (mainLogger.time(token, ct = new Date - t0, opts), ct),
  • ¶

    The tick method logs the time elapsed since the last call to tick (or since timer creation). A tick may be named. If a name is not passed in the number of times tick has been called on this timer will be used. Don’t mix named and un-named ticks.

    			tick: (name) => {
    				var now = new Date
    
    				name || (name = `tick_${nt++}`);
    
    				mainLogger.time(`${token}.${name}`, ct=now-tt, opts);
    
    				tt = now;
    
    				return ct
    			},
    		};
    	}
    
    	return mainLogger;
    }
  • ¶

    This is used for classifying time and gauge values.

    function makeThresholdsSieve(options, defaults) {
    
    	if (!options) options = {};
  • ¶

    Pre-apply defaults.

    	Object.keys(defaults).forEach(key => options[key] || (options[key] = defaults[key]));
    
    	return (key, overrides) => {
    		if (overrides && overrides[key] !== void 0) return overrides[key];
    		return options[key];
    	}
    }
    
    function makeTimeClassifier(opts) {
    	var thresholds = makeThresholdsSieve(opts.timing, DEFAULT_TIME_THRESHOLDS);
    	var fast = thresholds('fast');
    	var fine = thresholds('fine');
    	return (ms, o) => {
    		if (o) {
    			if      (ms <= thresholds('fast', o)) return 'fast';
    			else if (ms <= thresholds('fine', o)) return 'fine';
    			else                                  return 'slow';
    		} else {
    			if      (ms <= fast) return 'fast';
    			else if (ms <= fine) return 'fine';
    			else                 return 'slow';
    		}
    	}
    }
    
    function makeGaugeClassifier(opts) {
    	var thresholds = makeThresholdsSieve(opts.gauge, DEFAULT_GAUGE_THRESHOLDS);
    	var lo = thresholds('lo');
    	var hi = thresholds('hi');
    	return (val, o) => {
    		if (o) {
    			if      (val <= thresholds('lo', o)) return 'lo';
    			else if (val >= thresholds('hi', o)) return 'hi';
    			else                                 return 'ok';
    		} else {
    			if      (val <= lo) return 'lo';
    			else if (val >= hi) return 'hi';
    			else                return 'ok';
    		}
    	}
    
    }
    
    function getCombinedLogger(getLoggerForConfig, opts) {
    	return loggers[opts.name] || (loggers[opts.name] = wrapLogger(getLoggerForConfig, opts));
    }
    
    module.exports = { getCombinedLogger };