/** Based on the deadline, calculate and set the timeout to the given headers. */
  private static void updateTimeoutHeaders(
      @Nullable Deadline effectiveDeadline,
      @Nullable Deadline callDeadline,
      @Nullable Deadline outerCallDeadline,
      Metadata headers) {
    headers.removeAll(TIMEOUT_KEY);

    if (effectiveDeadline == null) {
      return;
    }

    long effectiveTimeout = max(0, effectiveDeadline.timeRemaining(TimeUnit.NANOSECONDS));
    headers.put(TIMEOUT_KEY, effectiveTimeout);

    logIfContextNarrowedTimeout(
        effectiveTimeout, effectiveDeadline, outerCallDeadline, callDeadline);
  }
  private static void logIfContextNarrowedTimeout(
      long effectiveTimeout,
      Deadline effectiveDeadline,
      @Nullable Deadline outerCallDeadline,
      @Nullable Deadline callDeadline) {
    if (!log.isLoggable(Level.INFO) || outerCallDeadline != effectiveDeadline) {
      return;
    }

    StringBuilder builder = new StringBuilder();
    builder.append(
        String.format("Call timeout set to '%d' ns, due to context deadline.", effectiveTimeout));
    if (callDeadline == null) {
      builder.append(" Explicit call timeout was not set.");
    } else {
      long callTimeout = callDeadline.timeRemaining(TimeUnit.NANOSECONDS);
      builder.append(String.format(" Explicit call timeout was '%d' ns.", callTimeout));
    }

    log.info(builder.toString());
  }