We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Profiler: Automatically fill `tag` in `record`?
Maybe we can use the caller's function name (`inspect.stack()`) if tag is not given.

TODO: Need to measure overhead.

--- 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_pfn_extras/profiler/_record.py`
Content:
```
1 from contextlib import contextmanager
2 from typing import Any, Callable, Generator, Iterable, Optional, TypeVar
3 
4 import torch
5 
6 from pytorch_pfn_extras.profiler._time_summary import time_summary, _ReportNotification
7 
8 
9 @contextmanager
10 def record(
11         tag: str,
12         metric: Optional[str] = None,
13         use_cuda: bool = False,
14 ) -> Generator[_ReportNotification, None, None]:
15     if metric is None:
16         metric = tag
17 
18     if use_cuda:
19         torch.cuda.nvtx.range_push(tag)  # type: ignore[no-untyped-call]
20     try:
21         with torch.autograd.profiler.record_function(tag):
22             with time_summary.report(metric, use_cuda) as ntf:
23                 yield ntf
24     finally:
25         if use_cuda:
26             torch.cuda.nvtx.range_pop()  # type: ignore[no-untyped-call]
27 
28 
29 _T = TypeVar('_T')
30 
31 
32 def record_function(
33         tag: str,
34         use_cuda: bool = False,
35 ) -> Callable[[Callable[..., _T]], Callable[..., _T]]:
36     def wrapper(f: Callable[..., _T]) -> Callable[..., _T]:
37         def wrapped(*args: Any, **kwargs: Any) -> _T:
38             with record(tag, use_cuda=use_cuda):
39                 return f(*args, **kwargs)
40 
41         return wrapped
42 
43     return wrapper
44 
45 
46 def record_iterable(
47     tag: str,
48     iter: Iterable[_T],
49     divide_metric: bool = False,
50     use_cuda: bool = False,
51 ) -> Iterable[_T]:
52     def wrapped() -> Iterable[_T]:
53         for i, x in enumerate(iter):
54             name = f"{tag}-{i}"
55             metric = name if divide_metric else tag
56             with record(name, metric, use_cuda=use_cuda):
57                 yield x
58 
59     return wrapped()
60
```
--- 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_pfn_extras/profiler/_record.py b/pytorch_pfn_extras/profiler/_record.py
--- a/pytorch_pfn_extras/profiler/_record.py
+++ b/pytorch_pfn_extras/profiler/_record.py
@@ -1,17 +1,35 @@
 from contextlib import contextmanager
+import inspect
 from typing import Any, Callable, Generator, Iterable, Optional, TypeVar
+import types
 
 import torch
 
 from pytorch_pfn_extras.profiler._time_summary import time_summary, _ReportNotification
 
 
+def _infer_tag_name(frame: Optional[types.FrameType], depth: int) -> str:
+    for _ in range(depth):
+        assert frame is not None
+        frame = frame.f_back
+    assert frame is not None
+    frame_info = inspect.getframeinfo(frame, context=0)
+    return '{}:{}:{}'.format(
+        inspect.getmodulename(frame_info.filename),
+        frame_info.lineno,
+        frame_info.function,
+    )
+
+
 @contextmanager
 def record(
-        tag: str,
+        tag: Optional[str],
         metric: Optional[str] = None,
         use_cuda: bool = False,
 ) -> Generator[_ReportNotification, None, None]:
+    if tag is None:
+        tag = _infer_tag_name(inspect.currentframe(), depth=2)
+
     if metric is None:
         metric = tag
 
@@ -30,12 +48,12 @@
 
 
 def record_function(
-        tag: str,
+        tag: Optional[str],
         use_cuda: bool = False,
 ) -> Callable[[Callable[..., _T]], Callable[..., _T]]:
     def wrapper(f: Callable[..., _T]) -> Callable[..., _T]:
         def wrapped(*args: Any, **kwargs: Any) -> _T:
-            with record(tag, use_cuda=use_cuda):
+            with record(tag or f.__name__, use_cuda=use_cuda):
                 return f(*args, **kwargs)
 
         return wrapped
@@ -44,11 +62,14 @@
 
 
 def record_iterable(
-    tag: str,
-    iter: Iterable[_T],
-    divide_metric: bool = False,
-    use_cuda: bool = False,
+        tag: Optional[str],
+        iter: Iterable[_T],
+        divide_metric: bool = False,
+        use_cuda: bool = False,
 ) -> Iterable[_T]:
+    if tag is None:
+        tag = _infer_tag_name(inspect.currentframe(), depth=1)
+
     def wrapped() -> Iterable[_T]:
         for i, x in enumerate(iter):
             name = f"{tag}-{i}"

{"golden_diff": "diff --git a/pytorch_pfn_extras/profiler/_record.py b/pytorch_pfn_extras/profiler/_record.py\n--- a/pytorch_pfn_extras/profiler/_record.py\n+++ b/pytorch_pfn_extras/profiler/_record.py\n@@ -1,17 +1,35 @@\n from contextlib import contextmanager\n+import inspect\n from typing import Any, Callable, Generator, Iterable, Optional, TypeVar\n+import types\n \n import torch\n \n from pytorch_pfn_extras.profiler._time_summary import time_summary, _ReportNotification\n \n \n+def _infer_tag_name(frame: Optional[types.FrameType], depth: int) -> str:\n+    for _ in range(depth):\n+        assert frame is not None\n+        frame = frame.f_back\n+    assert frame is not None\n+    frame_info = inspect.getframeinfo(frame, context=0)\n+    return '{}:{}:{}'.format(\n+        inspect.getmodulename(frame_info.filename),\n+        frame_info.lineno,\n+        frame_info.function,\n+    )\n+\n+\n @contextmanager\n def record(\n-        tag: str,\n+        tag: Optional[str],\n         metric: Optional[str] = None,\n         use_cuda: bool = False,\n ) -> Generator[_ReportNotification, None, None]:\n+    if tag is None:\n+        tag = _infer_tag_name(inspect.currentframe(), depth=2)\n+\n     if metric is None:\n         metric = tag\n \n@@ -30,12 +48,12 @@\n \n \n def record_function(\n-        tag: str,\n+        tag: Optional[str],\n         use_cuda: bool = False,\n ) -> Callable[[Callable[..., _T]], Callable[..., _T]]:\n     def wrapper(f: Callable[..., _T]) -> Callable[..., _T]:\n         def wrapped(*args: Any, **kwargs: Any) -> _T:\n-            with record(tag, use_cuda=use_cuda):\n+            with record(tag or f.__name__, use_cuda=use_cuda):\n                 return f(*args, **kwargs)\n \n         return wrapped\n@@ -44,11 +62,14 @@\n \n \n def record_iterable(\n-    tag: str,\n-    iter: Iterable[_T],\n-    divide_metric: bool = False,\n-    use_cuda: bool = False,\n+        tag: Optional[str],\n+        iter: Iterable[_T],\n+        divide_metric: bool = False,\n+        use_cuda: bool = False,\n ) -> Iterable[_T]:\n+    if tag is None:\n+        tag = _infer_tag_name(inspect.currentframe(), depth=1)\n+\n     def wrapped() -> Iterable[_T]:\n         for i, x in enumerate(iter):\n             name = f\"{tag}-{i}\"\n", "issue": "Profiler: Automatically fill `tag` in `record`?\nMaybe we can use the caller's function name (`inspect.stack()`) if tag is not given.\r\n\r\nTODO: Need to measure overhead.\n", "before_files": [{"content": "from contextlib import contextmanager\nfrom typing import Any, Callable, Generator, Iterable, Optional, TypeVar\n\nimport torch\n\nfrom pytorch_pfn_extras.profiler._time_summary import time_summary, _ReportNotification\n\n\n@contextmanager\ndef record(\n        tag: str,\n        metric: Optional[str] = None,\n        use_cuda: bool = False,\n) -> Generator[_ReportNotification, None, None]:\n    if metric is None:\n        metric = tag\n\n    if use_cuda:\n        torch.cuda.nvtx.range_push(tag)  # type: ignore[no-untyped-call]\n    try:\n        with torch.autograd.profiler.record_function(tag):\n            with time_summary.report(metric, use_cuda) as ntf:\n                yield ntf\n    finally:\n        if use_cuda:\n            torch.cuda.nvtx.range_pop()  # type: ignore[no-untyped-call]\n\n\n_T = TypeVar('_T')\n\n\ndef record_function(\n        tag: str,\n        use_cuda: bool = False,\n) -> Callable[[Callable[..., _T]], Callable[..., _T]]:\n    def wrapper(f: Callable[..., _T]) -> Callable[..., _T]:\n        def wrapped(*args: Any, **kwargs: Any) -> _T:\n            with record(tag, use_cuda=use_cuda):\n                return f(*args, **kwargs)\n\n        return wrapped\n\n    return wrapper\n\n\ndef record_iterable(\n    tag: str,\n    iter: Iterable[_T],\n    divide_metric: bool = False,\n    use_cuda: bool = False,\n) -> Iterable[_T]:\n    def wrapped() -> Iterable[_T]:\n        for i, x in enumerate(iter):\n            name = f\"{tag}-{i}\"\n            metric = name if divide_metric else tag\n            with record(name, metric, use_cuda=use_cuda):\n                yield x\n\n    return wrapped()\n", "path": "pytorch_pfn_extras/profiler/_record.py"}], "after_files": [{"content": "from contextlib import contextmanager\nimport inspect\nfrom typing import Any, Callable, Generator, Iterable, Optional, TypeVar\nimport types\n\nimport torch\n\nfrom pytorch_pfn_extras.profiler._time_summary import time_summary, _ReportNotification\n\n\ndef _infer_tag_name(frame: Optional[types.FrameType], depth: int) -> str:\n    for _ in range(depth):\n        assert frame is not None\n        frame = frame.f_back\n    assert frame is not None\n    frame_info = inspect.getframeinfo(frame, context=0)\n    return '{}:{}:{}'.format(\n        inspect.getmodulename(frame_info.filename),\n        frame_info.lineno,\n        frame_info.function,\n    )\n\n\n@contextmanager\ndef record(\n        tag: Optional[str],\n        metric: Optional[str] = None,\n        use_cuda: bool = False,\n) -> Generator[_ReportNotification, None, None]:\n    if tag is None:\n        tag = _infer_tag_name(inspect.currentframe(), depth=2)\n\n    if metric is None:\n        metric = tag\n\n    if use_cuda:\n        torch.cuda.nvtx.range_push(tag)  # type: ignore[no-untyped-call]\n    try:\n        with torch.autograd.profiler.record_function(tag):\n            with time_summary.report(metric, use_cuda) as ntf:\n                yield ntf\n    finally:\n        if use_cuda:\n            torch.cuda.nvtx.range_pop()  # type: ignore[no-untyped-call]\n\n\n_T = TypeVar('_T')\n\n\ndef record_function(\n        tag: Optional[str],\n        use_cuda: bool = False,\n) -> Callable[[Callable[..., _T]], Callable[..., _T]]:\n    def wrapper(f: Callable[..., _T]) -> Callable[..., _T]:\n        def wrapped(*args: Any, **kwargs: Any) -> _T:\n            with record(tag or f.__name__, use_cuda=use_cuda):\n                return f(*args, **kwargs)\n\n        return wrapped\n\n    return wrapper\n\n\ndef record_iterable(\n        tag: Optional[str],\n        iter: Iterable[_T],\n        divide_metric: bool = False,\n        use_cuda: bool = False,\n) -> Iterable[_T]:\n    if tag is None:\n        tag = _infer_tag_name(inspect.currentframe(), depth=1)\n\n    def wrapped() -> Iterable[_T]:\n        for i, x in enumerate(iter):\n            name = f\"{tag}-{i}\"\n            metric = name if divide_metric else tag\n            with record(name, metric, use_cuda=use_cuda):\n                yield x\n\n    return wrapped()\n", "path": "pytorch_pfn_extras/profiler/_record.py"}]}