We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Tune doesn't show timesteps anymore
This makes it not very useful for monitoring RL runs:
```
+--------------------------+----------+----------+-----------+--------+------------------+----------+
| Trial name               | ID       | status   | loc       |   iter |   total time (s) |   reward |
|--------------------------+----------+----------+-----------+--------+------------------+----------|
| SAC_Pendulum-v0_79dcd0fe | 79dcd0fe | RUNNING  | pid=11031 |     66 |          163.499 | -1105.85 |
+--------------------------+----------+----------+-----------+--------+------------------+----------+
```

cc @richardliaw 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `python/ray/tune/result.py`
Content:
```
1 from __future__ import absolute_import
2 from __future__ import division
3 from __future__ import print_function
4 
5 import os
6 
7 # yapf: disable
8 # __sphinx_doc_begin__
9 # (Optional/Auto-filled) training is terminated. Filled only if not provided.
10 DONE = "done"
11 
12 # (Optional) Enum for user controlled checkpoint
13 SHOULD_CHECKPOINT = "should_checkpoint"
14 
15 # (Auto-filled) The hostname of the machine hosting the training process.
16 HOSTNAME = "hostname"
17 
18 # (Auto-filled) The auto-assigned id of the trial.
19 TRIAL_ID = "trial_id"
20 
21 # (Auto-filled) The auto-assigned id of the trial.
22 EXPERIMENT_TAG = "experiment_tag"
23 
24 # (Auto-filled) The node ip of the machine hosting the training process.
25 NODE_IP = "node_ip"
26 
27 # (Auto-filled) The pid of the training process.
28 PID = "pid"
29 
30 # (Optional) Mean reward for current training iteration
31 EPISODE_REWARD_MEAN = "episode_reward_mean"
32 
33 # (Optional) Mean loss for training iteration
34 MEAN_LOSS = "mean_loss"
35 
36 # (Optional) Mean accuracy for training iteration
37 MEAN_ACCURACY = "mean_accuracy"
38 
39 # Number of episodes in this iteration.
40 EPISODES_THIS_ITER = "episodes_this_iter"
41 
42 # (Optional/Auto-filled) Accumulated number of episodes for this trial.
43 EPISODES_TOTAL = "episodes_total"
44 
45 # Number of timesteps in this iteration.
46 TIMESTEPS_THIS_ITER = "timesteps_this_iter"
47 
48 # (Auto-filled) Accumulated number of timesteps for this entire trial.
49 TIMESTEPS_TOTAL = "timesteps_total"
50 
51 # (Auto-filled) Time in seconds this iteration took to run.
52 # This may be overriden to override the system-computed time difference.
53 TIME_THIS_ITER_S = "time_this_iter_s"
54 
55 # (Auto-filled) Accumulated time in seconds for this entire trial.
56 TIME_TOTAL_S = "time_total_s"
57 
58 # (Auto-filled) The index of this training iteration.
59 TRAINING_ITERATION = "training_iteration"
60 # __sphinx_doc_end__
61 # yapf: enable
62 
63 DEFAULT_EXPERIMENT_INFO_KEYS = ("trainable_name", EXPERIMENT_TAG, TRIAL_ID)
64 
65 DEFAULT_RESULT_KEYS = (TRAINING_ITERATION, TIME_TOTAL_S, MEAN_ACCURACY,
66                        MEAN_LOSS)
67 
68 # __duplicate__ is a magic keyword used internally to
69 # avoid double-logging results when using the Function API.
70 RESULT_DUPLICATE = "__duplicate__"
71 
72 # Where Tune writes result files by default
73 DEFAULT_RESULTS_DIR = (os.environ.get("TUNE_RESULT_DIR")
74                        or os.path.expanduser("~/ray_results"))
75 
76 # Meta file about status under each experiment directory, can be
77 # parsed by automlboard if exists.
78 JOB_META_FILE = "job_status.json"
79 
80 # Meta file about status under each trial directory, can be parsed
81 # by automlboard if exists.
82 EXPR_META_FILE = "trial_status.json"
83 
84 # File that stores parameters of the trial.
85 EXPR_PARAM_FILE = "params.json"
86 
87 # Pickle File that stores parameters of the trial.
88 EXPR_PARAM_PICKLE_FILE = "params.pkl"
89 
90 # File that stores the progress of the trial.
91 EXPR_PROGRESS_FILE = "progress.csv"
92 
93 # File that stores results of the trial.
94 EXPR_RESULT_FILE = "result.json"
95 
96 # Config prefix when using Analysis.
97 CONFIG_PREFIX = "config/"
98
```

Path: `python/ray/tune/progress_reporter.py`
Content:
```
1 from __future__ import print_function
2 
3 import os
4 
5 from ray.tune.result import (DEFAULT_RESULT_KEYS, CONFIG_PREFIX, PID,
6                              EPISODE_REWARD_MEAN, MEAN_ACCURACY, MEAN_LOSS,
7                              HOSTNAME, TRAINING_ITERATION, TIME_TOTAL_S)
8 from ray.tune.util import flatten_dict
9 
10 try:
11     from tabulate import tabulate
12 except ImportError:
13     raise ImportError("ray.tune in ray > 0.7.5 requires 'tabulate'. "
14                       "Please re-run 'pip install ray[tune]' or "
15                       "'pip install ray[rllib]'.")
16 
17 DEFAULT_PROGRESS_KEYS = DEFAULT_RESULT_KEYS + (EPISODE_REWARD_MEAN, )
18 # Truncated representations of column names (to accommodate small screens).
19 REPORTED_REPRESENTATIONS = {
20     EPISODE_REWARD_MEAN: "reward",
21     MEAN_ACCURACY: "acc",
22     MEAN_LOSS: "loss",
23     TIME_TOTAL_S: "total time (s)",
24     TRAINING_ITERATION: "iter",
25 }
26 
27 
28 class ProgressReporter(object):
29     def report(self, trial_runner):
30         """Reports progress across all trials of the trial runner.
31 
32         Args:
33             trial_runner: Trial runner to report on.
34         """
35         raise NotImplementedError
36 
37 
38 class JupyterNotebookReporter(ProgressReporter):
39     def __init__(self, overwrite):
40         """Initializes a new JupyterNotebookReporter.
41 
42         Args:
43             overwrite (bool): Flag for overwriting the last reported progress.
44         """
45         self.overwrite = overwrite
46 
47     def report(self, trial_runner):
48         delim = "<br>"
49         messages = [
50             "== Status ==",
51             memory_debug_str(),
52             trial_runner.debug_string(delim=delim),
53             trial_progress_str(trial_runner.get_trials(), fmt="html")
54         ]
55         from IPython.display import clear_output
56         from IPython.core.display import display, HTML
57         if self.overwrite:
58             clear_output(wait=True)
59         display(HTML(delim.join(messages) + delim))
60 
61 
62 class CLIReporter(ProgressReporter):
63     def report(self, trial_runner):
64         messages = [
65             "== Status ==",
66             memory_debug_str(),
67             trial_runner.debug_string(),
68             trial_progress_str(trial_runner.get_trials())
69         ]
70         print("\n".join(messages) + "\n")
71 
72 
73 def memory_debug_str():
74     try:
75         import psutil
76         total_gb = psutil.virtual_memory().total / (1024**3)
77         used_gb = total_gb - psutil.virtual_memory().available / (1024**3)
78         if used_gb > total_gb * 0.9:
79             warn = (": ***LOW MEMORY*** less than 10% of the memory on "
80                     "this node is available for use. This can cause "
81                     "unexpected crashes. Consider "
82                     "reducing the memory used by your application "
83                     "or reducing the Ray object store size by setting "
84                     "`object_store_memory` when calling `ray.init`.")
85         else:
86             warn = ""
87         return "Memory usage on this node: {}/{} GiB{}".format(
88             round(used_gb, 1), round(total_gb, 1), warn)
89     except ImportError:
90         return ("Unknown memory usage. Please run `pip install psutil` "
91                 "(or ray[debug]) to resolve)")
92 
93 
94 def trial_progress_str(trials, metrics=None, fmt="psql", max_rows=100):
95     """Returns a human readable message for printing to the console.
96 
97     This contains a table where each row represents a trial, its parameters
98     and the current values of its metrics.
99 
100     Args:
101         trials (List[Trial]): List of trials to get progress string for.
102         metrics (List[str]): Names of metrics to include. Defaults to
103             metrics defined in DEFAULT_RESULT_KEYS.
104         fmt (str): Output format (see tablefmt in tabulate API).
105         max_rows (int): Maximum number of rows in the trial table.
106     """
107     messages = []
108     delim = "<br>" if fmt == "html" else "\n"
109     if len(trials) < 1:
110         return delim.join(messages)
111 
112     num_trials = len(trials)
113     trials_per_state = {}
114     for t in trials:
115         trials_per_state[t.status] = trials_per_state.get(t.status, 0) + 1
116     messages.append("Number of trials: {} ({})".format(num_trials,
117                                                        trials_per_state))
118     for local_dir in sorted({t.local_dir for t in trials}):
119         messages.append("Result logdir: {}".format(local_dir))
120 
121     if num_trials > max_rows:
122         overflow = num_trials - max_rows
123         # TODO(ujvl): suggestion for users to view more rows.
124         messages.append("Table truncated to {} rows ({} overflow).".format(
125             max_rows, overflow))
126 
127     # Pre-process trials to figure out what columns to show.
128     keys = list(metrics or DEFAULT_PROGRESS_KEYS)
129     keys = [k for k in keys if any(t.last_result.get(k) for t in trials)]
130     has_failed = any(t.error_file for t in trials)
131     # Build rows.
132     trial_table = []
133     params = list(set().union(*[t.evaluated_params for t in trials]))
134     for trial in trials[:min(num_trials, max_rows)]:
135         trial_table.append(_get_trial_info(trial, params, keys, has_failed))
136     # Parse columns.
137     parsed_columns = [REPORTED_REPRESENTATIONS.get(k, k) for k in keys]
138     columns = ["Trial name", "ID", "status", "loc"]
139     columns += ["failures", "error file"] if has_failed else []
140     columns += params + parsed_columns
141     messages.append(
142         tabulate(trial_table, headers=columns, tablefmt=fmt, showindex=False))
143     return delim.join(messages)
144 
145 
146 def _get_trial_info(trial, parameters, metrics, include_error_data=False):
147     """Returns the following information about a trial:
148 
149     name | ID | status | loc | # failures | error_file | params... | metrics...
150 
151     Args:
152         trial (Trial): Trial to get information for.
153         parameters (List[str]): Names of trial parameters to include.
154         metrics (List[str]): Names of metrics to include.
155         include_error_data (bool): Include error file and # of failures.
156     """
157     result = flatten_dict(trial.last_result)
158     trial_info = [str(trial), trial.trial_id, trial.status]
159     trial_info += [_location_str(result.get(HOSTNAME), result.get(PID))]
160     if include_error_data:
161         # TODO(ujvl): File path is too long to display in a single row.
162         trial_info += [trial.num_failures, trial.error_file]
163     trial_info += [result.get(CONFIG_PREFIX + param) for param in parameters]
164     trial_info += [result.get(metric) for metric in metrics]
165     return trial_info
166 
167 
168 def _location_str(hostname, pid):
169     if not pid:
170         return ""
171     elif hostname == os.uname()[1]:
172         return "pid={}".format(pid)
173     else:
174         return "{}:{}".format(hostname, pid)
175
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/python/ray/tune/progress_reporter.py b/python/ray/tune/progress_reporter.py
--- a/python/ray/tune/progress_reporter.py
+++ b/python/ray/tune/progress_reporter.py
@@ -4,7 +4,8 @@
 
 from ray.tune.result import (DEFAULT_RESULT_KEYS, CONFIG_PREFIX, PID,
                              EPISODE_REWARD_MEAN, MEAN_ACCURACY, MEAN_LOSS,
-                             HOSTNAME, TRAINING_ITERATION, TIME_TOTAL_S)
+                             HOSTNAME, TRAINING_ITERATION, TIME_TOTAL_S,
+                             TIMESTEPS_TOTAL)
 from ray.tune.util import flatten_dict
 
 try:
@@ -21,6 +22,7 @@
     MEAN_ACCURACY: "acc",
     MEAN_LOSS: "loss",
     TIME_TOTAL_S: "total time (s)",
+    TIMESTEPS_TOTAL: "timesteps",
     TRAINING_ITERATION: "iter",
 }
 
@@ -135,7 +137,7 @@
         trial_table.append(_get_trial_info(trial, params, keys, has_failed))
     # Parse columns.
     parsed_columns = [REPORTED_REPRESENTATIONS.get(k, k) for k in keys]
-    columns = ["Trial name", "ID", "status", "loc"]
+    columns = ["Trial name", "status", "loc"]
     columns += ["failures", "error file"] if has_failed else []
     columns += params + parsed_columns
     messages.append(
@@ -146,7 +148,7 @@
 def _get_trial_info(trial, parameters, metrics, include_error_data=False):
     """Returns the following information about a trial:
 
-    name | ID | status | loc | # failures | error_file | params... | metrics...
+    name | status | loc | # failures | error_file | params... | metrics...
 
     Args:
         trial (Trial): Trial to get information for.
@@ -155,7 +157,7 @@
         include_error_data (bool): Include error file and # of failures.
     """
     result = flatten_dict(trial.last_result)
-    trial_info = [str(trial), trial.trial_id, trial.status]
+    trial_info = [str(trial), trial.status]
     trial_info += [_location_str(result.get(HOSTNAME), result.get(PID))]
     if include_error_data:
         # TODO(ujvl): File path is too long to display in a single row.
diff --git a/python/ray/tune/result.py b/python/ray/tune/result.py
--- a/python/ray/tune/result.py
+++ b/python/ray/tune/result.py
@@ -62,8 +62,8 @@
 
 DEFAULT_EXPERIMENT_INFO_KEYS = ("trainable_name", EXPERIMENT_TAG, TRIAL_ID)
 
-DEFAULT_RESULT_KEYS = (TRAINING_ITERATION, TIME_TOTAL_S, MEAN_ACCURACY,
-                       MEAN_LOSS)
+DEFAULT_RESULT_KEYS = (TRAINING_ITERATION, TIME_TOTAL_S, TIMESTEPS_TOTAL,
+                       MEAN_ACCURACY, MEAN_LOSS)
 
 # __duplicate__ is a magic keyword used internally to
 # avoid double-logging results when using the Function API.

{"golden_diff": "diff --git a/python/ray/tune/progress_reporter.py b/python/ray/tune/progress_reporter.py\n--- a/python/ray/tune/progress_reporter.py\n+++ b/python/ray/tune/progress_reporter.py\n@@ -4,7 +4,8 @@\n \n from ray.tune.result import (DEFAULT_RESULT_KEYS, CONFIG_PREFIX, PID,\n                              EPISODE_REWARD_MEAN, MEAN_ACCURACY, MEAN_LOSS,\n-                             HOSTNAME, TRAINING_ITERATION, TIME_TOTAL_S)\n+                             HOSTNAME, TRAINING_ITERATION, TIME_TOTAL_S,\n+                             TIMESTEPS_TOTAL)\n from ray.tune.util import flatten_dict\n \n try:\n@@ -21,6 +22,7 @@\n     MEAN_ACCURACY: \"acc\",\n     MEAN_LOSS: \"loss\",\n     TIME_TOTAL_S: \"total time (s)\",\n+    TIMESTEPS_TOTAL: \"timesteps\",\n     TRAINING_ITERATION: \"iter\",\n }\n \n@@ -135,7 +137,7 @@\n         trial_table.append(_get_trial_info(trial, params, keys, has_failed))\n     # Parse columns.\n     parsed_columns = [REPORTED_REPRESENTATIONS.get(k, k) for k in keys]\n-    columns = [\"Trial name\", \"ID\", \"status\", \"loc\"]\n+    columns = [\"Trial name\", \"status\", \"loc\"]\n     columns += [\"failures\", \"error file\"] if has_failed else []\n     columns += params + parsed_columns\n     messages.append(\n@@ -146,7 +148,7 @@\n def _get_trial_info(trial, parameters, metrics, include_error_data=False):\n     \"\"\"Returns the following information about a trial:\n \n-    name | ID | status | loc | # failures | error_file | params... | metrics...\n+    name | status | loc | # failures | error_file | params... | metrics...\n \n     Args:\n         trial (Trial): Trial to get information for.\n@@ -155,7 +157,7 @@\n         include_error_data (bool): Include error file and # of failures.\n     \"\"\"\n     result = flatten_dict(trial.last_result)\n-    trial_info = [str(trial), trial.trial_id, trial.status]\n+    trial_info = [str(trial), trial.status]\n     trial_info += [_location_str(result.get(HOSTNAME), result.get(PID))]\n     if include_error_data:\n         # TODO(ujvl): File path is too long to display in a single row.\ndiff --git a/python/ray/tune/result.py b/python/ray/tune/result.py\n--- a/python/ray/tune/result.py\n+++ b/python/ray/tune/result.py\n@@ -62,8 +62,8 @@\n \n DEFAULT_EXPERIMENT_INFO_KEYS = (\"trainable_name\", EXPERIMENT_TAG, TRIAL_ID)\n \n-DEFAULT_RESULT_KEYS = (TRAINING_ITERATION, TIME_TOTAL_S, MEAN_ACCURACY,\n-                       MEAN_LOSS)\n+DEFAULT_RESULT_KEYS = (TRAINING_ITERATION, TIME_TOTAL_S, TIMESTEPS_TOTAL,\n+                       MEAN_ACCURACY, MEAN_LOSS)\n \n # __duplicate__ is a magic keyword used internally to\n # avoid double-logging results when using the Function API.\n", "issue": "Tune doesn't show timesteps anymore\nThis makes it not very useful for monitoring RL runs:\r\n```\r\n+--------------------------+----------+----------+-----------+--------+------------------+----------+\r\n| Trial name               | ID       | status   | loc       |   iter |   total time (s) |   reward |\r\n|--------------------------+----------+----------+-----------+--------+------------------+----------|\r\n| SAC_Pendulum-v0_79dcd0fe | 79dcd0fe | RUNNING  | pid=11031 |     66 |          163.499 | -1105.85 |\r\n+--------------------------+----------+----------+-----------+--------+------------------+----------+\r\n```\r\n\r\ncc @richardliaw \n", "before_files": [{"content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport os\n\n# yapf: disable\n# __sphinx_doc_begin__\n# (Optional/Auto-filled) training is terminated. Filled only if not provided.\nDONE = \"done\"\n\n# (Optional) Enum for user controlled checkpoint\nSHOULD_CHECKPOINT = \"should_checkpoint\"\n\n# (Auto-filled) The hostname of the machine hosting the training process.\nHOSTNAME = \"hostname\"\n\n# (Auto-filled) The auto-assigned id of the trial.\nTRIAL_ID = \"trial_id\"\n\n# (Auto-filled) The auto-assigned id of the trial.\nEXPERIMENT_TAG = \"experiment_tag\"\n\n# (Auto-filled) The node ip of the machine hosting the training process.\nNODE_IP = \"node_ip\"\n\n# (Auto-filled) The pid of the training process.\nPID = \"pid\"\n\n# (Optional) Mean reward for current training iteration\nEPISODE_REWARD_MEAN = \"episode_reward_mean\"\n\n# (Optional) Mean loss for training iteration\nMEAN_LOSS = \"mean_loss\"\n\n# (Optional) Mean accuracy for training iteration\nMEAN_ACCURACY = \"mean_accuracy\"\n\n# Number of episodes in this iteration.\nEPISODES_THIS_ITER = \"episodes_this_iter\"\n\n# (Optional/Auto-filled) Accumulated number of episodes for this trial.\nEPISODES_TOTAL = \"episodes_total\"\n\n# Number of timesteps in this iteration.\nTIMESTEPS_THIS_ITER = \"timesteps_this_iter\"\n\n# (Auto-filled) Accumulated number of timesteps for this entire trial.\nTIMESTEPS_TOTAL = \"timesteps_total\"\n\n# (Auto-filled) Time in seconds this iteration took to run.\n# This may be overriden to override the system-computed time difference.\nTIME_THIS_ITER_S = \"time_this_iter_s\"\n\n# (Auto-filled) Accumulated time in seconds for this entire trial.\nTIME_TOTAL_S = \"time_total_s\"\n\n# (Auto-filled) The index of this training iteration.\nTRAINING_ITERATION = \"training_iteration\"\n# __sphinx_doc_end__\n# yapf: enable\n\nDEFAULT_EXPERIMENT_INFO_KEYS = (\"trainable_name\", EXPERIMENT_TAG, TRIAL_ID)\n\nDEFAULT_RESULT_KEYS = (TRAINING_ITERATION, TIME_TOTAL_S, MEAN_ACCURACY,\n                       MEAN_LOSS)\n\n# __duplicate__ is a magic keyword used internally to\n# avoid double-logging results when using the Function API.\nRESULT_DUPLICATE = \"__duplicate__\"\n\n# Where Tune writes result files by default\nDEFAULT_RESULTS_DIR = (os.environ.get(\"TUNE_RESULT_DIR\")\n                       or os.path.expanduser(\"~/ray_results\"))\n\n# Meta file about status under each experiment directory, can be\n# parsed by automlboard if exists.\nJOB_META_FILE = \"job_status.json\"\n\n# Meta file about status under each trial directory, can be parsed\n# by automlboard if exists.\nEXPR_META_FILE = \"trial_status.json\"\n\n# File that stores parameters of the trial.\nEXPR_PARAM_FILE = \"params.json\"\n\n# Pickle File that stores parameters of the trial.\nEXPR_PARAM_PICKLE_FILE = \"params.pkl\"\n\n# File that stores the progress of the trial.\nEXPR_PROGRESS_FILE = \"progress.csv\"\n\n# File that stores results of the trial.\nEXPR_RESULT_FILE = \"result.json\"\n\n# Config prefix when using Analysis.\nCONFIG_PREFIX = \"config/\"\n", "path": "python/ray/tune/result.py"}, {"content": "from __future__ import print_function\n\nimport os\n\nfrom ray.tune.result import (DEFAULT_RESULT_KEYS, CONFIG_PREFIX, PID,\n                             EPISODE_REWARD_MEAN, MEAN_ACCURACY, MEAN_LOSS,\n                             HOSTNAME, TRAINING_ITERATION, TIME_TOTAL_S)\nfrom ray.tune.util import flatten_dict\n\ntry:\n    from tabulate import tabulate\nexcept ImportError:\n    raise ImportError(\"ray.tune in ray > 0.7.5 requires 'tabulate'. \"\n                      \"Please re-run 'pip install ray[tune]' or \"\n                      \"'pip install ray[rllib]'.\")\n\nDEFAULT_PROGRESS_KEYS = DEFAULT_RESULT_KEYS + (EPISODE_REWARD_MEAN, )\n# Truncated representations of column names (to accommodate small screens).\nREPORTED_REPRESENTATIONS = {\n    EPISODE_REWARD_MEAN: \"reward\",\n    MEAN_ACCURACY: \"acc\",\n    MEAN_LOSS: \"loss\",\n    TIME_TOTAL_S: \"total time (s)\",\n    TRAINING_ITERATION: \"iter\",\n}\n\n\nclass ProgressReporter(object):\n    def report(self, trial_runner):\n        \"\"\"Reports progress across all trials of the trial runner.\n\n        Args:\n            trial_runner: Trial runner to report on.\n        \"\"\"\n        raise NotImplementedError\n\n\nclass JupyterNotebookReporter(ProgressReporter):\n    def __init__(self, overwrite):\n        \"\"\"Initializes a new JupyterNotebookReporter.\n\n        Args:\n            overwrite (bool): Flag for overwriting the last reported progress.\n        \"\"\"\n        self.overwrite = overwrite\n\n    def report(self, trial_runner):\n        delim = \"<br>\"\n        messages = [\n            \"== Status ==\",\n            memory_debug_str(),\n            trial_runner.debug_string(delim=delim),\n            trial_progress_str(trial_runner.get_trials(), fmt=\"html\")\n        ]\n        from IPython.display import clear_output\n        from IPython.core.display import display, HTML\n        if self.overwrite:\n            clear_output(wait=True)\n        display(HTML(delim.join(messages) + delim))\n\n\nclass CLIReporter(ProgressReporter):\n    def report(self, trial_runner):\n        messages = [\n            \"== Status ==\",\n            memory_debug_str(),\n            trial_runner.debug_string(),\n            trial_progress_str(trial_runner.get_trials())\n        ]\n        print(\"\\n\".join(messages) + \"\\n\")\n\n\ndef memory_debug_str():\n    try:\n        import psutil\n        total_gb = psutil.virtual_memory().total / (1024**3)\n        used_gb = total_gb - psutil.virtual_memory().available / (1024**3)\n        if used_gb > total_gb * 0.9:\n            warn = (\": ***LOW MEMORY*** less than 10% of the memory on \"\n                    \"this node is available for use. This can cause \"\n                    \"unexpected crashes. Consider \"\n                    \"reducing the memory used by your application \"\n                    \"or reducing the Ray object store size by setting \"\n                    \"`object_store_memory` when calling `ray.init`.\")\n        else:\n            warn = \"\"\n        return \"Memory usage on this node: {}/{} GiB{}\".format(\n            round(used_gb, 1), round(total_gb, 1), warn)\n    except ImportError:\n        return (\"Unknown memory usage. Please run `pip install psutil` \"\n                \"(or ray[debug]) to resolve)\")\n\n\ndef trial_progress_str(trials, metrics=None, fmt=\"psql\", max_rows=100):\n    \"\"\"Returns a human readable message for printing to the console.\n\n    This contains a table where each row represents a trial, its parameters\n    and the current values of its metrics.\n\n    Args:\n        trials (List[Trial]): List of trials to get progress string for.\n        metrics (List[str]): Names of metrics to include. Defaults to\n            metrics defined in DEFAULT_RESULT_KEYS.\n        fmt (str): Output format (see tablefmt in tabulate API).\n        max_rows (int): Maximum number of rows in the trial table.\n    \"\"\"\n    messages = []\n    delim = \"<br>\" if fmt == \"html\" else \"\\n\"\n    if len(trials) < 1:\n        return delim.join(messages)\n\n    num_trials = len(trials)\n    trials_per_state = {}\n    for t in trials:\n        trials_per_state[t.status] = trials_per_state.get(t.status, 0) + 1\n    messages.append(\"Number of trials: {} ({})\".format(num_trials,\n                                                       trials_per_state))\n    for local_dir in sorted({t.local_dir for t in trials}):\n        messages.append(\"Result logdir: {}\".format(local_dir))\n\n    if num_trials > max_rows:\n        overflow = num_trials - max_rows\n        # TODO(ujvl): suggestion for users to view more rows.\n        messages.append(\"Table truncated to {} rows ({} overflow).\".format(\n            max_rows, overflow))\n\n    # Pre-process trials to figure out what columns to show.\n    keys = list(metrics or DEFAULT_PROGRESS_KEYS)\n    keys = [k for k in keys if any(t.last_result.get(k) for t in trials)]\n    has_failed = any(t.error_file for t in trials)\n    # Build rows.\n    trial_table = []\n    params = list(set().union(*[t.evaluated_params for t in trials]))\n    for trial in trials[:min(num_trials, max_rows)]:\n        trial_table.append(_get_trial_info(trial, params, keys, has_failed))\n    # Parse columns.\n    parsed_columns = [REPORTED_REPRESENTATIONS.get(k, k) for k in keys]\n    columns = [\"Trial name\", \"ID\", \"status\", \"loc\"]\n    columns += [\"failures\", \"error file\"] if has_failed else []\n    columns += params + parsed_columns\n    messages.append(\n        tabulate(trial_table, headers=columns, tablefmt=fmt, showindex=False))\n    return delim.join(messages)\n\n\ndef _get_trial_info(trial, parameters, metrics, include_error_data=False):\n    \"\"\"Returns the following information about a trial:\n\n    name | ID | status | loc | # failures | error_file | params... | metrics...\n\n    Args:\n        trial (Trial): Trial to get information for.\n        parameters (List[str]): Names of trial parameters to include.\n        metrics (List[str]): Names of metrics to include.\n        include_error_data (bool): Include error file and # of failures.\n    \"\"\"\n    result = flatten_dict(trial.last_result)\n    trial_info = [str(trial), trial.trial_id, trial.status]\n    trial_info += [_location_str(result.get(HOSTNAME), result.get(PID))]\n    if include_error_data:\n        # TODO(ujvl): File path is too long to display in a single row.\n        trial_info += [trial.num_failures, trial.error_file]\n    trial_info += [result.get(CONFIG_PREFIX + param) for param in parameters]\n    trial_info += [result.get(metric) for metric in metrics]\n    return trial_info\n\n\ndef _location_str(hostname, pid):\n    if not pid:\n        return \"\"\n    elif hostname == os.uname()[1]:\n        return \"pid={}\".format(pid)\n    else:\n        return \"{}:{}\".format(hostname, pid)\n", "path": "python/ray/tune/progress_reporter.py"}], "after_files": [{"content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport os\n\n# yapf: disable\n# __sphinx_doc_begin__\n# (Optional/Auto-filled) training is terminated. Filled only if not provided.\nDONE = \"done\"\n\n# (Optional) Enum for user controlled checkpoint\nSHOULD_CHECKPOINT = \"should_checkpoint\"\n\n# (Auto-filled) The hostname of the machine hosting the training process.\nHOSTNAME = \"hostname\"\n\n# (Auto-filled) The auto-assigned id of the trial.\nTRIAL_ID = \"trial_id\"\n\n# (Auto-filled) The auto-assigned id of the trial.\nEXPERIMENT_TAG = \"experiment_tag\"\n\n# (Auto-filled) The node ip of the machine hosting the training process.\nNODE_IP = \"node_ip\"\n\n# (Auto-filled) The pid of the training process.\nPID = \"pid\"\n\n# (Optional) Mean reward for current training iteration\nEPISODE_REWARD_MEAN = \"episode_reward_mean\"\n\n# (Optional) Mean loss for training iteration\nMEAN_LOSS = \"mean_loss\"\n\n# (Optional) Mean accuracy for training iteration\nMEAN_ACCURACY = \"mean_accuracy\"\n\n# Number of episodes in this iteration.\nEPISODES_THIS_ITER = \"episodes_this_iter\"\n\n# (Optional/Auto-filled) Accumulated number of episodes for this trial.\nEPISODES_TOTAL = \"episodes_total\"\n\n# Number of timesteps in this iteration.\nTIMESTEPS_THIS_ITER = \"timesteps_this_iter\"\n\n# (Auto-filled) Accumulated number of timesteps for this entire trial.\nTIMESTEPS_TOTAL = \"timesteps_total\"\n\n# (Auto-filled) Time in seconds this iteration took to run.\n# This may be overriden to override the system-computed time difference.\nTIME_THIS_ITER_S = \"time_this_iter_s\"\n\n# (Auto-filled) Accumulated time in seconds for this entire trial.\nTIME_TOTAL_S = \"time_total_s\"\n\n# (Auto-filled) The index of this training iteration.\nTRAINING_ITERATION = \"training_iteration\"\n# __sphinx_doc_end__\n# yapf: enable\n\nDEFAULT_EXPERIMENT_INFO_KEYS = (\"trainable_name\", EXPERIMENT_TAG, TRIAL_ID)\n\nDEFAULT_RESULT_KEYS = (TRAINING_ITERATION, TIME_TOTAL_S, TIMESTEPS_TOTAL,\n                       MEAN_ACCURACY, MEAN_LOSS)\n\n# __duplicate__ is a magic keyword used internally to\n# avoid double-logging results when using the Function API.\nRESULT_DUPLICATE = \"__duplicate__\"\n\n# Where Tune writes result files by default\nDEFAULT_RESULTS_DIR = (os.environ.get(\"TUNE_RESULT_DIR\")\n                       or os.path.expanduser(\"~/ray_results\"))\n\n# Meta file about status under each experiment directory, can be\n# parsed by automlboard if exists.\nJOB_META_FILE = \"job_status.json\"\n\n# Meta file about status under each trial directory, can be parsed\n# by automlboard if exists.\nEXPR_META_FILE = \"trial_status.json\"\n\n# File that stores parameters of the trial.\nEXPR_PARAM_FILE = \"params.json\"\n\n# Pickle File that stores parameters of the trial.\nEXPR_PARAM_PICKLE_FILE = \"params.pkl\"\n\n# File that stores the progress of the trial.\nEXPR_PROGRESS_FILE = \"progress.csv\"\n\n# File that stores results of the trial.\nEXPR_RESULT_FILE = \"result.json\"\n\n# Config prefix when using Analysis.\nCONFIG_PREFIX = \"config/\"\n", "path": "python/ray/tune/result.py"}, {"content": "from __future__ import print_function\n\nimport os\n\nfrom ray.tune.result import (DEFAULT_RESULT_KEYS, CONFIG_PREFIX, PID,\n                             EPISODE_REWARD_MEAN, MEAN_ACCURACY, MEAN_LOSS,\n                             HOSTNAME, TRAINING_ITERATION, TIME_TOTAL_S,\n                             TIMESTEPS_TOTAL)\nfrom ray.tune.util import flatten_dict\n\ntry:\n    from tabulate import tabulate\nexcept ImportError:\n    raise ImportError(\"ray.tune in ray > 0.7.5 requires 'tabulate'. \"\n                      \"Please re-run 'pip install ray[tune]' or \"\n                      \"'pip install ray[rllib]'.\")\n\nDEFAULT_PROGRESS_KEYS = DEFAULT_RESULT_KEYS + (EPISODE_REWARD_MEAN, )\n# Truncated representations of column names (to accommodate small screens).\nREPORTED_REPRESENTATIONS = {\n    EPISODE_REWARD_MEAN: \"reward\",\n    MEAN_ACCURACY: \"acc\",\n    MEAN_LOSS: \"loss\",\n    TIME_TOTAL_S: \"total time (s)\",\n    TIMESTEPS_TOTAL: \"timesteps\",\n    TRAINING_ITERATION: \"iter\",\n}\n\n\nclass ProgressReporter(object):\n    def report(self, trial_runner):\n        \"\"\"Reports progress across all trials of the trial runner.\n\n        Args:\n            trial_runner: Trial runner to report on.\n        \"\"\"\n        raise NotImplementedError\n\n\nclass JupyterNotebookReporter(ProgressReporter):\n    def __init__(self, overwrite):\n        \"\"\"Initializes a new JupyterNotebookReporter.\n\n        Args:\n            overwrite (bool): Flag for overwriting the last reported progress.\n        \"\"\"\n        self.overwrite = overwrite\n\n    def report(self, trial_runner):\n        delim = \"<br>\"\n        messages = [\n            \"== Status ==\",\n            memory_debug_str(),\n            trial_runner.debug_string(delim=delim),\n            trial_progress_str(trial_runner.get_trials(), fmt=\"html\")\n        ]\n        from IPython.display import clear_output\n        from IPython.core.display import display, HTML\n        if self.overwrite:\n            clear_output(wait=True)\n        display(HTML(delim.join(messages) + delim))\n\n\nclass CLIReporter(ProgressReporter):\n    def report(self, trial_runner):\n        messages = [\n            \"== Status ==\",\n            memory_debug_str(),\n            trial_runner.debug_string(),\n            trial_progress_str(trial_runner.get_trials())\n        ]\n        print(\"\\n\".join(messages) + \"\\n\")\n\n\ndef memory_debug_str():\n    try:\n        import psutil\n        total_gb = psutil.virtual_memory().total / (1024**3)\n        used_gb = total_gb - psutil.virtual_memory().available / (1024**3)\n        if used_gb > total_gb * 0.9:\n            warn = (\": ***LOW MEMORY*** less than 10% of the memory on \"\n                    \"this node is available for use. This can cause \"\n                    \"unexpected crashes. Consider \"\n                    \"reducing the memory used by your application \"\n                    \"or reducing the Ray object store size by setting \"\n                    \"`object_store_memory` when calling `ray.init`.\")\n        else:\n            warn = \"\"\n        return \"Memory usage on this node: {}/{} GiB{}\".format(\n            round(used_gb, 1), round(total_gb, 1), warn)\n    except ImportError:\n        return (\"Unknown memory usage. Please run `pip install psutil` \"\n                \"(or ray[debug]) to resolve)\")\n\n\ndef trial_progress_str(trials, metrics=None, fmt=\"psql\", max_rows=100):\n    \"\"\"Returns a human readable message for printing to the console.\n\n    This contains a table where each row represents a trial, its parameters\n    and the current values of its metrics.\n\n    Args:\n        trials (List[Trial]): List of trials to get progress string for.\n        metrics (List[str]): Names of metrics to include. Defaults to\n            metrics defined in DEFAULT_RESULT_KEYS.\n        fmt (str): Output format (see tablefmt in tabulate API).\n        max_rows (int): Maximum number of rows in the trial table.\n    \"\"\"\n    messages = []\n    delim = \"<br>\" if fmt == \"html\" else \"\\n\"\n    if len(trials) < 1:\n        return delim.join(messages)\n\n    num_trials = len(trials)\n    trials_per_state = {}\n    for t in trials:\n        trials_per_state[t.status] = trials_per_state.get(t.status, 0) + 1\n    messages.append(\"Number of trials: {} ({})\".format(num_trials,\n                                                       trials_per_state))\n    for local_dir in sorted({t.local_dir for t in trials}):\n        messages.append(\"Result logdir: {}\".format(local_dir))\n\n    if num_trials > max_rows:\n        overflow = num_trials - max_rows\n        # TODO(ujvl): suggestion for users to view more rows.\n        messages.append(\"Table truncated to {} rows ({} overflow).\".format(\n            max_rows, overflow))\n\n    # Pre-process trials to figure out what columns to show.\n    keys = list(metrics or DEFAULT_PROGRESS_KEYS)\n    keys = [k for k in keys if any(t.last_result.get(k) for t in trials)]\n    has_failed = any(t.error_file for t in trials)\n    # Build rows.\n    trial_table = []\n    params = list(set().union(*[t.evaluated_params for t in trials]))\n    for trial in trials[:min(num_trials, max_rows)]:\n        trial_table.append(_get_trial_info(trial, params, keys, has_failed))\n    # Parse columns.\n    parsed_columns = [REPORTED_REPRESENTATIONS.get(k, k) for k in keys]\n    columns = [\"Trial name\", \"status\", \"loc\"]\n    columns += [\"failures\", \"error file\"] if has_failed else []\n    columns += params + parsed_columns\n    messages.append(\n        tabulate(trial_table, headers=columns, tablefmt=fmt, showindex=False))\n    return delim.join(messages)\n\n\ndef _get_trial_info(trial, parameters, metrics, include_error_data=False):\n    \"\"\"Returns the following information about a trial:\n\n    name | status | loc | # failures | error_file | params... | metrics...\n\n    Args:\n        trial (Trial): Trial to get information for.\n        parameters (List[str]): Names of trial parameters to include.\n        metrics (List[str]): Names of metrics to include.\n        include_error_data (bool): Include error file and # of failures.\n    \"\"\"\n    result = flatten_dict(trial.last_result)\n    trial_info = [str(trial), trial.status]\n    trial_info += [_location_str(result.get(HOSTNAME), result.get(PID))]\n    if include_error_data:\n        # TODO(ujvl): File path is too long to display in a single row.\n        trial_info += [trial.num_failures, trial.error_file]\n    trial_info += [result.get(CONFIG_PREFIX + param) for param in parameters]\n    trial_info += [result.get(metric) for metric in metrics]\n    return trial_info\n\n\ndef _location_str(hostname, pid):\n    if not pid:\n        return \"\"\n    elif hostname == os.uname()[1]:\n        return \"pid={}\".format(pid)\n    else:\n        return \"{}:{}\".format(hostname, pid)\n", "path": "python/ray/tune/progress_reporter.py"}]}