Repository: CTFd/CTFd

Issue:
init_logs not called, no handlers installed
**Environment**:

  - CTFd Version/Commit: 6e8c7aaa50857fde0be87f694c134ce714e11221
  - Operating System: Linux (deployed via Docker)
  - Web Browser and Version: Firefox

**What happened?**
Since the 2.0 commit, it appears that `CTFd.utils.logging.init_logs` isn't called. As a result, `log()` calls aren't logged to the log files

**What did you expect to happen?**
Calls to `log()` should result in log files

**How to reproduce your issue**
from a console:
```
import logging
print(logging.getLogger('logins').handlers)
from CTFd.utils.logging import init_logs
init_logs(app)
print(logging.getLogger('logins').handlers)
```

**Any associated stack traces or error logs**
N/A



Discussion:

Resolving patch:
diff --git a/CTFd/__init__.py b/CTFd/__init__.py
--- a/CTFd/__init__.py
+++ b/CTFd/__init__.py
@@ -13,7 +13,7 @@
 from CTFd.utils.migrations import migrations, migrate, upgrade, stamp, create_database
 from CTFd.utils.sessions import CachingSessionInterface
 from CTFd.utils.updates import update_check
-from CTFd.utils.initialization import init_request_processors, init_template_filters, init_template_globals
+from CTFd.utils.initialization import init_request_processors, init_template_filters, init_template_globals, init_logs
 from CTFd.utils.events import socketio
 from CTFd.plugins import init_plugins
 
@@ -206,6 +206,7 @@ def create_app(config='CTFd.config.Config'):
         app.register_error_handler(500, general_error)
         app.register_error_handler(502, gateway_error)
 
+        init_logs(app)
         init_plugins(app)
 
         return app
diff --git a/CTFd/utils/initialization/__init__.py b/CTFd/utils/initialization/__init__.py
--- a/CTFd/utils/initialization/__init__.py
+++ b/CTFd/utils/initialization/__init__.py
@@ -33,6 +33,8 @@
 from sqlalchemy.exc import InvalidRequestError, IntegrityError
 
 import datetime
+import logging
+import os
 
 
 def init_template_filters(app):
@@ -64,6 +66,48 @@ def init_template_globals(app):
     app.jinja_env.globals.update(scores_visible=scores_visible)
 
 
+def init_logs(app):
+    logger_submissions = logging.getLogger('submissions')
+    logger_logins = logging.getLogger('logins')
+    logger_registrations = logging.getLogger('registrations')
+
+    logger_submissions.setLevel(logging.INFO)
+    logger_logins.setLevel(logging.INFO)
+    logger_registrations.setLevel(logging.INFO)
+
+    log_dir = app.config['LOG_FOLDER']
+    if not os.path.exists(log_dir):
+        os.makedirs(log_dir)
+
+    logs = {
+        'submissions': os.path.join(log_dir, 'submissions.log'),
+        'logins': os.path.join(log_dir, 'logins.log'),
+        'registrations': os.path.join(log_dir, 'registrations.log')
+    }
+
+    for log in logs.values():
+        if not os.path.exists(log):
+            open(log, 'a').close()
+
+    submission_log = logging.handlers.RotatingFileHandler(logs['submissions'], maxBytes=10000)
+    login_log = logging.handlers.RotatingFileHandler(logs['logins'], maxBytes=10000)
+    registration_log = logging.handlers.RotatingFileHandler(logs['registrations'], maxBytes=10000)
+
+    logger_submissions.addHandler(
+        submission_log
+    )
+    logger_logins.addHandler(
+        login_log
+    )
+    logger_registrations.addHandler(
+        registration_log
+    )
+
+    logger_submissions.propagate = 0
+    logger_logins.propagate = 0
+    logger_registrations.propagate = 0
+
+
 def init_request_processors(app):
     @app.context_processor
     def inject_user():
diff --git a/CTFd/utils/logging/__init__.py b/CTFd/utils/logging/__init__.py
--- a/CTFd/utils/logging/__init__.py
+++ b/CTFd/utils/logging/__init__.py
@@ -2,52 +2,9 @@
 from CTFd.utils.user import get_ip
 import logging
 import logging.handlers
-import os
 import time
 
 
-def init_logs(app):
-    logger_submissions = logging.getLogger('submissions')
-    logger_logins = logging.getLogger('logins')
-    logger_registrations = logging.getLogger('registrations')
-
-    logger_submissions.setLevel(logging.INFO)
-    logger_logins.setLevel(logging.INFO)
-    logger_registrations.setLevel(logging.INFO)
-
-    log_dir = app.config['LOG_FOLDER']
-    if not os.path.exists(log_dir):
-        os.makedirs(log_dir)
-
-    logs = {
-        'submissions': os.path.join(log_dir, 'submissions.log'),
-        'logins': os.path.join(log_dir, 'logins.log'),
-        'registrations': os.path.join(log_dir, 'registrations.log')
-    }
-
-    for log in logs.values():
-        if not os.path.exists(log):
-            open(log, 'a').close()
-
-    submission_log = logging.handlers.RotatingFileHandler(logs['submissions'], maxBytes=10000)
-    login_log = logging.handlers.RotatingFileHandler(logs['logins'], maxBytes=10000)
-    registration_log = logging.handlers.RotatingFileHandler(logs['registrations'], maxBytes=10000)
-
-    logger_submissions.addHandler(
-        submission_log
-    )
-    logger_logins.addHandler(
-        login_log
-    )
-    logger_registrations.addHandler(
-        registration_log
-    )
-
-    logger_submissions.propagate = 0
-    logger_logins.propagate = 0
-    logger_registrations.propagate = 0
-
-
 def log(logger, format, **kwargs):
     logger = logging.getLogger(logger)
     props = {


Test patch: