docs: function createLogger(label) {
  
       /**
        * This will be the logger object that we populate with functions and
        * return to the caller.
        * @typedef Logger
        * @property {Function} setLevel
        * @property {Function} setOutput
        * @property {Function} setFormatFunction
        * @property {Object} levels
        * @property {Function} error
        * @property {Function} warn
        * @property {Function} info
        * @property {Function} verbose
        * @property {Function} debug
        * @property {Function} silly
        * @private
        */
       /*:: type Logger = {
                 setLevel?: function,
                 setOutput?: function,
                 setFormatFunction?: function,
                 levels: Object,
                 error?: function,
                 warn?: function,
                 info?: function,
                 verbose?: function,
                 debug?: function,
                 silly?: function,
        };*/
       const logger /*: Logger */ = {
           levels: LEVELS
       };
       let logLevel = LEVELS.info;
  
  
       //
       // Set the log output
       //
       let outputFunctions;
  
       /**
        * By default the `error` and `warn` levels log output to `console.error`, while all other
        * levels log output to `console.log`.
        * @param {Object} output - An object with 'log' and 'error' functions.
        * @throws {Error}
        * @example
        * log.setOutput({
        *     error: myErrorStream
        *     log: myLogStream
        * });
        */
       function setOutput(output) {
           if (!output ||
               typeof output.log !== 'function') {
               throw Error('logger.setOutput: expect an object as the parameter with "log" and "error" properties.');
           }
           outputFunctions = {
               log: output.log,
               error: (typeof output.error === 'function') ? output.error : output.log
           };
       }
       logger.setOutput = setOutput;
       logger.setOutput(console);
  
  
       //
       // Create the logging functions
       //
  
       function joinMsgArgs(msgArgs) {
           if (!msgArgs) {
               return '';
           }
           return msgArgs.map((arg) => {
              if (arg === null) {
                  return 'null';
              } else if (typeof arg === 'undefined') {
                  return 'undefined';
              } else if (typeof arg === 'string') {
                   return arg;
               } else if (typeof arg === 'object') {
                   try {
                       return JSON.stringify(arg);
                   } catch (ex) {
                       return arg.toString();
                   }
               } else { // boolean, symbol, number, function
                   return arg.toString();
               }
           }).join(' ');
       }
  
  
       /**
        * The default log formatting.  This can overriden by the user by using
        * `log.setFormatFunction()`.
        *
        * @param  {Date} date             - The date the message was created.
        * @param  {string} level          - The current log level.
        * @param  {string} [fnLabel]      - The label that we are logging to.
        * @param  {Array.<*>} [msgArgs] - The multiple message parameters.
        * @returns {string}               - The formatted message to print.
        * @private
        */
       let format = function formatFn(date, level, fnLabel, msgArgs) {
           const l = (fnLabel === null || fnLabel === undefined) ? '' : ` ${fnLabel}`;
           return `${date.toISOString()} ${level}${l}: ${joinMsgArgs(msgArgs)}`;
       };
  
  
       /**
        * Create the log for writing.
        * @param  {string} levelName - The name of the level to log at.
        * @param  {...*} varArgs     - The parameters of the original log.
        * @private
        */
        function writeLog(levelName, varArgs) {       // eslint-disable-line no-unused-vars
  
            const args = [].slice.call(arguments);
            args.splice(0, 1);
  
            const str = format(new Date(), levelName, label, args);
            if (LEVELS[levelName] <= LEVELS.warn) {
                outputFunctions.error(str);
            } else {
                outputFunctions.log(str);
            }
        }
  
  
       /**
        * Override the default format function.  Must supply a function to handle the following
        * parameters (date, level, fnLabel, ...msgArgs).
        * @param {Function} newFormatFunction - The new function to do the formatting of the output.
        * @throws {Error}
        * @example
        * log.setFormatFunction(function (date, level, label, ...msgArgs) {
        *       const l = level.toUpperCase();
        *       const d = date.getTime();
        *       const s = msgArgs.toString();
        *       return `${l} ${d} ${s}`;
        * });
        * log.info('Another info line.');
        *
        * // Output:
        * // stdout: INFO 1489198884388 Another info line.
        */
       function setFormatFunction(newFormatFunction) {
  
           if (typeof newFormatFunction !== 'function') {
               throw Error('logger.setFormatFunction: expect a function as parameter.');
           }
           format = newFormatFunction;
       }
       logger.setFormatFunction = setFormatFunction;
  
  
       //
       // Set the log level
       //
  
       let DEBUG;
       if (typeof process === 'object' && typeof process.env === 'object') {
           DEBUG = process.env.DEBUG;
       }
       if (DEBUG === '*') {
           logLevel = LEVELS.debug;
       } else if (DEBUG === label && label) {
           logLevel = LEVELS.debug;
       }
  
       /**
        * Set the log level of the logger.  Anything equal to or below this level
        * will be output.  The default level is `info`. The available log levels are:
        *    - error
        *    - warn
        *    - info
        *    - verbose
        *    - debug
        *    - silly
        * @param {number} newLogLevel - The new level.
        * @throws {Error}
        *
        * @example
        * log.setLevel(log.levels.error);
        *
        * log.debug('This happened!');
        * log.info('My first info line.');
        * log.warn('You have an object: ', {obj: 'a'});
        * log.error('My second error line.');
        *
        * // Output:
        * // stderr: 2017-03-10T09:44:06.394Z error: My second error line.
        */
       function setLevel(newLogLevel) {
           if (isNaN(newLogLevel) || newLogLevel < 0 || newLogLevel > LEVELS.silly) {
               throw Error(`setLevel(): invalid level: ${newLogLevel}`);
           }
  
           logLevel = newLogLevel;
           Object.keys(LEVELS).forEach((levelName, levelIndex) => {
               if (levelIndex <= logLevel) {
                   logger[levelName] = function logit() {
                       const msgArgs = [levelName].concat([].slice.call(arguments));
                       writeLog.apply(writeLog, msgArgs);
                   };
               } else {
                   logger[levelName] = () => {};
               }
  
           });
       }
       setLevel(logLevel);
       logger.setLevel = setLevel;
  
       return logger;
  
  }