We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add support to log hparams and metrics to tensorboard?
How can I log metrics (_e.g._ validation loss of best epoch) together with the set of hyperparameters?

I have looked through the docs and through the code.
It seems like an obvious thing, so maybe I'm just not getting it.

Currently, the only way that I found was to extend the logger class:
```python
class MyTensorBoardLogger(TensorBoardLogger):

    def __init__(self, *args, **kwargs):
        super(MyTensorBoardLogger, self).__init__(*args, **kwargs)

    def log_hyperparams(self, *args, **kwargs):
        pass

    @rank_zero_only
    def log_hyperparams_metrics(self, params: dict, metrics: dict) -> None:
        params = self._convert_params(params)
        exp, ssi, sei = hparams(params, metrics)
        writer = self.experiment._get_file_writer()
        writer.add_summary(exp)
        writer.add_summary(ssi)
        writer.add_summary(sei)
        # some alternative should be added
        self.tags.update(params)
```
And then I'm writing the hparams with metrics in a callback:
```
def on_train_end(self, trainer, module):
        module.logger.log_hyperparams_metrics(module.hparams, {'val_loss': self.best_val_loss})
```
But that doesn't seem right. 
Is there a better way to write some metric together with the hparams as well?

#### Environment

 - OS: Ubuntu18.04
 - conda4.8.3
 - pytorch-lightning==0.7.1
- torch==1.4.0


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pytorch_lightning/loggers/tensorboard.py`
Content:
```
1 """
2 TensorBoard
3 -----------
4 """
5 
6 import csv
7 import os
8 from argparse import Namespace
9 from typing import Optional, Dict, Union, Any
10 from warnings import warn
11 
12 import torch
13 from pkg_resources import parse_version
14 from torch.utils.tensorboard import SummaryWriter
15 
16 from pytorch_lightning import _logger as log
17 from pytorch_lightning.loggers.base import LightningLoggerBase
18 from pytorch_lightning.utilities import rank_zero_only
19 
20 
21 class TensorBoardLogger(LightningLoggerBase):
22     r"""
23     Log to local file system in `TensorBoard <https://www.tensorflow.org/tensorboard>`_ format.
24     Implemented using :class:`~torch.utils.tensorboard.SummaryWriter`. Logs are saved to
25     ``os.path.join(save_dir, name, version)``. This is the default logger in Lightning, it comes
26     preinstalled.
27 
28     Example:
29         >>> from pytorch_lightning import Trainer
30         >>> from pytorch_lightning.loggers import TensorBoardLogger
31         >>> logger = TensorBoardLogger("tb_logs", name="my_model")
32         >>> trainer = Trainer(logger=logger)
33 
34     Args:
35         save_dir: Save directory
36         name: Experiment name. Defaults to ``'default'``. If it is the empty string then no per-experiment
37             subdirectory is used.
38         version: Experiment version. If version is not specified the logger inspects the save
39             directory for existing versions, then automatically assigns the next available version.
40             If it is a string then it is used as the run-specific subdirectory name,
41             otherwise ``'version_${version}'`` is used.
42         \**kwargs: Other arguments are passed directly to the :class:`SummaryWriter` constructor.
43 
44     """
45     NAME_CSV_TAGS = 'meta_tags.csv'
46 
47     def __init__(self,
48                  save_dir: str,
49                  name: Optional[str] = "default",
50                  version: Optional[Union[int, str]] = None,
51                  **kwargs):
52         super().__init__()
53         self.save_dir = save_dir
54         self._name = name
55         self._version = version
56 
57         self._experiment = None
58         self.tags = {}
59         self._kwargs = kwargs
60 
61     @property
62     def root_dir(self) -> str:
63         """
64         Parent directory for all tensorboard checkpoint subdirectories.
65         If the experiment name parameter is ``None`` or the empty string, no experiment subdirectory is used
66         and the checkpoint will be saved in "save_dir/version_dir"
67         """
68         if self.name is None or len(self.name) == 0:
69             return self.save_dir
70         else:
71             return os.path.join(self.save_dir, self.name)
72 
73     @property
74     def log_dir(self) -> str:
75         """
76         The directory for this run's tensorboard checkpoint. By default, it is named
77         ``'version_${self.version}'`` but it can be overridden by passing a string value
78         for the constructor's version parameter instead of ``None`` or an int.
79         """
80         # create a pseudo standard path ala test-tube
81         version = self.version if isinstance(self.version, str) else f"version_{self.version}"
82         log_dir = os.path.join(self.root_dir, version)
83         return log_dir
84 
85     @property
86     def experiment(self) -> SummaryWriter:
87         r"""
88         Actual tensorboard object. To use TensorBoard features in your
89         :class:`~pytorch_lightning.core.lightning.LightningModule` do the following.
90 
91         Example::
92 
93             self.logger.experiment.some_tensorboard_function()
94 
95         """
96         if self._experiment is not None:
97             return self._experiment
98 
99         os.makedirs(self.root_dir, exist_ok=True)
100         self._experiment = SummaryWriter(log_dir=self.log_dir, **self._kwargs)
101         return self._experiment
102 
103     @rank_zero_only
104     def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:
105         params = self._convert_params(params)
106         params = self._flatten_dict(params)
107         sanitized_params = self._sanitize_params(params)
108 
109         if parse_version(torch.__version__) < parse_version("1.3.0"):
110             warn(
111                 f"Hyperparameter logging is not available for Torch version {torch.__version__}."
112                 " Skipping log_hyperparams. Upgrade to Torch 1.3.0 or above to enable"
113                 " hyperparameter logging."
114             )
115         else:
116             from torch.utils.tensorboard.summary import hparams
117             exp, ssi, sei = hparams(sanitized_params, {})
118             writer = self.experiment._get_file_writer()
119             writer.add_summary(exp)
120             writer.add_summary(ssi)
121             writer.add_summary(sei)
122 
123         # some alternative should be added
124         self.tags.update(sanitized_params)
125 
126     @rank_zero_only
127     def log_metrics(self, metrics: Dict[str, float], step: Optional[int] = None) -> None:
128         for k, v in metrics.items():
129             if isinstance(v, torch.Tensor):
130                 v = v.item()
131             self.experiment.add_scalar(k, v, step)
132 
133     @rank_zero_only
134     def save(self) -> None:
135         super().save()
136         try:
137             self.experiment.flush()
138         except AttributeError:
139             # you are using PT version (<v1.2) which does not have implemented flush
140             self.experiment._get_file_writer().flush()
141 
142         dir_path = self.log_dir
143         if not os.path.isdir(dir_path):
144             dir_path = self.save_dir
145 
146         # prepare the file path
147         meta_tags_path = os.path.join(dir_path, self.NAME_CSV_TAGS)
148 
149         # save the metatags file
150         with open(meta_tags_path, 'w', newline='') as csvfile:
151             fieldnames = ['key', 'value']
152             writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
153             writer.writerow({'key': 'key', 'value': 'value'})
154             for k, v in self.tags.items():
155                 writer.writerow({'key': k, 'value': v})
156 
157     @rank_zero_only
158     def finalize(self, status: str) -> None:
159         self.save()
160 
161     @property
162     def name(self) -> str:
163         return self._name
164 
165     @property
166     def version(self) -> int:
167         if self._version is None:
168             self._version = self._get_next_version()
169         return self._version
170 
171     def _get_next_version(self):
172         root_dir = os.path.join(self.save_dir, self.name)
173 
174         if not os.path.isdir(root_dir):
175             log.warning('Missing logger folder: %s', root_dir)
176             return 0
177 
178         existing_versions = []
179         for d in os.listdir(root_dir):
180             if os.path.isdir(os.path.join(root_dir, d)) and d.startswith("version_"):
181                 existing_versions.append(int(d.split("_")[1]))
182 
183         if len(existing_versions) == 0:
184             return 0
185 
186         return max(existing_versions) + 1
187
```
--- 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/pytorch_lightning/loggers/tensorboard.py b/pytorch_lightning/loggers/tensorboard.py
--- a/pytorch_lightning/loggers/tensorboard.py
+++ b/pytorch_lightning/loggers/tensorboard.py
@@ -101,7 +101,8 @@
         return self._experiment
 
     @rank_zero_only
-    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:
+    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace],
+                        metrics: Optional[Dict[str, Any]] = None) -> None:
         params = self._convert_params(params)
         params = self._flatten_dict(params)
         sanitized_params = self._sanitize_params(params)
@@ -114,7 +115,9 @@
             )
         else:
             from torch.utils.tensorboard.summary import hparams
-            exp, ssi, sei = hparams(sanitized_params, {})
+            if metrics is None:
+                metrics = {}
+            exp, ssi, sei = hparams(sanitized_params, metrics)
             writer = self.experiment._get_file_writer()
             writer.add_summary(exp)
             writer.add_summary(ssi)

{"golden_diff": "diff --git a/pytorch_lightning/loggers/tensorboard.py b/pytorch_lightning/loggers/tensorboard.py\n--- a/pytorch_lightning/loggers/tensorboard.py\n+++ b/pytorch_lightning/loggers/tensorboard.py\n@@ -101,7 +101,8 @@\n         return self._experiment\n \n     @rank_zero_only\n-    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:\n+    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace],\n+                        metrics: Optional[Dict[str, Any]] = None) -> None:\n         params = self._convert_params(params)\n         params = self._flatten_dict(params)\n         sanitized_params = self._sanitize_params(params)\n@@ -114,7 +115,9 @@\n             )\n         else:\n             from torch.utils.tensorboard.summary import hparams\n-            exp, ssi, sei = hparams(sanitized_params, {})\n+            if metrics is None:\n+                metrics = {}\n+            exp, ssi, sei = hparams(sanitized_params, metrics)\n             writer = self.experiment._get_file_writer()\n             writer.add_summary(exp)\n             writer.add_summary(ssi)\n", "issue": "Add support to log hparams and metrics to tensorboard?\nHow can I log metrics (_e.g._ validation loss of best epoch) together with the set of hyperparameters?\r\n\r\nI have looked through the docs and through the code.\r\nIt seems like an obvious thing, so maybe I'm just not getting it.\r\n\r\nCurrently, the only way that I found was to extend the logger class:\r\n```python\r\nclass MyTensorBoardLogger(TensorBoardLogger):\r\n\r\n    def __init__(self, *args, **kwargs):\r\n        super(MyTensorBoardLogger, self).__init__(*args, **kwargs)\r\n\r\n    def log_hyperparams(self, *args, **kwargs):\r\n        pass\r\n\r\n    @rank_zero_only\r\n    def log_hyperparams_metrics(self, params: dict, metrics: dict) -> None:\r\n        params = self._convert_params(params)\r\n        exp, ssi, sei = hparams(params, metrics)\r\n        writer = self.experiment._get_file_writer()\r\n        writer.add_summary(exp)\r\n        writer.add_summary(ssi)\r\n        writer.add_summary(sei)\r\n        # some alternative should be added\r\n        self.tags.update(params)\r\n```\r\nAnd then I'm writing the hparams with metrics in a callback:\r\n```\r\ndef on_train_end(self, trainer, module):\r\n        module.logger.log_hyperparams_metrics(module.hparams, {'val_loss': self.best_val_loss})\r\n```\r\nBut that doesn't seem right. \r\nIs there a better way to write some metric together with the hparams as well?\r\n\r\n#### Environment\r\n\r\n - OS: Ubuntu18.04\r\n - conda4.8.3\r\n - pytorch-lightning==0.7.1\r\n- torch==1.4.0\r\n\n", "before_files": [{"content": "\"\"\"\nTensorBoard\n-----------\n\"\"\"\n\nimport csv\nimport os\nfrom argparse import Namespace\nfrom typing import Optional, Dict, Union, Any\nfrom warnings import warn\n\nimport torch\nfrom pkg_resources import parse_version\nfrom torch.utils.tensorboard import SummaryWriter\n\nfrom pytorch_lightning import _logger as log\nfrom pytorch_lightning.loggers.base import LightningLoggerBase\nfrom pytorch_lightning.utilities import rank_zero_only\n\n\nclass TensorBoardLogger(LightningLoggerBase):\n    r\"\"\"\n    Log to local file system in `TensorBoard <https://www.tensorflow.org/tensorboard>`_ format.\n    Implemented using :class:`~torch.utils.tensorboard.SummaryWriter`. Logs are saved to\n    ``os.path.join(save_dir, name, version)``. This is the default logger in Lightning, it comes\n    preinstalled.\n\n    Example:\n        >>> from pytorch_lightning import Trainer\n        >>> from pytorch_lightning.loggers import TensorBoardLogger\n        >>> logger = TensorBoardLogger(\"tb_logs\", name=\"my_model\")\n        >>> trainer = Trainer(logger=logger)\n\n    Args:\n        save_dir: Save directory\n        name: Experiment name. Defaults to ``'default'``. If it is the empty string then no per-experiment\n            subdirectory is used.\n        version: Experiment version. If version is not specified the logger inspects the save\n            directory for existing versions, then automatically assigns the next available version.\n            If it is a string then it is used as the run-specific subdirectory name,\n            otherwise ``'version_${version}'`` is used.\n        \\**kwargs: Other arguments are passed directly to the :class:`SummaryWriter` constructor.\n\n    \"\"\"\n    NAME_CSV_TAGS = 'meta_tags.csv'\n\n    def __init__(self,\n                 save_dir: str,\n                 name: Optional[str] = \"default\",\n                 version: Optional[Union[int, str]] = None,\n                 **kwargs):\n        super().__init__()\n        self.save_dir = save_dir\n        self._name = name\n        self._version = version\n\n        self._experiment = None\n        self.tags = {}\n        self._kwargs = kwargs\n\n    @property\n    def root_dir(self) -> str:\n        \"\"\"\n        Parent directory for all tensorboard checkpoint subdirectories.\n        If the experiment name parameter is ``None`` or the empty string, no experiment subdirectory is used\n        and the checkpoint will be saved in \"save_dir/version_dir\"\n        \"\"\"\n        if self.name is None or len(self.name) == 0:\n            return self.save_dir\n        else:\n            return os.path.join(self.save_dir, self.name)\n\n    @property\n    def log_dir(self) -> str:\n        \"\"\"\n        The directory for this run's tensorboard checkpoint. By default, it is named\n        ``'version_${self.version}'`` but it can be overridden by passing a string value\n        for the constructor's version parameter instead of ``None`` or an int.\n        \"\"\"\n        # create a pseudo standard path ala test-tube\n        version = self.version if isinstance(self.version, str) else f\"version_{self.version}\"\n        log_dir = os.path.join(self.root_dir, version)\n        return log_dir\n\n    @property\n    def experiment(self) -> SummaryWriter:\n        r\"\"\"\n        Actual tensorboard object. To use TensorBoard features in your\n        :class:`~pytorch_lightning.core.lightning.LightningModule` do the following.\n\n        Example::\n\n            self.logger.experiment.some_tensorboard_function()\n\n        \"\"\"\n        if self._experiment is not None:\n            return self._experiment\n\n        os.makedirs(self.root_dir, exist_ok=True)\n        self._experiment = SummaryWriter(log_dir=self.log_dir, **self._kwargs)\n        return self._experiment\n\n    @rank_zero_only\n    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:\n        params = self._convert_params(params)\n        params = self._flatten_dict(params)\n        sanitized_params = self._sanitize_params(params)\n\n        if parse_version(torch.__version__) < parse_version(\"1.3.0\"):\n            warn(\n                f\"Hyperparameter logging is not available for Torch version {torch.__version__}.\"\n                \" Skipping log_hyperparams. Upgrade to Torch 1.3.0 or above to enable\"\n                \" hyperparameter logging.\"\n            )\n        else:\n            from torch.utils.tensorboard.summary import hparams\n            exp, ssi, sei = hparams(sanitized_params, {})\n            writer = self.experiment._get_file_writer()\n            writer.add_summary(exp)\n            writer.add_summary(ssi)\n            writer.add_summary(sei)\n\n        # some alternative should be added\n        self.tags.update(sanitized_params)\n\n    @rank_zero_only\n    def log_metrics(self, metrics: Dict[str, float], step: Optional[int] = None) -> None:\n        for k, v in metrics.items():\n            if isinstance(v, torch.Tensor):\n                v = v.item()\n            self.experiment.add_scalar(k, v, step)\n\n    @rank_zero_only\n    def save(self) -> None:\n        super().save()\n        try:\n            self.experiment.flush()\n        except AttributeError:\n            # you are using PT version (<v1.2) which does not have implemented flush\n            self.experiment._get_file_writer().flush()\n\n        dir_path = self.log_dir\n        if not os.path.isdir(dir_path):\n            dir_path = self.save_dir\n\n        # prepare the file path\n        meta_tags_path = os.path.join(dir_path, self.NAME_CSV_TAGS)\n\n        # save the metatags file\n        with open(meta_tags_path, 'w', newline='') as csvfile:\n            fieldnames = ['key', 'value']\n            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)\n            writer.writerow({'key': 'key', 'value': 'value'})\n            for k, v in self.tags.items():\n                writer.writerow({'key': k, 'value': v})\n\n    @rank_zero_only\n    def finalize(self, status: str) -> None:\n        self.save()\n\n    @property\n    def name(self) -> str:\n        return self._name\n\n    @property\n    def version(self) -> int:\n        if self._version is None:\n            self._version = self._get_next_version()\n        return self._version\n\n    def _get_next_version(self):\n        root_dir = os.path.join(self.save_dir, self.name)\n\n        if not os.path.isdir(root_dir):\n            log.warning('Missing logger folder: %s', root_dir)\n            return 0\n\n        existing_versions = []\n        for d in os.listdir(root_dir):\n            if os.path.isdir(os.path.join(root_dir, d)) and d.startswith(\"version_\"):\n                existing_versions.append(int(d.split(\"_\")[1]))\n\n        if len(existing_versions) == 0:\n            return 0\n\n        return max(existing_versions) + 1\n", "path": "pytorch_lightning/loggers/tensorboard.py"}], "after_files": [{"content": "\"\"\"\nTensorBoard\n-----------\n\"\"\"\n\nimport csv\nimport os\nfrom argparse import Namespace\nfrom typing import Optional, Dict, Union, Any\nfrom warnings import warn\n\nimport torch\nfrom pkg_resources import parse_version\nfrom torch.utils.tensorboard import SummaryWriter\n\nfrom pytorch_lightning import _logger as log\nfrom pytorch_lightning.loggers.base import LightningLoggerBase\nfrom pytorch_lightning.utilities import rank_zero_only\n\n\nclass TensorBoardLogger(LightningLoggerBase):\n    r\"\"\"\n    Log to local file system in `TensorBoard <https://www.tensorflow.org/tensorboard>`_ format.\n    Implemented using :class:`~torch.utils.tensorboard.SummaryWriter`. Logs are saved to\n    ``os.path.join(save_dir, name, version)``. This is the default logger in Lightning, it comes\n    preinstalled.\n\n    Example:\n        >>> from pytorch_lightning import Trainer\n        >>> from pytorch_lightning.loggers import TensorBoardLogger\n        >>> logger = TensorBoardLogger(\"tb_logs\", name=\"my_model\")\n        >>> trainer = Trainer(logger=logger)\n\n    Args:\n        save_dir: Save directory\n        name: Experiment name. Defaults to ``'default'``. If it is the empty string then no per-experiment\n            subdirectory is used.\n        version: Experiment version. If version is not specified the logger inspects the save\n            directory for existing versions, then automatically assigns the next available version.\n            If it is a string then it is used as the run-specific subdirectory name,\n            otherwise ``'version_${version}'`` is used.\n        \\**kwargs: Other arguments are passed directly to the :class:`SummaryWriter` constructor.\n\n    \"\"\"\n    NAME_CSV_TAGS = 'meta_tags.csv'\n\n    def __init__(self,\n                 save_dir: str,\n                 name: Optional[str] = \"default\",\n                 version: Optional[Union[int, str]] = None,\n                 **kwargs):\n        super().__init__()\n        self.save_dir = save_dir\n        self._name = name\n        self._version = version\n\n        self._experiment = None\n        self.tags = {}\n        self._kwargs = kwargs\n\n    @property\n    def root_dir(self) -> str:\n        \"\"\"\n        Parent directory for all tensorboard checkpoint subdirectories.\n        If the experiment name parameter is ``None`` or the empty string, no experiment subdirectory is used\n        and the checkpoint will be saved in \"save_dir/version_dir\"\n        \"\"\"\n        if self.name is None or len(self.name) == 0:\n            return self.save_dir\n        else:\n            return os.path.join(self.save_dir, self.name)\n\n    @property\n    def log_dir(self) -> str:\n        \"\"\"\n        The directory for this run's tensorboard checkpoint. By default, it is named\n        ``'version_${self.version}'`` but it can be overridden by passing a string value\n        for the constructor's version parameter instead of ``None`` or an int.\n        \"\"\"\n        # create a pseudo standard path ala test-tube\n        version = self.version if isinstance(self.version, str) else f\"version_{self.version}\"\n        log_dir = os.path.join(self.root_dir, version)\n        return log_dir\n\n    @property\n    def experiment(self) -> SummaryWriter:\n        r\"\"\"\n        Actual tensorboard object. To use TensorBoard features in your\n        :class:`~pytorch_lightning.core.lightning.LightningModule` do the following.\n\n        Example::\n\n            self.logger.experiment.some_tensorboard_function()\n\n        \"\"\"\n        if self._experiment is not None:\n            return self._experiment\n\n        os.makedirs(self.root_dir, exist_ok=True)\n        self._experiment = SummaryWriter(log_dir=self.log_dir, **self._kwargs)\n        return self._experiment\n\n    @rank_zero_only\n    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace],\n                        metrics: Optional[Dict[str, Any]] = None) -> None:\n        params = self._convert_params(params)\n        params = self._flatten_dict(params)\n        sanitized_params = self._sanitize_params(params)\n\n        if parse_version(torch.__version__) < parse_version(\"1.3.0\"):\n            warn(\n                f\"Hyperparameter logging is not available for Torch version {torch.__version__}.\"\n                \" Skipping log_hyperparams. Upgrade to Torch 1.3.0 or above to enable\"\n                \" hyperparameter logging.\"\n            )\n        else:\n            from torch.utils.tensorboard.summary import hparams\n            if metrics is None:\n                metrics = {}\n            exp, ssi, sei = hparams(sanitized_params, metrics)\n            writer = self.experiment._get_file_writer()\n            writer.add_summary(exp)\n            writer.add_summary(ssi)\n            writer.add_summary(sei)\n\n        # some alternative should be added\n        self.tags.update(sanitized_params)\n\n    @rank_zero_only\n    def log_metrics(self, metrics: Dict[str, float], step: Optional[int] = None) -> None:\n        for k, v in metrics.items():\n            if isinstance(v, torch.Tensor):\n                v = v.item()\n            self.experiment.add_scalar(k, v, step)\n\n    @rank_zero_only\n    def save(self) -> None:\n        super().save()\n        try:\n            self.experiment.flush()\n        except AttributeError:\n            # you are using PT version (<v1.2) which does not have implemented flush\n            self.experiment._get_file_writer().flush()\n\n        dir_path = self.log_dir\n        if not os.path.isdir(dir_path):\n            dir_path = self.save_dir\n\n        # prepare the file path\n        meta_tags_path = os.path.join(dir_path, self.NAME_CSV_TAGS)\n\n        # save the metatags file\n        with open(meta_tags_path, 'w', newline='') as csvfile:\n            fieldnames = ['key', 'value']\n            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)\n            writer.writerow({'key': 'key', 'value': 'value'})\n            for k, v in self.tags.items():\n                writer.writerow({'key': k, 'value': v})\n\n    @rank_zero_only\n    def finalize(self, status: str) -> None:\n        self.save()\n\n    @property\n    def name(self) -> str:\n        return self._name\n\n    @property\n    def version(self) -> int:\n        if self._version is None:\n            self._version = self._get_next_version()\n        return self._version\n\n    def _get_next_version(self):\n        root_dir = os.path.join(self.save_dir, self.name)\n\n        if not os.path.isdir(root_dir):\n            log.warning('Missing logger folder: %s', root_dir)\n            return 0\n\n        existing_versions = []\n        for d in os.listdir(root_dir):\n            if os.path.isdir(os.path.join(root_dir, d)) and d.startswith(\"version_\"):\n                existing_versions.append(int(d.split(\"_\")[1]))\n\n        if len(existing_versions) == 0:\n            return 0\n\n        return max(existing_versions) + 1\n", "path": "pytorch_lightning/loggers/tensorboard.py"}]}