We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add a 'conda env export' to logging module
We could add the output of `conda env export` to the beginning of log files so that the exact environment being used to run a script is logged. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `jwql/utils/logging_functions.py`
Content:
```
1 """ Logging functions for the ``jwql`` automation platform.
2 
3 This module provides decorators to log the execution of modules.  Log
4 files are written to the ``logs/`` directory in the ``jwql`` central
5 storage area, named by module name and timestamp, e.g.
6 ``monitor_filesystem/monitor_filesystem_2018-06-20-15:22:51.log``
7 
8 
9 Authors
10 -------
11 
12     - Catherine Martlin
13     - Alex Viana (WFC3 QL Version)
14     - Matthew Bourque
15 
16 Use
17 ---
18 
19     To log the execution of a module, use:
20     ::
21 
22         import os
23         import logging
24 
25         from jwql.logging.logging_functions import configure_logging
26         from jwql.logging.logging_functions import log_info
27         from jwql.logging.logging_functions import log_fail
28 
29         @log_info
30         @log_fail
31         def my_main_function():
32             pass
33 
34         if __name__ == '__main__':
35 
36             module = os.path.basename(__file__).replace('.py', '')
37             configure_logging(module)
38 
39             my_main_function()
40 
41 Dependencies
42 ------------
43 
44     The user must have a configuration file named ``config.json``
45     placed in the ``utils`` directory and it must contain keys for
46     ``log_dir`` and ``admin_account``.
47 
48 References
49 ----------
50     This code is adopted and updated from python routine
51     ``logging_functions.py`` written by Alex Viana, 2013 for the WFC3
52     Quicklook automation platform.
53 """
54 
55 import datetime
56 import getpass
57 import importlib
58 import logging
59 import os
60 import pwd
61 import socket
62 import sys
63 import time
64 import traceback
65 
66 from functools import wraps
67 
68 from jwql.utils.permissions import set_permissions
69 from jwql.utils.utils import get_config, ensure_dir_exists
70 
71 
72 def configure_logging(module):
73     """Configure the log file with a standard logging format.
74 
75     Parameters
76     ----------
77     module : str
78         The name of the module being logged.
79     production_mode : bool
80         Whether or not the output should be written to the production
81         environement.
82     path : str
83         Where to write the log if user-supplied path; default to working dir.
84 
85     Returns
86     -------
87     log_file : str
88         The path to the file where the log is written to.
89     """
90 
91     # Determine log file location
92     log_file = make_log_file(module)
93 
94     # Make sure no other root lhandlers exist before configuring the logger
95     for handler in logging.root.handlers[:]:
96         logging.root.removeHandler(handler)
97 
98     # Create the log file and set the permissions
99     logging.basicConfig(filename=log_file,
100                         format='%(asctime)s %(levelname)s: %(message)s',
101                         datefmt='%m/%d/%Y %H:%M:%S %p',
102                         level=logging.INFO)
103     print('Log file initialized to {}'.format(log_file))
104     set_permissions(log_file)
105 
106     return log_file
107 
108 
109 def get_log_status(log_file):
110     """Returns the end status of the given ``log_file`` (i.e.
111     ``SUCCESS`` or ``FAILURE``)
112 
113     Parameters
114     ----------
115     log_file : str
116         The path to the file where the log is written to
117 
118     Returns
119     -------
120     status : bool
121         The status of the execution of the script described by the log
122         file (i.e. ``SUCCESS`` or ``FAILURE``)
123     """
124 
125     with open(log_file, 'r') as f:
126         data = f.readlines()
127     last_line = data[-1].strip()
128 
129     if 'Completed Successfully' in last_line:
130         return 'SUCCESS'
131     else:
132         return 'FAILURE'
133 
134 
135 def make_log_file(module):
136     """Create the log file name based on the module name.
137 
138     The name of the ``log_file`` is a combination of the name of the
139     module being logged and the current datetime.
140 
141     Parameters
142     ----------
143     module : str
144         The name of the module being logged.
145     production_mode : bool
146         Whether or not the output should be written to the production
147         environment.
148     path : str
149         Where to write the log if user-supplied path; default to
150         working dir.
151 
152     Returns
153     -------
154     log_file : str
155         The full path to where the log file will be written to.
156     """
157 
158     # Build filename
159     timestamp = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M')
160     filename = '{0}_{1}.log'.format(module, timestamp)
161 
162     # Determine save location
163     user = pwd.getpwuid(os.getuid()).pw_name
164     admin_account = get_config()['admin_account']
165     log_path = get_config()['log_dir']
166 
167     # For production
168     if user == admin_account and socket.gethostname()[0] == 'p':
169         log_file = os.path.join(log_path, 'prod', module, filename)
170 
171     # For test
172     elif user == admin_account and socket.gethostname()[0] == 't':
173         log_file = os.path.join(log_path, 'test', module, filename)
174 
175     # For dev
176     elif user == admin_account and socket.gethostname()[0] == 'd':
177         log_file = os.path.join(log_path, 'dev', module, filename)
178 
179     # For local (also write to dev)
180     else:
181         log_file = os.path.join(log_path, 'dev', module, filename)
182 
183     # Make sure parent directory exists
184     ensure_dir_exists(os.path.dirname(log_file))
185 
186     return log_file
187 
188 
189 def log_info(func):
190     """Decorator to log useful system information.
191 
192     This function can be used as a decorator to log user environment
193     and system information. Future packages we want to track can be
194     added or removed as necessary.
195 
196     Parameters
197     ----------
198     func : func
199         The function to decorate.
200 
201     Returns
202     -------
203     wrapped : func
204         The wrapped function.
205     """
206 
207     @wraps(func)
208     def wrapped(*args, **kwargs):
209 
210         # Log environment information
211         logging.info('User: ' + getpass.getuser())
212         logging.info('System: ' + socket.gethostname())
213         logging.info('Python Version: ' + sys.version.replace('\n', ''))
214         logging.info('Python Executable Path: ' + sys.executable)
215 
216         # Read in setup.py file to build list of required modules
217         with open(get_config()['setup_file']) as f:
218             data = f.readlines()
219 
220         for i, line in enumerate(data):
221             if 'REQUIRES = [' in line:
222                 begin = i + 1
223             elif 'setup(' in line:
224                 end = i - 2
225         required_modules = data[begin:end]
226 
227         # Clean up the module list
228         module_list = [item.strip().replace("'", "").replace(",", "").split("=")[0].split(">")[0].split("<")[0] for item in required_modules]
229 
230         # Log common module version information
231         for module in module_list:
232             try:
233                 mod = importlib.import_module(module)
234                 logging.info(module + ' Version: ' + mod.__version__)
235                 logging.info(module + ' Path: ' + mod.__path__[0])
236             except (ImportError, AttributeError) as err:
237                 logging.warning(err)
238 
239         logging.info('')
240 
241         # Call the function and time it
242         t1_cpu = time.clock()
243         t1_time = time.time()
244         func(*args, **kwargs)
245         t2_cpu = time.clock()
246         t2_time = time.time()
247 
248         # Log execution time
249         hours_cpu, remainder_cpu = divmod(t2_cpu - t1_cpu, 60 * 60)
250         minutes_cpu, seconds_cpu = divmod(remainder_cpu, 60)
251         hours_time, remainder_time = divmod(t2_time - t1_time, 60 * 60)
252         minutes_time, seconds_time = divmod(remainder_time, 60)
253         logging.info('Elapsed Real Time: {}:{}:{}'.format(int(hours_time), int(minutes_time), int(seconds_time)))
254         logging.info('Elapsed CPU Time: {}:{}:{}'.format(int(hours_cpu), int(minutes_cpu), int(seconds_cpu)))
255 
256     return wrapped
257 
258 
259 def log_fail(func):
260     """Decorator to log crashes in the decorated code.
261 
262     Parameters
263     ----------
264     func : func
265         The function to decorate.
266 
267     Returns
268     -------
269     wrapped : func
270         The wrapped function.
271     """
272 
273     @wraps(func)
274     def wrapped(*args, **kwargs):
275 
276         try:
277 
278             # Run the function
279             func(*args, **kwargs)
280             logging.info('Completed Successfully')
281 
282         except Exception:
283             logging.critical(traceback.format_exc())
284             logging.critical('CRASHED')
285 
286     return wrapped
287 
288 
289 def log_timing(func):
290     """Decorator to time a module or function within a code.
291 
292     Parameters
293     ----------
294     func : func
295         The function to time.
296 
297     Returns
298     -------
299     wrapped : func
300         The wrapped function. Will log the time."""
301 
302     def wrapped(*args, **kwargs):
303 
304         # Call the function and time it
305         t1_cpu = time.process_time()
306         t1_time = time.time()
307         func(*args, **kwargs)
308         t2_cpu = time.process_time()
309         t2_time = time.time()
310 
311         # Log execution time
312         hours_cpu, remainder_cpu = divmod(t2_cpu - t1_cpu, 60 * 60)
313         minutes_cpu, seconds_cpu = divmod(remainder_cpu, 60)
314         hours_time, remainder_time = divmod(t2_time - t1_time, 60 * 60)
315         minutes_time, seconds_time = divmod(remainder_time, 60)
316         logging.info('Elapsed Real Time of {}: {}:{}:{}'.format(func.__name__, int(hours_time), int(minutes_time), int(seconds_time)))
317         logging.info('Elapsed CPU Time of {}: {}:{}:{}'.format(func.__name__, int(hours_cpu), int(minutes_cpu), int(seconds_cpu)))
318 
319     return wrapped
320
```
--- 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/jwql/utils/logging_functions.py b/jwql/utils/logging_functions.py
--- a/jwql/utils/logging_functions.py
+++ b/jwql/utils/logging_functions.py
@@ -10,8 +10,9 @@
 -------
 
     - Catherine Martlin
-    - Alex Viana (WFC3 QL Version)
+    - Alex Viana (wfc3ql Version)
     - Matthew Bourque
+    - Jason Neal
 
 Use
 ---
@@ -59,6 +60,7 @@
 import os
 import pwd
 import socket
+import subprocess
 import sys
 import time
 import traceback
@@ -236,7 +238,10 @@
             except (ImportError, AttributeError) as err:
                 logging.warning(err)
 
-        logging.info('')
+        environment = subprocess.check_output(['conda', 'env', 'export'], universal_newlines=True)
+        logging.info('Environment:')
+        for line in environment.split('\n'):
+            logging.info(line)
 
         # Call the function and time it
         t1_cpu = time.clock()

{"golden_diff": "diff --git a/jwql/utils/logging_functions.py b/jwql/utils/logging_functions.py\n--- a/jwql/utils/logging_functions.py\n+++ b/jwql/utils/logging_functions.py\n@@ -10,8 +10,9 @@\n -------\n \n     - Catherine Martlin\n-    - Alex Viana (WFC3 QL Version)\n+    - Alex Viana (wfc3ql Version)\n     - Matthew Bourque\n+    - Jason Neal\n \n Use\n ---\n@@ -59,6 +60,7 @@\n import os\n import pwd\n import socket\n+import subprocess\n import sys\n import time\n import traceback\n@@ -236,7 +238,10 @@\n             except (ImportError, AttributeError) as err:\n                 logging.warning(err)\n \n-        logging.info('')\n+        environment = subprocess.check_output(['conda', 'env', 'export'], universal_newlines=True)\n+        logging.info('Environment:')\n+        for line in environment.split('\\n'):\n+            logging.info(line)\n \n         # Call the function and time it\n         t1_cpu = time.clock()\n", "issue": "Add a 'conda env export' to logging module\nWe could add the output of `conda env export` to the beginning of log files so that the exact environment being used to run a script is logged. \n", "before_files": [{"content": "\"\"\" Logging functions for the ``jwql`` automation platform.\n\nThis module provides decorators to log the execution of modules.  Log\nfiles are written to the ``logs/`` directory in the ``jwql`` central\nstorage area, named by module name and timestamp, e.g.\n``monitor_filesystem/monitor_filesystem_2018-06-20-15:22:51.log``\n\n\nAuthors\n-------\n\n    - Catherine Martlin\n    - Alex Viana (WFC3 QL Version)\n    - Matthew Bourque\n\nUse\n---\n\n    To log the execution of a module, use:\n    ::\n\n        import os\n        import logging\n\n        from jwql.logging.logging_functions import configure_logging\n        from jwql.logging.logging_functions import log_info\n        from jwql.logging.logging_functions import log_fail\n\n        @log_info\n        @log_fail\n        def my_main_function():\n            pass\n\n        if __name__ == '__main__':\n\n            module = os.path.basename(__file__).replace('.py', '')\n            configure_logging(module)\n\n            my_main_function()\n\nDependencies\n------------\n\n    The user must have a configuration file named ``config.json``\n    placed in the ``utils`` directory and it must contain keys for\n    ``log_dir`` and ``admin_account``.\n\nReferences\n----------\n    This code is adopted and updated from python routine\n    ``logging_functions.py`` written by Alex Viana, 2013 for the WFC3\n    Quicklook automation platform.\n\"\"\"\n\nimport datetime\nimport getpass\nimport importlib\nimport logging\nimport os\nimport pwd\nimport socket\nimport sys\nimport time\nimport traceback\n\nfrom functools import wraps\n\nfrom jwql.utils.permissions import set_permissions\nfrom jwql.utils.utils import get_config, ensure_dir_exists\n\n\ndef configure_logging(module):\n    \"\"\"Configure the log file with a standard logging format.\n\n    Parameters\n    ----------\n    module : str\n        The name of the module being logged.\n    production_mode : bool\n        Whether or not the output should be written to the production\n        environement.\n    path : str\n        Where to write the log if user-supplied path; default to working dir.\n\n    Returns\n    -------\n    log_file : str\n        The path to the file where the log is written to.\n    \"\"\"\n\n    # Determine log file location\n    log_file = make_log_file(module)\n\n    # Make sure no other root lhandlers exist before configuring the logger\n    for handler in logging.root.handlers[:]:\n        logging.root.removeHandler(handler)\n\n    # Create the log file and set the permissions\n    logging.basicConfig(filename=log_file,\n                        format='%(asctime)s %(levelname)s: %(message)s',\n                        datefmt='%m/%d/%Y %H:%M:%S %p',\n                        level=logging.INFO)\n    print('Log file initialized to {}'.format(log_file))\n    set_permissions(log_file)\n\n    return log_file\n\n\ndef get_log_status(log_file):\n    \"\"\"Returns the end status of the given ``log_file`` (i.e.\n    ``SUCCESS`` or ``FAILURE``)\n\n    Parameters\n    ----------\n    log_file : str\n        The path to the file where the log is written to\n\n    Returns\n    -------\n    status : bool\n        The status of the execution of the script described by the log\n        file (i.e. ``SUCCESS`` or ``FAILURE``)\n    \"\"\"\n\n    with open(log_file, 'r') as f:\n        data = f.readlines()\n    last_line = data[-1].strip()\n\n    if 'Completed Successfully' in last_line:\n        return 'SUCCESS'\n    else:\n        return 'FAILURE'\n\n\ndef make_log_file(module):\n    \"\"\"Create the log file name based on the module name.\n\n    The name of the ``log_file`` is a combination of the name of the\n    module being logged and the current datetime.\n\n    Parameters\n    ----------\n    module : str\n        The name of the module being logged.\n    production_mode : bool\n        Whether or not the output should be written to the production\n        environment.\n    path : str\n        Where to write the log if user-supplied path; default to\n        working dir.\n\n    Returns\n    -------\n    log_file : str\n        The full path to where the log file will be written to.\n    \"\"\"\n\n    # Build filename\n    timestamp = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M')\n    filename = '{0}_{1}.log'.format(module, timestamp)\n\n    # Determine save location\n    user = pwd.getpwuid(os.getuid()).pw_name\n    admin_account = get_config()['admin_account']\n    log_path = get_config()['log_dir']\n\n    # For production\n    if user == admin_account and socket.gethostname()[0] == 'p':\n        log_file = os.path.join(log_path, 'prod', module, filename)\n\n    # For test\n    elif user == admin_account and socket.gethostname()[0] == 't':\n        log_file = os.path.join(log_path, 'test', module, filename)\n\n    # For dev\n    elif user == admin_account and socket.gethostname()[0] == 'd':\n        log_file = os.path.join(log_path, 'dev', module, filename)\n\n    # For local (also write to dev)\n    else:\n        log_file = os.path.join(log_path, 'dev', module, filename)\n\n    # Make sure parent directory exists\n    ensure_dir_exists(os.path.dirname(log_file))\n\n    return log_file\n\n\ndef log_info(func):\n    \"\"\"Decorator to log useful system information.\n\n    This function can be used as a decorator to log user environment\n    and system information. Future packages we want to track can be\n    added or removed as necessary.\n\n    Parameters\n    ----------\n    func : func\n        The function to decorate.\n\n    Returns\n    -------\n    wrapped : func\n        The wrapped function.\n    \"\"\"\n\n    @wraps(func)\n    def wrapped(*args, **kwargs):\n\n        # Log environment information\n        logging.info('User: ' + getpass.getuser())\n        logging.info('System: ' + socket.gethostname())\n        logging.info('Python Version: ' + sys.version.replace('\\n', ''))\n        logging.info('Python Executable Path: ' + sys.executable)\n\n        # Read in setup.py file to build list of required modules\n        with open(get_config()['setup_file']) as f:\n            data = f.readlines()\n\n        for i, line in enumerate(data):\n            if 'REQUIRES = [' in line:\n                begin = i + 1\n            elif 'setup(' in line:\n                end = i - 2\n        required_modules = data[begin:end]\n\n        # Clean up the module list\n        module_list = [item.strip().replace(\"'\", \"\").replace(\",\", \"\").split(\"=\")[0].split(\">\")[0].split(\"<\")[0] for item in required_modules]\n\n        # Log common module version information\n        for module in module_list:\n            try:\n                mod = importlib.import_module(module)\n                logging.info(module + ' Version: ' + mod.__version__)\n                logging.info(module + ' Path: ' + mod.__path__[0])\n            except (ImportError, AttributeError) as err:\n                logging.warning(err)\n\n        logging.info('')\n\n        # Call the function and time it\n        t1_cpu = time.clock()\n        t1_time = time.time()\n        func(*args, **kwargs)\n        t2_cpu = time.clock()\n        t2_time = time.time()\n\n        # Log execution time\n        hours_cpu, remainder_cpu = divmod(t2_cpu - t1_cpu, 60 * 60)\n        minutes_cpu, seconds_cpu = divmod(remainder_cpu, 60)\n        hours_time, remainder_time = divmod(t2_time - t1_time, 60 * 60)\n        minutes_time, seconds_time = divmod(remainder_time, 60)\n        logging.info('Elapsed Real Time: {}:{}:{}'.format(int(hours_time), int(minutes_time), int(seconds_time)))\n        logging.info('Elapsed CPU Time: {}:{}:{}'.format(int(hours_cpu), int(minutes_cpu), int(seconds_cpu)))\n\n    return wrapped\n\n\ndef log_fail(func):\n    \"\"\"Decorator to log crashes in the decorated code.\n\n    Parameters\n    ----------\n    func : func\n        The function to decorate.\n\n    Returns\n    -------\n    wrapped : func\n        The wrapped function.\n    \"\"\"\n\n    @wraps(func)\n    def wrapped(*args, **kwargs):\n\n        try:\n\n            # Run the function\n            func(*args, **kwargs)\n            logging.info('Completed Successfully')\n\n        except Exception:\n            logging.critical(traceback.format_exc())\n            logging.critical('CRASHED')\n\n    return wrapped\n\n\ndef log_timing(func):\n    \"\"\"Decorator to time a module or function within a code.\n\n    Parameters\n    ----------\n    func : func\n        The function to time.\n\n    Returns\n    -------\n    wrapped : func\n        The wrapped function. Will log the time.\"\"\"\n\n    def wrapped(*args, **kwargs):\n\n        # Call the function and time it\n        t1_cpu = time.process_time()\n        t1_time = time.time()\n        func(*args, **kwargs)\n        t2_cpu = time.process_time()\n        t2_time = time.time()\n\n        # Log execution time\n        hours_cpu, remainder_cpu = divmod(t2_cpu - t1_cpu, 60 * 60)\n        minutes_cpu, seconds_cpu = divmod(remainder_cpu, 60)\n        hours_time, remainder_time = divmod(t2_time - t1_time, 60 * 60)\n        minutes_time, seconds_time = divmod(remainder_time, 60)\n        logging.info('Elapsed Real Time of {}: {}:{}:{}'.format(func.__name__, int(hours_time), int(minutes_time), int(seconds_time)))\n        logging.info('Elapsed CPU Time of {}: {}:{}:{}'.format(func.__name__, int(hours_cpu), int(minutes_cpu), int(seconds_cpu)))\n\n    return wrapped\n", "path": "jwql/utils/logging_functions.py"}], "after_files": [{"content": "\"\"\" Logging functions for the ``jwql`` automation platform.\n\nThis module provides decorators to log the execution of modules.  Log\nfiles are written to the ``logs/`` directory in the ``jwql`` central\nstorage area, named by module name and timestamp, e.g.\n``monitor_filesystem/monitor_filesystem_2018-06-20-15:22:51.log``\n\n\nAuthors\n-------\n\n    - Catherine Martlin\n    - Alex Viana (wfc3ql Version)\n    - Matthew Bourque\n    - Jason Neal\n\nUse\n---\n\n    To log the execution of a module, use:\n    ::\n\n        import os\n        import logging\n\n        from jwql.logging.logging_functions import configure_logging\n        from jwql.logging.logging_functions import log_info\n        from jwql.logging.logging_functions import log_fail\n\n        @log_info\n        @log_fail\n        def my_main_function():\n            pass\n\n        if __name__ == '__main__':\n\n            module = os.path.basename(__file__).replace('.py', '')\n            configure_logging(module)\n\n            my_main_function()\n\nDependencies\n------------\n\n    The user must have a configuration file named ``config.json``\n    placed in the ``utils`` directory and it must contain keys for\n    ``log_dir`` and ``admin_account``.\n\nReferences\n----------\n    This code is adopted and updated from python routine\n    ``logging_functions.py`` written by Alex Viana, 2013 for the WFC3\n    Quicklook automation platform.\n\"\"\"\n\nimport datetime\nimport getpass\nimport importlib\nimport logging\nimport os\nimport pwd\nimport socket\nimport subprocess\nimport sys\nimport time\nimport traceback\n\nfrom functools import wraps\n\nfrom jwql.utils.permissions import set_permissions\nfrom jwql.utils.utils import get_config, ensure_dir_exists\n\n\ndef configure_logging(module):\n    \"\"\"Configure the log file with a standard logging format.\n\n    Parameters\n    ----------\n    module : str\n        The name of the module being logged.\n    production_mode : bool\n        Whether or not the output should be written to the production\n        environement.\n    path : str\n        Where to write the log if user-supplied path; default to working dir.\n\n    Returns\n    -------\n    log_file : str\n        The path to the file where the log is written to.\n    \"\"\"\n\n    # Determine log file location\n    log_file = make_log_file(module)\n\n    # Make sure no other root lhandlers exist before configuring the logger\n    for handler in logging.root.handlers[:]:\n        logging.root.removeHandler(handler)\n\n    # Create the log file and set the permissions\n    logging.basicConfig(filename=log_file,\n                        format='%(asctime)s %(levelname)s: %(message)s',\n                        datefmt='%m/%d/%Y %H:%M:%S %p',\n                        level=logging.INFO)\n    print('Log file initialized to {}'.format(log_file))\n    set_permissions(log_file)\n\n    return log_file\n\n\ndef get_log_status(log_file):\n    \"\"\"Returns the end status of the given ``log_file`` (i.e.\n    ``SUCCESS`` or ``FAILURE``)\n\n    Parameters\n    ----------\n    log_file : str\n        The path to the file where the log is written to\n\n    Returns\n    -------\n    status : bool\n        The status of the execution of the script described by the log\n        file (i.e. ``SUCCESS`` or ``FAILURE``)\n    \"\"\"\n\n    with open(log_file, 'r') as f:\n        data = f.readlines()\n    last_line = data[-1].strip()\n\n    if 'Completed Successfully' in last_line:\n        return 'SUCCESS'\n    else:\n        return 'FAILURE'\n\n\ndef make_log_file(module):\n    \"\"\"Create the log file name based on the module name.\n\n    The name of the ``log_file`` is a combination of the name of the\n    module being logged and the current datetime.\n\n    Parameters\n    ----------\n    module : str\n        The name of the module being logged.\n    production_mode : bool\n        Whether or not the output should be written to the production\n        environment.\n    path : str\n        Where to write the log if user-supplied path; default to\n        working dir.\n\n    Returns\n    -------\n    log_file : str\n        The full path to where the log file will be written to.\n    \"\"\"\n\n    # Build filename\n    timestamp = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M')\n    filename = '{0}_{1}.log'.format(module, timestamp)\n\n    # Determine save location\n    user = pwd.getpwuid(os.getuid()).pw_name\n    admin_account = get_config()['admin_account']\n    log_path = get_config()['log_dir']\n\n    # For production\n    if user == admin_account and socket.gethostname()[0] == 'p':\n        log_file = os.path.join(log_path, 'prod', module, filename)\n\n    # For test\n    elif user == admin_account and socket.gethostname()[0] == 't':\n        log_file = os.path.join(log_path, 'test', module, filename)\n\n    # For dev\n    elif user == admin_account and socket.gethostname()[0] == 'd':\n        log_file = os.path.join(log_path, 'dev', module, filename)\n\n    # For local (also write to dev)\n    else:\n        log_file = os.path.join(log_path, 'dev', module, filename)\n\n    # Make sure parent directory exists\n    ensure_dir_exists(os.path.dirname(log_file))\n\n    return log_file\n\n\ndef log_info(func):\n    \"\"\"Decorator to log useful system information.\n\n    This function can be used as a decorator to log user environment\n    and system information. Future packages we want to track can be\n    added or removed as necessary.\n\n    Parameters\n    ----------\n    func : func\n        The function to decorate.\n\n    Returns\n    -------\n    wrapped : func\n        The wrapped function.\n    \"\"\"\n\n    @wraps(func)\n    def wrapped(*args, **kwargs):\n\n        # Log environment information\n        logging.info('User: ' + getpass.getuser())\n        logging.info('System: ' + socket.gethostname())\n        logging.info('Python Version: ' + sys.version.replace('\\n', ''))\n        logging.info('Python Executable Path: ' + sys.executable)\n\n        # Read in setup.py file to build list of required modules\n        with open(get_config()['setup_file']) as f:\n            data = f.readlines()\n\n        for i, line in enumerate(data):\n            if 'REQUIRES = [' in line:\n                begin = i + 1\n            elif 'setup(' in line:\n                end = i - 2\n        required_modules = data[begin:end]\n\n        # Clean up the module list\n        module_list = [item.strip().replace(\"'\", \"\").replace(\",\", \"\").split(\"=\")[0].split(\">\")[0].split(\"<\")[0] for item in required_modules]\n\n        # Log common module version information\n        for module in module_list:\n            try:\n                mod = importlib.import_module(module)\n                logging.info(module + ' Version: ' + mod.__version__)\n                logging.info(module + ' Path: ' + mod.__path__[0])\n            except (ImportError, AttributeError) as err:\n                logging.warning(err)\n\n        environment = subprocess.check_output(['conda', 'env', 'export'], universal_newlines=True)\n        logging.info('Environment:')\n        for line in environment.split('\\n'):\n            logging.info(line)\n\n        # Call the function and time it\n        t1_cpu = time.clock()\n        t1_time = time.time()\n        func(*args, **kwargs)\n        t2_cpu = time.clock()\n        t2_time = time.time()\n\n        # Log execution time\n        hours_cpu, remainder_cpu = divmod(t2_cpu - t1_cpu, 60 * 60)\n        minutes_cpu, seconds_cpu = divmod(remainder_cpu, 60)\n        hours_time, remainder_time = divmod(t2_time - t1_time, 60 * 60)\n        minutes_time, seconds_time = divmod(remainder_time, 60)\n        logging.info('Elapsed Real Time: {}:{}:{}'.format(int(hours_time), int(minutes_time), int(seconds_time)))\n        logging.info('Elapsed CPU Time: {}:{}:{}'.format(int(hours_cpu), int(minutes_cpu), int(seconds_cpu)))\n\n    return wrapped\n\n\ndef log_fail(func):\n    \"\"\"Decorator to log crashes in the decorated code.\n\n    Parameters\n    ----------\n    func : func\n        The function to decorate.\n\n    Returns\n    -------\n    wrapped : func\n        The wrapped function.\n    \"\"\"\n\n    @wraps(func)\n    def wrapped(*args, **kwargs):\n\n        try:\n\n            # Run the function\n            func(*args, **kwargs)\n            logging.info('Completed Successfully')\n\n        except Exception:\n            logging.critical(traceback.format_exc())\n            logging.critical('CRASHED')\n\n    return wrapped\n\n\ndef log_timing(func):\n    \"\"\"Decorator to time a module or function within a code.\n\n    Parameters\n    ----------\n    func : func\n        The function to time.\n\n    Returns\n    -------\n    wrapped : func\n        The wrapped function. Will log the time.\"\"\"\n\n    def wrapped(*args, **kwargs):\n\n        # Call the function and time it\n        t1_cpu = time.process_time()\n        t1_time = time.time()\n        func(*args, **kwargs)\n        t2_cpu = time.process_time()\n        t2_time = time.time()\n\n        # Log execution time\n        hours_cpu, remainder_cpu = divmod(t2_cpu - t1_cpu, 60 * 60)\n        minutes_cpu, seconds_cpu = divmod(remainder_cpu, 60)\n        hours_time, remainder_time = divmod(t2_time - t1_time, 60 * 60)\n        minutes_time, seconds_time = divmod(remainder_time, 60)\n        logging.info('Elapsed Real Time of {}: {}:{}:{}'.format(func.__name__, int(hours_time), int(minutes_time), int(seconds_time)))\n        logging.info('Elapsed CPU Time of {}: {}:{}:{}'.format(func.__name__, int(hours_cpu), int(minutes_cpu), int(seconds_cpu)))\n\n    return wrapped\n", "path": "jwql/utils/logging_functions.py"}]}