function computeAndLogIssueResponseStats(label, issues) {
  /** @param {AugmentedGitHubIssue} issue @return {(e: AugmentedGitHubIssue['events'][0]) => boolean} */
  const isEventResponse = issue => e => {
    const isHumanResponse =
      RESPONSE_LOGINS.has(e.actor.login) &&
      RESPONSE_EVENTS.has(e.event) &&
      e.actor.login !== issue.user.login;
    const isBotClose = e.event === 'closed' && e.actor.login === 'devtools-bot';
    return isHumanResponse || isBotClose;
  };
  /** @param {AugmentedGitHubIssue} issue @return {(c: AugmentedGitHubIssue['comments'][0]) => boolean} */
  const isCommentResponse = issue => c =>
    RESPONSE_LOGINS.has(c.user.login) && c.user.login !== issue.user.login;
  const withResponse = issues.filter(
    i => i.events.some(isEventResponse(i)) || i.comments.some(isCommentResponse(i))
  );

  const firstResponses = withResponse
    .map(issue => {
      const labelResponse = issue.events.find(isEventResponse(issue));
      const labelResponseTs =
        (labelResponse && new Date(labelResponse.created_at).getTime()) || Infinity;
      const commentResponse = issue.comments.find(isCommentResponse(issue));
      const commentResponseTs =
        (commentResponse && new Date(commentResponse.created_at).getTime()) || Infinity;

      let firstResponse = {login: '', created_at: ''};
      if (labelResponse && labelResponseTs < commentResponseTs) {
        firstResponse = {
          login: labelResponse.actor.login,
          created_at: labelResponse.created_at,
        };
      } else {
        if (!commentResponse) {
          throw new Error(`Issue did not have a response:\n${JSON.stringify(issue, null, 2)}`);
        }
        firstResponse = {
          login: commentResponse.user.login,
          created_at: commentResponse.created_at,
        };
      }

      return {
        issue,
        labelResponse,
        commentResponse,
        firstResponse,
        firstResponseTimeInHours:
          (new Date(firstResponse.created_at).getTime() - new Date(issue.created_at).getTime()) /
          HOUR_IN_MS,
      };
    })
    .sort((a, b) => a.firstResponseTimeInHours - b.firstResponseTimeInHours);

  const responseTimeInHours = firstResponses.map(r => r.firstResponseTimeInHours);
  const medianResponseTime = responseTimeInHours[Math.floor(withResponse.length / 2)];

  const responsesByLogin = Object.values(
    firstResponses.reduce(
      (map, response) => {
        const responses = map[response.firstResponse.login] || [];
        responses.push(response);
        map[response.firstResponse.login] = responses;
        return map;
      },
      /** @type {Record<string, typeof firstResponses>} */ ({})
    )
  ).sort((a, b) => b.length - a.length);

  console.log(`${log.bold}${label}${log.reset}`);
  console.log(`  ${percent(withResponse.length / issues.length)} of issues received a response`);
  console.log(
    `  Median response time of ${log.bold}${medianResponseTime.toFixed(1)} hours${log.reset}`
  );
  console.log('  By User');
  /** @type {Record<string, Record<string, string | number>>} */
  const byUser = {};
  responsesByLogin.forEach(responses => {
    const user = responses[0].firstResponse.login;
    const medianResponseTime = responses[Math.floor(responses.length / 2)].firstResponseTimeInHours;
    byUser[user] = {
      responses: responses.length,
      medianResponseTime: `${medianResponseTime.toFixed(1)} hours`,
    };
  });
  console.table(byUser);
}
@param {string} label
@param {Array<AugmentedGitHubIssue>} issues