prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Set lemur to log to stdout
  When running lemur inside docker I would like to have it log everything to `stdout` so that I can forward logs to splunk. At the moment `lemur.config.py` has a `LEMUR_LOG` parameter that expects a filename. Is there a way to configure lemur to log to stdout instead of a file?
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `lemur/factory.py`
  Content:
  ```
  1 """
  2 .. module: lemur.factory
  3     :platform: Unix
  4     :synopsis: This module contains all the needed functions to allow
  5     the factory app creation.
  6 
  7     :copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
  8     :license: Apache, see LICENSE for more details.
  9 .. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
  10 
  11 """
  12 import os
  13 import imp
  14 import errno
  15 import pkg_resources
  16 
  17 from logging import Formatter, StreamHandler
  18 from logging.handlers import RotatingFileHandler
  19 
  20 from flask import Flask
  21 from lemur.common.health import mod as health
  22 from lemur.extensions import db, migrate, principal, smtp_mail, metrics
  23 
  24 
  25 DEFAULT_BLUEPRINTS = (
  26     health,
  27 )
  28 
  29 API_VERSION = 1
  30 
  31 
  32 def create_app(app_name=None, blueprints=None, config=None):
  33     """
  34     Lemur application factory
  35 
  36     :param config:
  37     :param app_name:
  38     :param blueprints:
  39     :return:
  40     """
  41     if not blueprints:
  42         blueprints = DEFAULT_BLUEPRINTS
  43     else:
  44         blueprints = blueprints + DEFAULT_BLUEPRINTS
  45 
  46     if not app_name:
  47         app_name = __name__
  48 
  49     app = Flask(app_name)
  50     configure_app(app, config)
  51     configure_blueprints(app, blueprints)
  52     configure_extensions(app)
  53     configure_logging(app)
  54     install_plugins(app)
  55 
  56     @app.teardown_appcontext
  57     def teardown(exception=None):
  58         if db.session:
  59             db.session.remove()
  60 
  61     return app
  62 
  63 
  64 def from_file(file_path, silent=False):
  65     """
  66     Updates the values in the config from a Python file.  This function
  67     behaves as if the file was imported as module with the
  68 
  69     :param file_path:
  70     :param silent:
  71     """
  72     d = imp.new_module('config')
  73     d.__file__ = file_path
  74     try:
  75         with open(file_path) as config_file:
  76             exec(compile(config_file.read(),  # nosec: config file safe
  77                  file_path, 'exec'), d.__dict__)
  78     except IOError as e:
  79         if silent and e.errno in (errno.ENOENT, errno.EISDIR):
  80             return False
  81         e.strerror = 'Unable to load configuration file (%s)' % e.strerror
  82         raise
  83     return d
  84 
  85 
  86 def configure_app(app, config=None):
  87     """
  88     Different ways of configuration
  89 
  90     :param app:
  91     :param config:
  92     :return:
  93     """
  94     # respect the config first
  95     if config and config != 'None':
  96         app.config['CONFIG_PATH'] = config
  97         app.config.from_object(from_file(config))
  98     else:
  99         try:
  100             app.config.from_envvar("LEMUR_CONF")
  101         except RuntimeError:
  102             # look in default paths
  103             if os.path.isfile(os.path.expanduser("~/.lemur/lemur.conf.py")):
  104                 app.config.from_object(from_file(os.path.expanduser("~/.lemur/lemur.conf.py")))
  105             else:
  106                 app.config.from_object(from_file(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default.conf.py')))
  107 
  108     # we don't use this
  109     app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
  110 
  111 
  112 def configure_extensions(app):
  113     """
  114     Attaches and configures any needed flask extensions
  115     to our app.
  116 
  117     :param app:
  118     """
  119     db.init_app(app)
  120     migrate.init_app(app, db)
  121     principal.init_app(app)
  122     smtp_mail.init_app(app)
  123     metrics.init_app(app)
  124 
  125 
  126 def configure_blueprints(app, blueprints):
  127     """
  128     We prefix our APIs with their given version so that we can support
  129     multiple concurrent API versions.
  130 
  131     :param app:
  132     :param blueprints:
  133     """
  134     for blueprint in blueprints:
  135         app.register_blueprint(blueprint, url_prefix="/api/{0}".format(API_VERSION))
  136 
  137 
  138 def configure_logging(app):
  139     """
  140     Sets up application wide logging.
  141 
  142     :param app:
  143     """
  144     handler = RotatingFileHandler(app.config.get('LOG_FILE', 'lemur.log'), maxBytes=10000000, backupCount=100)
  145 
  146     handler.setFormatter(Formatter(
  147         '%(asctime)s %(levelname)s: %(message)s '
  148         '[in %(pathname)s:%(lineno)d]'
  149     ))
  150 
  151     handler.setLevel(app.config.get('LOG_LEVEL', 'DEBUG'))
  152     app.logger.setLevel(app.config.get('LOG_LEVEL', 'DEBUG'))
  153     app.logger.addHandler(handler)
  154 
  155     stream_handler = StreamHandler()
  156     stream_handler.setLevel(app.config.get('LOG_LEVEL'))
  157     app.logger.addHandler(stream_handler)
  158 
  159 
  160 def install_plugins(app):
  161     """
  162     Installs new issuers that are not currently bundled with Lemur.
  163 
  164     :param app:
  165     :return:
  166     """
  167     from lemur.plugins import plugins
  168     from lemur.plugins.base import register
  169     # entry_points={
  170     #    'lemur.plugins': [
  171     #         'verisign = lemur_verisign.plugin:VerisignPlugin'
  172     #     ],
  173     # },
  174     for ep in pkg_resources.iter_entry_points('lemur.plugins'):
  175         try:
  176             plugin = ep.load()
  177         except Exception:
  178             import traceback
  179             app.logger.error("Failed to load plugin %r:\n%s\n" % (ep.name, traceback.format_exc()))
  180         else:
  181             register(plugin)
  182 
  183     # ensure that we have some way to notify
  184     with app.app_context():
  185         try:
  186             slug = app.config.get("LEMUR_DEFAULT_NOTIFICATION_PLUGIN", "email-notification")
  187             plugins.get(slug)
  188         except KeyError:
  189             raise Exception("Unable to location notification plugin: {slug}. Ensure that LEMUR_DEFAULT_NOTIFICATION_PLUGIN is set to a valid and installed notification plugin.".format(slug=slug))
  190
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/lemur/factory.py b/lemur/factory.py
  --- a/lemur/factory.py
  +++ b/lemur/factory.py
  @@ -153,7 +153,7 @@
       app.logger.addHandler(handler)
   
       stream_handler = StreamHandler()
  -    stream_handler.setLevel(app.config.get('LOG_LEVEL'))
  +    stream_handler.setLevel(app.config.get('LOG_LEVEL', 'DEBUG'))
       app.logger.addHandler(stream_handler)
  
verification_info: {"golden_diff": "diff --git a/lemur/factory.py b/lemur/factory.py\n--- a/lemur/factory.py\n+++ b/lemur/factory.py\n@@ -153,7 +153,7 @@\n     app.logger.addHandler(handler)\n \n     stream_handler = StreamHandler()\n-    stream_handler.setLevel(app.config.get('LOG_LEVEL'))\n+    stream_handler.setLevel(app.config.get('LOG_LEVEL', 'DEBUG'))\n     app.logger.addHandler(stream_handler)\n", "issue": "Set lemur to log to stdout\nWhen running lemur inside docker I would like to have it log everything to `stdout` so that I can forward logs to splunk. At the moment `lemur.config.py` has a `LEMUR_LOG` parameter that expects a filename. Is there a way to configure lemur to log to stdout instead of a file?\n", "before_files": [{"content": "\"\"\"\n.. module: lemur.factory\n    :platform: Unix\n    :synopsis: This module contains all the needed functions to allow\n    the factory app creation.\n\n    :copyright: (c) 2015 by Netflix Inc., see AUTHORS for more\n    :license: Apache, see LICENSE for more details.\n.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>\n\n\"\"\"\nimport os\nimport imp\nimport errno\nimport pkg_resources\n\nfrom logging import Formatter, StreamHandler\nfrom logging.handlers import RotatingFileHandler\n\nfrom flask import Flask\nfrom lemur.common.health import mod as health\nfrom lemur.extensions import db, migrate, principal, smtp_mail, metrics\n\n\nDEFAULT_BLUEPRINTS = (\n    health,\n)\n\nAPI_VERSION = 1\n\n\ndef create_app(app_name=None, blueprints=None, config=None):\n    \"\"\"\n    Lemur application factory\n\n    :param config:\n    :param app_name:\n    :param blueprints:\n    :return:\n    \"\"\"\n    if not blueprints:\n        blueprints = DEFAULT_BLUEPRINTS\n    else:\n        blueprints = blueprints + DEFAULT_BLUEPRINTS\n\n    if not app_name:\n        app_name = __name__\n\n    app = Flask(app_name)\n    configure_app(app, config)\n    configure_blueprints(app, blueprints)\n    configure_extensions(app)\n    configure_logging(app)\n    install_plugins(app)\n\n    @app.teardown_appcontext\n    def teardown(exception=None):\n        if db.session:\n            db.session.remove()\n\n    return app\n\n\ndef from_file(file_path, silent=False):\n    \"\"\"\n    Updates the values in the config from a Python file.  This function\n    behaves as if the file was imported as module with the\n\n    :param file_path:\n    :param silent:\n    \"\"\"\n    d = imp.new_module('config')\n    d.__file__ = file_path\n    try:\n        with open(file_path) as config_file:\n            exec(compile(config_file.read(),  # nosec: config file safe\n                 file_path, 'exec'), d.__dict__)\n    except IOError as e:\n        if silent and e.errno in (errno.ENOENT, errno.EISDIR):\n            return False\n        e.strerror = 'Unable to load configuration file (%s)' % e.strerror\n        raise\n    return d\n\n\ndef configure_app(app, config=None):\n    \"\"\"\n    Different ways of configuration\n\n    :param app:\n    :param config:\n    :return:\n    \"\"\"\n    # respect the config first\n    if config and config != 'None':\n        app.config['CONFIG_PATH'] = config\n        app.config.from_object(from_file(config))\n    else:\n        try:\n            app.config.from_envvar(\"LEMUR_CONF\")\n        except RuntimeError:\n            # look in default paths\n            if os.path.isfile(os.path.expanduser(\"~/.lemur/lemur.conf.py\")):\n                app.config.from_object(from_file(os.path.expanduser(\"~/.lemur/lemur.conf.py\")))\n            else:\n                app.config.from_object(from_file(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default.conf.py')))\n\n    # we don't use this\n    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\n\n\ndef configure_extensions(app):\n    \"\"\"\n    Attaches and configures any needed flask extensions\n    to our app.\n\n    :param app:\n    \"\"\"\n    db.init_app(app)\n    migrate.init_app(app, db)\n    principal.init_app(app)\n    smtp_mail.init_app(app)\n    metrics.init_app(app)\n\n\ndef configure_blueprints(app, blueprints):\n    \"\"\"\n    We prefix our APIs with their given version so that we can support\n    multiple concurrent API versions.\n\n    :param app:\n    :param blueprints:\n    \"\"\"\n    for blueprint in blueprints:\n        app.register_blueprint(blueprint, url_prefix=\"/api/{0}\".format(API_VERSION))\n\n\ndef configure_logging(app):\n    \"\"\"\n    Sets up application wide logging.\n\n    :param app:\n    \"\"\"\n    handler = RotatingFileHandler(app.config.get('LOG_FILE', 'lemur.log'), maxBytes=10000000, backupCount=100)\n\n    handler.setFormatter(Formatter(\n        '%(asctime)s %(levelname)s: %(message)s '\n        '[in %(pathname)s:%(lineno)d]'\n    ))\n\n    handler.setLevel(app.config.get('LOG_LEVEL', 'DEBUG'))\n    app.logger.setLevel(app.config.get('LOG_LEVEL', 'DEBUG'))\n    app.logger.addHandler(handler)\n\n    stream_handler = StreamHandler()\n    stream_handler.setLevel(app.config.get('LOG_LEVEL'))\n    app.logger.addHandler(stream_handler)\n\n\ndef install_plugins(app):\n    \"\"\"\n    Installs new issuers that are not currently bundled with Lemur.\n\n    :param app:\n    :return:\n    \"\"\"\n    from lemur.plugins import plugins\n    from lemur.plugins.base import register\n    # entry_points={\n    #    'lemur.plugins': [\n    #         'verisign = lemur_verisign.plugin:VerisignPlugin'\n    #     ],\n    # },\n    for ep in pkg_resources.iter_entry_points('lemur.plugins'):\n        try:\n            plugin = ep.load()\n        except Exception:\n            import traceback\n            app.logger.error(\"Failed to load plugin %r:\\n%s\\n\" % (ep.name, traceback.format_exc()))\n        else:\n            register(plugin)\n\n    # ensure that we have some way to notify\n    with app.app_context():\n        try:\n            slug = app.config.get(\"LEMUR_DEFAULT_NOTIFICATION_PLUGIN\", \"email-notification\")\n            plugins.get(slug)\n        except KeyError:\n            raise Exception(\"Unable to location notification plugin: {slug}. Ensure that LEMUR_DEFAULT_NOTIFICATION_PLUGIN is set to a valid and installed notification plugin.\".format(slug=slug))\n", "path": "lemur/factory.py"}], "after_files": [{"content": "\"\"\"\n.. module: lemur.factory\n    :platform: Unix\n    :synopsis: This module contains all the needed functions to allow\n    the factory app creation.\n\n    :copyright: (c) 2015 by Netflix Inc., see AUTHORS for more\n    :license: Apache, see LICENSE for more details.\n.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>\n\n\"\"\"\nimport os\nimport imp\nimport errno\nimport pkg_resources\n\nfrom logging import Formatter, StreamHandler\nfrom logging.handlers import RotatingFileHandler\n\nfrom flask import Flask\nfrom lemur.common.health import mod as health\nfrom lemur.extensions import db, migrate, principal, smtp_mail, metrics\n\n\nDEFAULT_BLUEPRINTS = (\n    health,\n)\n\nAPI_VERSION = 1\n\n\ndef create_app(app_name=None, blueprints=None, config=None):\n    \"\"\"\n    Lemur application factory\n\n    :param config:\n    :param app_name:\n    :param blueprints:\n    :return:\n    \"\"\"\n    if not blueprints:\n        blueprints = DEFAULT_BLUEPRINTS\n    else:\n        blueprints = blueprints + DEFAULT_BLUEPRINTS\n\n    if not app_name:\n        app_name = __name__\n\n    app = Flask(app_name)\n    configure_app(app, config)\n    configure_blueprints(app, blueprints)\n    configure_extensions(app)\n    configure_logging(app)\n    install_plugins(app)\n\n    @app.teardown_appcontext\n    def teardown(exception=None):\n        if db.session:\n            db.session.remove()\n\n    return app\n\n\ndef from_file(file_path, silent=False):\n    \"\"\"\n    Updates the values in the config from a Python file.  This function\n    behaves as if the file was imported as module with the\n\n    :param file_path:\n    :param silent:\n    \"\"\"\n    d = imp.new_module('config')\n    d.__file__ = file_path\n    try:\n        with open(file_path) as config_file:\n            exec(compile(config_file.read(),  # nosec: config file safe\n                 file_path, 'exec'), d.__dict__)\n    except IOError as e:\n        if silent and e.errno in (errno.ENOENT, errno.EISDIR):\n            return False\n        e.strerror = 'Unable to load configuration file (%s)' % e.strerror\n        raise\n    return d\n\n\ndef configure_app(app, config=None):\n    \"\"\"\n    Different ways of configuration\n\n    :param app:\n    :param config:\n    :return:\n    \"\"\"\n    # respect the config first\n    if config and config != 'None':\n        app.config['CONFIG_PATH'] = config\n        app.config.from_object(from_file(config))\n    else:\n        try:\n            app.config.from_envvar(\"LEMUR_CONF\")\n        except RuntimeError:\n            # look in default paths\n            if os.path.isfile(os.path.expanduser(\"~/.lemur/lemur.conf.py\")):\n                app.config.from_object(from_file(os.path.expanduser(\"~/.lemur/lemur.conf.py\")))\n            else:\n                app.config.from_object(from_file(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default.conf.py')))\n\n    # we don't use this\n    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\n\n\ndef configure_extensions(app):\n    \"\"\"\n    Attaches and configures any needed flask extensions\n    to our app.\n\n    :param app:\n    \"\"\"\n    db.init_app(app)\n    migrate.init_app(app, db)\n    principal.init_app(app)\n    smtp_mail.init_app(app)\n    metrics.init_app(app)\n\n\ndef configure_blueprints(app, blueprints):\n    \"\"\"\n    We prefix our APIs with their given version so that we can support\n    multiple concurrent API versions.\n\n    :param app:\n    :param blueprints:\n    \"\"\"\n    for blueprint in blueprints:\n        app.register_blueprint(blueprint, url_prefix=\"/api/{0}\".format(API_VERSION))\n\n\ndef configure_logging(app):\n    \"\"\"\n    Sets up application wide logging.\n\n    :param app:\n    \"\"\"\n    handler = RotatingFileHandler(app.config.get('LOG_FILE', 'lemur.log'), maxBytes=10000000, backupCount=100)\n\n    handler.setFormatter(Formatter(\n        '%(asctime)s %(levelname)s: %(message)s '\n        '[in %(pathname)s:%(lineno)d]'\n    ))\n\n    handler.setLevel(app.config.get('LOG_LEVEL', 'DEBUG'))\n    app.logger.setLevel(app.config.get('LOG_LEVEL', 'DEBUG'))\n    app.logger.addHandler(handler)\n\n    stream_handler = StreamHandler()\n    stream_handler.setLevel(app.config.get('LOG_LEVEL', 'DEBUG'))\n    app.logger.addHandler(stream_handler)\n\n\ndef install_plugins(app):\n    \"\"\"\n    Installs new issuers that are not currently bundled with Lemur.\n\n    :param app:\n    :return:\n    \"\"\"\n    from lemur.plugins import plugins\n    from lemur.plugins.base import register\n    # entry_points={\n    #    'lemur.plugins': [\n    #         'verisign = lemur_verisign.plugin:VerisignPlugin'\n    #     ],\n    # },\n    for ep in pkg_resources.iter_entry_points('lemur.plugins'):\n        try:\n            plugin = ep.load()\n        except Exception:\n            import traceback\n            app.logger.error(\"Failed to load plugin %r:\\n%s\\n\" % (ep.name, traceback.format_exc()))\n        else:\n            register(plugin)\n\n    # ensure that we have some way to notify\n    with app.app_context():\n        try:\n            slug = app.config.get(\"LEMUR_DEFAULT_NOTIFICATION_PLUGIN\", \"email-notification\")\n            plugins.get(slug)\n        except KeyError:\n            raise Exception(\"Unable to location notification plugin: {slug}. Ensure that LEMUR_DEFAULT_NOTIFICATION_PLUGIN is set to a valid and installed notification plugin.\".format(slug=slug))\n", "path": "lemur/factory.py"}]}