message: Add logger emitter to solve MaxListenersExceededWarning
diff: @@ -65,6 +65,7 @@ import * as fs from 'fs';
  import * as os from 'os';
  import * as path from 'path';
  import { Writable } from 'stream';
  +import * as EventEmitter from 'events';
  import * as Bunyan from 'bunyan-sfdx-no-dtrace';
  import * as _ from 'lodash';
  import { Global, Mode } from './global';
  @@ -110,13 +111,6 @@ export type FieldValue = string | number | boolean;
  * A logging abstraction powered by {@link https://github.com/cwallsfdc/node-bunyan|Bunyan} that provides both a default
  * logger configuration that will log to `sfdx.log`, and a way to create custom loggers based on the same foundation.
  *
  - * `Logger` construction automatically adds `process` event listeners to `uncaughtException` and `exit` events to
  - * to log fatal errors and clean up open streams, respectively. Because of this, creation of many loggers (for example,
  - * as children of the `root` sfdx logger) can cause Node.js to emit `MaxListenersExceededWarning` warnings. If this
  - * occurs, you can increase the number of acceptable listeners using
  - * {@link https://nodejs.org/api/events.html#events_emitter_setmaxlisteners_n|EventEmitter.setMaxListeners}, as
  - * appropriate to your application.
  - *
  * @example
  * // Gets the root sfdx logger
  * const logger = await Logger.root();
  @@ -215,16 +209,18 @@ export class Logger {
  return level;
  }
  + // Rollup all instance-specific process event listeners together to prevent global `MaxListenersExceededWarning`s.
  + private static readonly lifecycle = (() => {
  + const events = new EventEmitter();
  + events.setMaxListeners(0); // never warn on listener counts
  + process.on('uncaughtException', (err) => events.emit('uncaughtException', err));
  + process.on('exit', () => events.emit('exit'));
  + return events;
  + })();
  +
  // The sfdx root logger singleton
  private static rootLogger: Logger;
  - /**
  - * @ignore
  - */
  - private static shouldUseProcessListeners() {
  - return Global.getEnvironmentMode() !== Mode.TEST;
  - }
  -
  // The actual Bunyan logger
  private bunyan: Bunyan;
  @@ -258,9 +254,9 @@ export class Logger {
  // all SFDX loggers must filter sensitive data
  this.addFilter((...args) => _filter(...args));
  - if (Logger.shouldUseProcessListeners()) {
  - process.on('uncaughtException', this.uncaughtExceptionHandler);
  - process.on('exit', this.exitHandler);
  + if (Global.getEnvironmentMode() !== Mode.TEST) {
  + Logger.lifecycle.on('uncaughtException', this.uncaughtExceptionHandler);
  + Logger.lifecycle.on('exit', this.exitHandler);
  }
  this.trace(`Created '${this.getName()}' logger instance`);
  @@ -454,10 +450,8 @@ export class Logger {
  }
  });
  } finally {
  - if (Logger.shouldUseProcessListeners()) {
  - process.removeListener('uncaughtException', this.uncaughtExceptionHandler);
  - process.removeListener('exit', this.exitHandler);
  - }
  + Logger.lifecycle.removeListener('uncaughtException', this.uncaughtExceptionHandler);
  + Logger.lifecycle.removeListener('exit', this.exitHandler);
  }
  }
  }
  