code: def get_timer_summary(timer: TimerProtocol) -> str:
      """Given a timer, generate a summary of all the recorded actions.
  
      Args:
          timer: the Timer object for which to generate a summary
  
      Raises:
          ValueError
              If the input Timer has no recorded actions
      """
      sep: str = os.linesep
      output_string = f"Timer Report{sep}"
  
      if len(timer.recorded_durations) == 0:
          return output_string
  
      max_key = max(len(k) for k in timer.recorded_durations.keys())
  
      def log_row(
          action: str, mean: str, num_calls: str, total: str, per: str
      ) -> str:
          row = f"{sep}|  {action:<{max_key}s}\t|  {mean:<15}\t|"
          row += f"  {num_calls:<15}\t|  {total:<15}\t|  {per:<15}\t|"
          return row
  
      header_string = log_row(
          "Action",
          "Mean duration (s)",
          "Num calls",
          "Total time (s)",
          "Percentage %",
      )
      output_string_len = len(header_string.expandtabs()) - 1
      sep_lines = f"{sep}{'-' * output_string_len}"
      output_string += sep_lines + header_string + sep_lines
      report: _TABLE_DATA
      (
          report,
          total_calls,
          total_duration,
      ) = _make_report(timer)
      output_string += log_row(
          "Total",
          "-",
          f"{total_calls:}",
          f"{total_duration:.5}",
          "100 %",
      )
      output_string += sep_lines
      for (
          action,
          mean_duration,
          num_calls,
          total_duration,
          duration_per,
      ) in report:
          output_string += log_row(
              action,
              f"{mean_duration:.5}",
              f"{num_calls}",
              f"{total_duration:.5}",
              f"{duration_per:.5}",
          )
      output_string += sep_lines
  
      output_string += sep
      return output_string
  
imports: import datetime
  import logging
  import os
  from collections import defaultdict
  from contextlib import contextmanager
  from time import perf_counter
  from typing import Any, Dict, Generator, List, Optional, Protocol, runtime_checkable, Sequence, Tuple, TypeVar
  import numpy
  import torch
  import torch.distributed
  from tabulate import tabulate
  from torchtnt.utils.distributed import PGWrapper
label_desc: Use image node_id 4 for calling a global function with example usage: get_timer_summary(timer) and returns: output_string, output_string, row