async function execWithRetriesAndLogs(bin, options = {}) {
  const {
    retries = 9,
    interval = 1000,
    backoff,
    prefix = null,
    args = null,
    timeout,
    statusLogs = {},
    verbosity = 'normal',
    maxBuffer,
  } = options;

  const trackingId = execsCounter.inc();
  const cmd = _composeCommand(bin, prefix, args);
  const logger = rootLogger.child({ fn: 'execWithRetriesAndLogs', cmd, trackingId });
  const logLevelSuccess = (verbosity === 'high' ? 'debug' : 'trace');
  const logLevelFail = (verbosity === 'low' ? 'debug' : 'error');

  let result;
  try {
    logger.debug({ event: 'EXEC_CMD' }, `${cmd}`);

    await retry({ retries, interval, backoff }, async (tryNumber, lastError) => {
      if (statusLogs.trying) {
        _logExecTrying(logger, statusLogs.trying, tryNumber, lastError);
      } else if (statusLogs.retrying) {
        _logExecRetrying(logger, cmd, tryNumber, lastError);
      }
      result = await exec(cmd, _.omitBy({ timeout, maxBuffer }, _.isUndefined));
    });
  } catch (err) {
    const failReason = err.code == null && timeout > 0
      ? `timeout = ${timeout}ms`
      : `error = ${err} (code=${err.code})`;
    _logExecFail(logger, logLevelFail, cmd, err, failReason);
    throw err;
  }

  if (result === undefined) {
    logger.error({ event: 'EXEC_UNDEFINED' }, `command returned undefined`);
    throw new DetoxRuntimeError(`command ${cmd} returned undefined`);
  }

  _logExecOutput(logger, logLevelSuccess, result);
  _logExecSuccess(logger, logLevelSuccess, result, statusLogs.successful);

  if (typeof result.stdout === 'string') {
    result.stdout = result.stdout.replace(/\r\n/g, '\n');
  }

  if (typeof result.stderr === 'string') {
    result.stderr = result.stderr.replace(/\r\n/g, '\n');
  }

  return result;
}
Executes a command with retries and logs
@param {*} bin - command to execute
@param {*} options - options
@returns {Promise<import('promisify-child-process').Output>}