We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`logger._setup_test_logger` has unused param
The `filename` param is not used.
Let's remove it

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mobly/logger.py`
Content:
```
1 # Copyright 2016 Google Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 from __future__ import print_function
16 
17 import datetime
18 import logging
19 import os
20 import re
21 import sys
22 
23 from mobly import records
24 from mobly import utils
25 
26 log_line_format = '%(asctime)s.%(msecs).03d %(levelname)s %(message)s'
27 # The micro seconds are added by the format string above,
28 # so the time format does not include ms.
29 log_line_time_format = '%m-%d %H:%M:%S'
30 log_line_timestamp_len = 18
31 
32 logline_timestamp_re = re.compile('\d\d-\d\d \d\d:\d\d:\d\d.\d\d\d')
33 
34 
35 def _parse_logline_timestamp(t):
36     """Parses a logline timestamp into a tuple.
37 
38     Args:
39         t: Timestamp in logline format.
40 
41     Returns:
42         An iterable of date and time elements in the order of month, day, hour,
43         minute, second, microsecond.
44     """
45     date, time = t.split(' ')
46     month, day = date.split('-')
47     h, m, s = time.split(':')
48     s, ms = s.split('.')
49     return (month, day, h, m, s, ms)
50 
51 
52 def is_valid_logline_timestamp(timestamp):
53     if len(timestamp) == log_line_timestamp_len:
54         if logline_timestamp_re.match(timestamp):
55             return True
56     return False
57 
58 
59 def logline_timestamp_comparator(t1, t2):
60     """Comparator for timestamps in logline format.
61 
62     Args:
63         t1: Timestamp in logline format.
64         t2: Timestamp in logline format.
65 
66     Returns:
67         -1 if t1 < t2; 1 if t1 > t2; 0 if t1 == t2.
68     """
69     dt1 = _parse_logline_timestamp(t1)
70     dt2 = _parse_logline_timestamp(t2)
71     for u1, u2 in zip(dt1, dt2):
72         if u1 < u2:
73             return -1
74         elif u1 > u2:
75             return 1
76     return 0
77 
78 
79 def _get_timestamp(time_format, delta=None):
80     t = datetime.datetime.now()
81     if delta:
82         t = t + datetime.timedelta(seconds=delta)
83     return t.strftime(time_format)[:-3]
84 
85 
86 def epoch_to_log_line_timestamp(epoch_time, time_zone=None):
87     """Converts an epoch timestamp in ms to log line timestamp format, which
88     is readible for humans.
89 
90     Args:
91         epoch_time: integer, an epoch timestamp in ms.
92         time_zone: instance of tzinfo, time zone information.
93             Using pytz rather than python 3.2 time_zone implementation for
94             python 2 compatibility reasons.
95 
96     Returns:
97         A string that is the corresponding timestamp in log line timestamp
98         format.
99     """
100     s, ms = divmod(epoch_time, 1000)
101     d = datetime.datetime.fromtimestamp(s, tz=time_zone)
102     return d.strftime('%m-%d %H:%M:%S.') + str(ms)
103 
104 
105 def get_log_line_timestamp(delta=None):
106     """Returns a timestamp in the format used by log lines.
107 
108     Default is current time. If a delta is set, the return value will be
109     the current time offset by delta seconds.
110 
111     Args:
112         delta: Number of seconds to offset from current time; can be negative.
113 
114     Returns:
115         A timestamp in log line format with an offset.
116     """
117     return _get_timestamp('%m-%d %H:%M:%S.%f', delta)
118 
119 
120 def get_log_file_timestamp(delta=None):
121     """Returns a timestamp in the format used for log file names.
122 
123     Default is current time. If a delta is set, the return value will be
124     the current time offset by delta seconds.
125 
126     Args:
127         delta: Number of seconds to offset from current time; can be negative.
128 
129     Returns:
130         A timestamp in log filen name format with an offset.
131     """
132     return _get_timestamp('%m-%d-%Y_%H-%M-%S-%f', delta)
133 
134 
135 def _setup_test_logger(log_path, prefix=None, filename=None):
136     """Customizes the root logger for a test run.
137 
138     The logger object has a stream handler and a file handler. The stream
139     handler logs INFO level to the terminal, the file handler logs DEBUG
140     level to files.
141 
142     Args:
143         log_path: Location of the log file.
144         prefix: A prefix for each log line in terminal.
145         filename: Name of the log file. The default is the time the logger
146             is requested.
147     """
148     log = logging.getLogger()
149     kill_test_logger(log)
150     log.propagate = False
151     log.setLevel(logging.DEBUG)
152     # Log info to stream
153     terminal_format = log_line_format
154     if prefix:
155         terminal_format = '[%s] %s' % (prefix, log_line_format)
156     c_formatter = logging.Formatter(terminal_format, log_line_time_format)
157     ch = logging.StreamHandler(sys.stdout)
158     ch.setFormatter(c_formatter)
159     ch.setLevel(logging.INFO)
160     # Log everything to file
161     f_formatter = logging.Formatter(log_line_format, log_line_time_format)
162     # All the logs of this test class go into one directory
163     if filename is None:
164         filename = get_log_file_timestamp()
165         utils.create_dir(log_path)
166     # Write logger output to files
167     fh_info = logging.FileHandler(
168         os.path.join(log_path, records.OUTPUT_FILE_INFO_LOG))
169     fh_info.setFormatter(f_formatter)
170     fh_info.setLevel(logging.INFO)
171     fh_debug = logging.FileHandler(
172         os.path.join(log_path, records.OUTPUT_FILE_DEBUG_LOG))
173     fh_debug.setFormatter(f_formatter)
174     fh_debug.setLevel(logging.DEBUG)
175     log.addHandler(ch)
176     log.addHandler(fh_info)
177     log.addHandler(fh_debug)
178     log.log_path = log_path
179     logging.log_path = log_path
180 
181 
182 def kill_test_logger(logger):
183     """Cleans up a test logger object by removing all of its handlers.
184 
185     Args:
186         logger: The logging object to clean up.
187     """
188     for h in list(logger.handlers):
189         logger.removeHandler(h)
190         if isinstance(h, logging.FileHandler):
191             h.close()
192 
193 
194 def create_latest_log_alias(actual_path):
195     """Creates a symlink to the latest test run logs.
196 
197     Args:
198         actual_path: The source directory where the latest test run's logs are.
199     """
200     alias_path = os.path.join(os.path.dirname(actual_path), 'latest')
201     utils.create_alias(actual_path, alias_path)
202 
203 
204 def setup_test_logger(log_path, prefix=None, filename=None):
205     """Customizes the root logger for a test run.
206 
207     Args:
208         log_path: Location of the report file.
209         prefix: A prefix for each log line in terminal.
210         filename: Name of the files. The default is the time the objects
211             are requested.
212     """
213     if filename is None:
214         filename = get_log_file_timestamp()
215     utils.create_dir(log_path)
216     _setup_test_logger(log_path, prefix, filename)
217     logging.info('Test output folder: "%s"', log_path)
218     create_latest_log_alias(log_path)
219 
220 
221 def normalize_log_line_timestamp(log_line_timestamp):
222     """Replace special characters in log line timestamp with normal characters.
223 
224     Args:
225         log_line_timestamp: A string in the log line timestamp format. Obtained
226             with get_log_line_timestamp.
227 
228     Returns:
229         A string representing the same time as input timestamp, but without
230         special characters.
231     """
232     norm_tp = log_line_timestamp.replace(' ', '_')
233     norm_tp = norm_tp.replace(':', '-')
234     return norm_tp
235
```
--- 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/mobly/logger.py b/mobly/logger.py
--- a/mobly/logger.py
+++ b/mobly/logger.py
@@ -132,7 +132,7 @@
     return _get_timestamp('%m-%d-%Y_%H-%M-%S-%f', delta)
 
 
-def _setup_test_logger(log_path, prefix=None, filename=None):
+def _setup_test_logger(log_path, prefix=None):
     """Customizes the root logger for a test run.
 
     The logger object has a stream handler and a file handler. The stream
@@ -159,10 +159,6 @@
     ch.setLevel(logging.INFO)
     # Log everything to file
     f_formatter = logging.Formatter(log_line_format, log_line_time_format)
-    # All the logs of this test class go into one directory
-    if filename is None:
-        filename = get_log_file_timestamp()
-        utils.create_dir(log_path)
     # Write logger output to files
     fh_info = logging.FileHandler(
         os.path.join(log_path, records.OUTPUT_FILE_INFO_LOG))
@@ -210,10 +206,8 @@
         filename: Name of the files. The default is the time the objects
             are requested.
     """
-    if filename is None:
-        filename = get_log_file_timestamp()
     utils.create_dir(log_path)
-    _setup_test_logger(log_path, prefix, filename)
+    _setup_test_logger(log_path, prefix)
     logging.info('Test output folder: "%s"', log_path)
     create_latest_log_alias(log_path)

{"golden_diff": "diff --git a/mobly/logger.py b/mobly/logger.py\n--- a/mobly/logger.py\n+++ b/mobly/logger.py\n@@ -132,7 +132,7 @@\n     return _get_timestamp('%m-%d-%Y_%H-%M-%S-%f', delta)\n \n \n-def _setup_test_logger(log_path, prefix=None, filename=None):\n+def _setup_test_logger(log_path, prefix=None):\n     \"\"\"Customizes the root logger for a test run.\n \n     The logger object has a stream handler and a file handler. The stream\n@@ -159,10 +159,6 @@\n     ch.setLevel(logging.INFO)\n     # Log everything to file\n     f_formatter = logging.Formatter(log_line_format, log_line_time_format)\n-    # All the logs of this test class go into one directory\n-    if filename is None:\n-        filename = get_log_file_timestamp()\n-        utils.create_dir(log_path)\n     # Write logger output to files\n     fh_info = logging.FileHandler(\n         os.path.join(log_path, records.OUTPUT_FILE_INFO_LOG))\n@@ -210,10 +206,8 @@\n         filename: Name of the files. The default is the time the objects\n             are requested.\n     \"\"\"\n-    if filename is None:\n-        filename = get_log_file_timestamp()\n     utils.create_dir(log_path)\n-    _setup_test_logger(log_path, prefix, filename)\n+    _setup_test_logger(log_path, prefix)\n     logging.info('Test output folder: \"%s\"', log_path)\n     create_latest_log_alias(log_path)\n", "issue": "`logger._setup_test_logger` has unused param\nThe `filename` param is not used.\r\nLet's remove it\n", "before_files": [{"content": "# Copyright 2016 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import print_function\n\nimport datetime\nimport logging\nimport os\nimport re\nimport sys\n\nfrom mobly import records\nfrom mobly import utils\n\nlog_line_format = '%(asctime)s.%(msecs).03d %(levelname)s %(message)s'\n# The micro seconds are added by the format string above,\n# so the time format does not include ms.\nlog_line_time_format = '%m-%d %H:%M:%S'\nlog_line_timestamp_len = 18\n\nlogline_timestamp_re = re.compile('\\d\\d-\\d\\d \\d\\d:\\d\\d:\\d\\d.\\d\\d\\d')\n\n\ndef _parse_logline_timestamp(t):\n    \"\"\"Parses a logline timestamp into a tuple.\n\n    Args:\n        t: Timestamp in logline format.\n\n    Returns:\n        An iterable of date and time elements in the order of month, day, hour,\n        minute, second, microsecond.\n    \"\"\"\n    date, time = t.split(' ')\n    month, day = date.split('-')\n    h, m, s = time.split(':')\n    s, ms = s.split('.')\n    return (month, day, h, m, s, ms)\n\n\ndef is_valid_logline_timestamp(timestamp):\n    if len(timestamp) == log_line_timestamp_len:\n        if logline_timestamp_re.match(timestamp):\n            return True\n    return False\n\n\ndef logline_timestamp_comparator(t1, t2):\n    \"\"\"Comparator for timestamps in logline format.\n\n    Args:\n        t1: Timestamp in logline format.\n        t2: Timestamp in logline format.\n\n    Returns:\n        -1 if t1 < t2; 1 if t1 > t2; 0 if t1 == t2.\n    \"\"\"\n    dt1 = _parse_logline_timestamp(t1)\n    dt2 = _parse_logline_timestamp(t2)\n    for u1, u2 in zip(dt1, dt2):\n        if u1 < u2:\n            return -1\n        elif u1 > u2:\n            return 1\n    return 0\n\n\ndef _get_timestamp(time_format, delta=None):\n    t = datetime.datetime.now()\n    if delta:\n        t = t + datetime.timedelta(seconds=delta)\n    return t.strftime(time_format)[:-3]\n\n\ndef epoch_to_log_line_timestamp(epoch_time, time_zone=None):\n    \"\"\"Converts an epoch timestamp in ms to log line timestamp format, which\n    is readible for humans.\n\n    Args:\n        epoch_time: integer, an epoch timestamp in ms.\n        time_zone: instance of tzinfo, time zone information.\n            Using pytz rather than python 3.2 time_zone implementation for\n            python 2 compatibility reasons.\n\n    Returns:\n        A string that is the corresponding timestamp in log line timestamp\n        format.\n    \"\"\"\n    s, ms = divmod(epoch_time, 1000)\n    d = datetime.datetime.fromtimestamp(s, tz=time_zone)\n    return d.strftime('%m-%d %H:%M:%S.') + str(ms)\n\n\ndef get_log_line_timestamp(delta=None):\n    \"\"\"Returns a timestamp in the format used by log lines.\n\n    Default is current time. If a delta is set, the return value will be\n    the current time offset by delta seconds.\n\n    Args:\n        delta: Number of seconds to offset from current time; can be negative.\n\n    Returns:\n        A timestamp in log line format with an offset.\n    \"\"\"\n    return _get_timestamp('%m-%d %H:%M:%S.%f', delta)\n\n\ndef get_log_file_timestamp(delta=None):\n    \"\"\"Returns a timestamp in the format used for log file names.\n\n    Default is current time. If a delta is set, the return value will be\n    the current time offset by delta seconds.\n\n    Args:\n        delta: Number of seconds to offset from current time; can be negative.\n\n    Returns:\n        A timestamp in log filen name format with an offset.\n    \"\"\"\n    return _get_timestamp('%m-%d-%Y_%H-%M-%S-%f', delta)\n\n\ndef _setup_test_logger(log_path, prefix=None, filename=None):\n    \"\"\"Customizes the root logger for a test run.\n\n    The logger object has a stream handler and a file handler. The stream\n    handler logs INFO level to the terminal, the file handler logs DEBUG\n    level to files.\n\n    Args:\n        log_path: Location of the log file.\n        prefix: A prefix for each log line in terminal.\n        filename: Name of the log file. The default is the time the logger\n            is requested.\n    \"\"\"\n    log = logging.getLogger()\n    kill_test_logger(log)\n    log.propagate = False\n    log.setLevel(logging.DEBUG)\n    # Log info to stream\n    terminal_format = log_line_format\n    if prefix:\n        terminal_format = '[%s] %s' % (prefix, log_line_format)\n    c_formatter = logging.Formatter(terminal_format, log_line_time_format)\n    ch = logging.StreamHandler(sys.stdout)\n    ch.setFormatter(c_formatter)\n    ch.setLevel(logging.INFO)\n    # Log everything to file\n    f_formatter = logging.Formatter(log_line_format, log_line_time_format)\n    # All the logs of this test class go into one directory\n    if filename is None:\n        filename = get_log_file_timestamp()\n        utils.create_dir(log_path)\n    # Write logger output to files\n    fh_info = logging.FileHandler(\n        os.path.join(log_path, records.OUTPUT_FILE_INFO_LOG))\n    fh_info.setFormatter(f_formatter)\n    fh_info.setLevel(logging.INFO)\n    fh_debug = logging.FileHandler(\n        os.path.join(log_path, records.OUTPUT_FILE_DEBUG_LOG))\n    fh_debug.setFormatter(f_formatter)\n    fh_debug.setLevel(logging.DEBUG)\n    log.addHandler(ch)\n    log.addHandler(fh_info)\n    log.addHandler(fh_debug)\n    log.log_path = log_path\n    logging.log_path = log_path\n\n\ndef kill_test_logger(logger):\n    \"\"\"Cleans up a test logger object by removing all of its handlers.\n\n    Args:\n        logger: The logging object to clean up.\n    \"\"\"\n    for h in list(logger.handlers):\n        logger.removeHandler(h)\n        if isinstance(h, logging.FileHandler):\n            h.close()\n\n\ndef create_latest_log_alias(actual_path):\n    \"\"\"Creates a symlink to the latest test run logs.\n\n    Args:\n        actual_path: The source directory where the latest test run's logs are.\n    \"\"\"\n    alias_path = os.path.join(os.path.dirname(actual_path), 'latest')\n    utils.create_alias(actual_path, alias_path)\n\n\ndef setup_test_logger(log_path, prefix=None, filename=None):\n    \"\"\"Customizes the root logger for a test run.\n\n    Args:\n        log_path: Location of the report file.\n        prefix: A prefix for each log line in terminal.\n        filename: Name of the files. The default is the time the objects\n            are requested.\n    \"\"\"\n    if filename is None:\n        filename = get_log_file_timestamp()\n    utils.create_dir(log_path)\n    _setup_test_logger(log_path, prefix, filename)\n    logging.info('Test output folder: \"%s\"', log_path)\n    create_latest_log_alias(log_path)\n\n\ndef normalize_log_line_timestamp(log_line_timestamp):\n    \"\"\"Replace special characters in log line timestamp with normal characters.\n\n    Args:\n        log_line_timestamp: A string in the log line timestamp format. Obtained\n            with get_log_line_timestamp.\n\n    Returns:\n        A string representing the same time as input timestamp, but without\n        special characters.\n    \"\"\"\n    norm_tp = log_line_timestamp.replace(' ', '_')\n    norm_tp = norm_tp.replace(':', '-')\n    return norm_tp\n", "path": "mobly/logger.py"}], "after_files": [{"content": "# Copyright 2016 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import print_function\n\nimport datetime\nimport logging\nimport os\nimport re\nimport sys\n\nfrom mobly import records\nfrom mobly import utils\n\nlog_line_format = '%(asctime)s.%(msecs).03d %(levelname)s %(message)s'\n# The micro seconds are added by the format string above,\n# so the time format does not include ms.\nlog_line_time_format = '%m-%d %H:%M:%S'\nlog_line_timestamp_len = 18\n\nlogline_timestamp_re = re.compile('\\d\\d-\\d\\d \\d\\d:\\d\\d:\\d\\d.\\d\\d\\d')\n\n\ndef _parse_logline_timestamp(t):\n    \"\"\"Parses a logline timestamp into a tuple.\n\n    Args:\n        t: Timestamp in logline format.\n\n    Returns:\n        An iterable of date and time elements in the order of month, day, hour,\n        minute, second, microsecond.\n    \"\"\"\n    date, time = t.split(' ')\n    month, day = date.split('-')\n    h, m, s = time.split(':')\n    s, ms = s.split('.')\n    return (month, day, h, m, s, ms)\n\n\ndef is_valid_logline_timestamp(timestamp):\n    if len(timestamp) == log_line_timestamp_len:\n        if logline_timestamp_re.match(timestamp):\n            return True\n    return False\n\n\ndef logline_timestamp_comparator(t1, t2):\n    \"\"\"Comparator for timestamps in logline format.\n\n    Args:\n        t1: Timestamp in logline format.\n        t2: Timestamp in logline format.\n\n    Returns:\n        -1 if t1 < t2; 1 if t1 > t2; 0 if t1 == t2.\n    \"\"\"\n    dt1 = _parse_logline_timestamp(t1)\n    dt2 = _parse_logline_timestamp(t2)\n    for u1, u2 in zip(dt1, dt2):\n        if u1 < u2:\n            return -1\n        elif u1 > u2:\n            return 1\n    return 0\n\n\ndef _get_timestamp(time_format, delta=None):\n    t = datetime.datetime.now()\n    if delta:\n        t = t + datetime.timedelta(seconds=delta)\n    return t.strftime(time_format)[:-3]\n\n\ndef epoch_to_log_line_timestamp(epoch_time, time_zone=None):\n    \"\"\"Converts an epoch timestamp in ms to log line timestamp format, which\n    is readible for humans.\n\n    Args:\n        epoch_time: integer, an epoch timestamp in ms.\n        time_zone: instance of tzinfo, time zone information.\n            Using pytz rather than python 3.2 time_zone implementation for\n            python 2 compatibility reasons.\n\n    Returns:\n        A string that is the corresponding timestamp in log line timestamp\n        format.\n    \"\"\"\n    s, ms = divmod(epoch_time, 1000)\n    d = datetime.datetime.fromtimestamp(s, tz=time_zone)\n    return d.strftime('%m-%d %H:%M:%S.') + str(ms)\n\n\ndef get_log_line_timestamp(delta=None):\n    \"\"\"Returns a timestamp in the format used by log lines.\n\n    Default is current time. If a delta is set, the return value will be\n    the current time offset by delta seconds.\n\n    Args:\n        delta: Number of seconds to offset from current time; can be negative.\n\n    Returns:\n        A timestamp in log line format with an offset.\n    \"\"\"\n    return _get_timestamp('%m-%d %H:%M:%S.%f', delta)\n\n\ndef get_log_file_timestamp(delta=None):\n    \"\"\"Returns a timestamp in the format used for log file names.\n\n    Default is current time. If a delta is set, the return value will be\n    the current time offset by delta seconds.\n\n    Args:\n        delta: Number of seconds to offset from current time; can be negative.\n\n    Returns:\n        A timestamp in log filen name format with an offset.\n    \"\"\"\n    return _get_timestamp('%m-%d-%Y_%H-%M-%S-%f', delta)\n\n\ndef _setup_test_logger(log_path, prefix=None):\n    \"\"\"Customizes the root logger for a test run.\n\n    The logger object has a stream handler and a file handler. The stream\n    handler logs INFO level to the terminal, the file handler logs DEBUG\n    level to files.\n\n    Args:\n        log_path: Location of the log file.\n        prefix: A prefix for each log line in terminal.\n        filename: Name of the log file. The default is the time the logger\n            is requested.\n    \"\"\"\n    log = logging.getLogger()\n    kill_test_logger(log)\n    log.propagate = False\n    log.setLevel(logging.DEBUG)\n    # Log info to stream\n    terminal_format = log_line_format\n    if prefix:\n        terminal_format = '[%s] %s' % (prefix, log_line_format)\n    c_formatter = logging.Formatter(terminal_format, log_line_time_format)\n    ch = logging.StreamHandler(sys.stdout)\n    ch.setFormatter(c_formatter)\n    ch.setLevel(logging.INFO)\n    # Log everything to file\n    f_formatter = logging.Formatter(log_line_format, log_line_time_format)\n    # Write logger output to files\n    fh_info = logging.FileHandler(\n        os.path.join(log_path, records.OUTPUT_FILE_INFO_LOG))\n    fh_info.setFormatter(f_formatter)\n    fh_info.setLevel(logging.INFO)\n    fh_debug = logging.FileHandler(\n        os.path.join(log_path, records.OUTPUT_FILE_DEBUG_LOG))\n    fh_debug.setFormatter(f_formatter)\n    fh_debug.setLevel(logging.DEBUG)\n    log.addHandler(ch)\n    log.addHandler(fh_info)\n    log.addHandler(fh_debug)\n    log.log_path = log_path\n    logging.log_path = log_path\n\n\ndef kill_test_logger(logger):\n    \"\"\"Cleans up a test logger object by removing all of its handlers.\n\n    Args:\n        logger: The logging object to clean up.\n    \"\"\"\n    for h in list(logger.handlers):\n        logger.removeHandler(h)\n        if isinstance(h, logging.FileHandler):\n            h.close()\n\n\ndef create_latest_log_alias(actual_path):\n    \"\"\"Creates a symlink to the latest test run logs.\n\n    Args:\n        actual_path: The source directory where the latest test run's logs are.\n    \"\"\"\n    alias_path = os.path.join(os.path.dirname(actual_path), 'latest')\n    utils.create_alias(actual_path, alias_path)\n\n\ndef setup_test_logger(log_path, prefix=None, filename=None):\n    \"\"\"Customizes the root logger for a test run.\n\n    Args:\n        log_path: Location of the report file.\n        prefix: A prefix for each log line in terminal.\n        filename: Name of the files. The default is the time the objects\n            are requested.\n    \"\"\"\n    utils.create_dir(log_path)\n    _setup_test_logger(log_path, prefix)\n    logging.info('Test output folder: \"%s\"', log_path)\n    create_latest_log_alias(log_path)\n\n\ndef normalize_log_line_timestamp(log_line_timestamp):\n    \"\"\"Replace special characters in log line timestamp with normal characters.\n\n    Args:\n        log_line_timestamp: A string in the log line timestamp format. Obtained\n            with get_log_line_timestamp.\n\n    Returns:\n        A string representing the same time as input timestamp, but without\n        special characters.\n    \"\"\"\n    norm_tp = log_line_timestamp.replace(' ', '_')\n    norm_tp = norm_tp.replace(':', '-')\n    return norm_tp\n", "path": "mobly/logger.py"}]}