Skip to content

Commit

Permalink
Merge 5266a07 into ff6798e
Browse files Browse the repository at this point in the history
  • Loading branch information
justanr committed Nov 18, 2017
2 parents ff6798e + 5266a07 commit 984ce9d
Show file tree
Hide file tree
Showing 35 changed files with 233 additions and 44 deletions.
4 changes: 4 additions & 0 deletions flaskbb/__init__.py
Expand Up @@ -10,4 +10,8 @@
:license: BSD, see LICENSE for more details.
"""
__version__ = '1.0' # noqa
import logging

logger = logging.getLogger(__name__)

from flaskbb.app import create_app # noqa
87 changes: 54 additions & 33 deletions flaskbb/app.py
Expand Up @@ -10,6 +10,7 @@
"""
import os
import logging
import logging.config
import time
from functools import partial

Expand Down Expand Up @@ -58,6 +59,9 @@
from flaskbb.plugins import spec


logger = logging.getLogger(__name__)


def create_app(config=None):
"""Creates the app.
Expand Down Expand Up @@ -324,63 +328,80 @@ def get_locale():

def configure_logging(app):
"""Configures logging."""
if app.config.get('USE_DEFAULT_LOGGING'):
configure_default_logging(app)

if app.config.get('LOG_CONF_FILE'):
logging.config.fileConfig(
app.config['LOG_CONF_FILE'], disable_existing_loggers=False
)

if app.config["SQLALCHEMY_ECHO"]:
# Ref: http://stackoverflow.com/a/8428546
@event.listens_for(Engine, "before_cursor_execute")
def before_cursor_execute(
conn, cursor, statement, parameters, context, executemany
):
conn.info.setdefault('query_start_time', []).append(time.time())

logs_folder = os.path.join(app.root_path, os.pardir, "logs")
@event.listens_for(Engine, "after_cursor_execute")
def after_cursor_execute(
conn, cursor, statement, parameters, context, executemany
):
total = time.time() - conn.info['query_start_time'].pop(-1)
app.logger.debug("Total Time: %f", total)


def configure_default_logging(app):
from logging.handlers import SMTPHandler

logs_folder = app.config.get('LOG_PATH')

if logs_folder is None:
logs_folder = os.path.join(app.root_path, os.pardir, "logs")

default_log_format = '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'

formatter = logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]')
app.config.get('LOG_FORMAT') or default_log_format
)

info_log = os.path.join(logs_folder, app.config['INFO_LOG'])

info_file_handler = logging.handlers.RotatingFileHandler(
info_log,
maxBytes=100000,
backupCount=10
info_log, maxBytes=100000, backupCount=10
)

info_file_handler.setLevel(logging.INFO)
log_level = app.config.get('LOG_LEVEL') or logging.INFO

info_file_handler.setLevel(log_level)
info_file_handler.setFormatter(formatter)
app.logger.addHandler(info_file_handler)

error_log = os.path.join(logs_folder, app.config['ERROR_LOG'])

error_file_handler = logging.handlers.RotatingFileHandler(
error_log,
maxBytes=100000,
backupCount=10
error_log, maxBytes=100000, backupCount=10
)

error_file_handler.setLevel(logging.ERROR)
error_file_handler.setFormatter(formatter)
app.logger.addHandler(error_file_handler)

if app.config["SEND_LOGS"]:
mail_handler = \
SMTPHandler(
app.config['MAIL_SERVER'],
app.config['MAIL_DEFAULT_SENDER'],
app.config['ADMINS'],
'application error, no admins specified',
(app.config['MAIL_USERNAME'], app.config['MAIL_PASSWORD'])
)

mail_handler.setLevel(logging.ERROR)
mail_handler.setFormatter(formatter)
app.logger.addHandler(mail_handler)
configure_mail_logs(app)

if app.config["SQLALCHEMY_ECHO"]:
# Ref: http://stackoverflow.com/a/8428546
@event.listens_for(Engine, "before_cursor_execute")
def before_cursor_execute(conn, cursor, statement,
parameters, context, executemany):
conn.info.setdefault('query_start_time', []).append(time.time())

@event.listens_for(Engine, "after_cursor_execute")
def after_cursor_execute(conn, cursor, statement,
parameters, context, executemany):
total = time.time() - conn.info['query_start_time'].pop(-1)
app.logger.debug("Total Time: %f", total)
def configure_mail_logs(app):
mail_handler = SMTPHandler(
app.config['MAIL_SERVER'], app.config['MAIL_DEFAULT_SENDER'],
app.config['ADMINS'], 'application error, no admins specified',
(app.config['MAIL_USERNAME'], app.config['MAIL_PASSWORD'])
)

mail_handler.setLevel(logging.ERROR)
mail_handler.setFormatter(formatter)
app.logger.addHandler(mail_handler)


def load_plugins(app):
Expand Down
3 changes: 3 additions & 0 deletions flaskbb/auth/__init__.py
@@ -0,0 +1,3 @@
import logging

logger = logging.getLogger(__name__)
5 changes: 5 additions & 0 deletions flaskbb/auth/forms.py
Expand Up @@ -8,6 +8,7 @@
:copyright: (c) 2014 by the FlaskBB Team.
:license: BSD, see LICENSE for more details.
"""
import logging
from flask_wtf import FlaskForm
from wtforms import (StringField, PasswordField, BooleanField, HiddenField,
SubmitField, SelectField)
Expand All @@ -20,6 +21,10 @@
from flaskbb.utils.helpers import time_utcnow
from flaskbb.utils.fields import RecaptchaField


logger = logging.getLogger(__name__)


USERNAME_RE = r'^[\w.+-]+$'
is_valid_username = regexp(
USERNAME_RE, message=_("You can only use letters, numbers or dashes.")
Expand Down
5 changes: 5 additions & 0 deletions flaskbb/auth/views.py
Expand Up @@ -10,6 +10,7 @@
:license: BSD, see LICENSE for more details.
"""
from datetime import datetime
import logging

from flask import Blueprint, flash, g, redirect, request, url_for
from flask.views import MethodView
Expand All @@ -33,6 +34,10 @@
from flaskbb.utils.settings import flaskbb_config
from flaskbb.utils.tokens import get_token_status


logger = logging.getLogger(__name__)


auth = Blueprint("auth", __name__)


Expand Down
11 changes: 10 additions & 1 deletion flaskbb/cli/main.py
Expand Up @@ -504,7 +504,8 @@ def generate_config(development, output, force):
"mail_admin_address": "admin@yourdomain",
"secret_key": binascii.hexlify(os.urandom(24)).decode(),
"csrf_secret_key": binascii.hexlify(os.urandom(24)).decode(),
"timestamp": datetime.utcnow().strftime("%A, %d. %B %Y at %H:%M")
"timestamp": datetime.utcnow().strftime("%A, %d. %B %Y at %H:%M"),
"log_config_path": "",
}

if not force:
Expand Down Expand Up @@ -615,6 +616,14 @@ def generate_config(development, output, force):
click.style("Mail Admin Email", fg="magenta"),
default=default_conf.get("mail_admin_address"))

click.secho("Optional filepath to load a logging configuration file from. "
"See the Python logging documentation for more detail.\n"
"\thttps://docs.python.org/library/logging.config.html#logging-config-fileformat",
fg="cyan")
default_conf["log_config_path"] =click.prompt(
click.style("Logging Config Path", fg="magenta"),
default=default_conf.get("log_config_path"))

write_config(default_conf, config_template, config_path)

# Finished
Expand Down
1 change: 1 addition & 0 deletions flaskbb/configs/config.cfg.template
Expand Up @@ -154,6 +154,7 @@ ADMINS = ["{{ mail_admin_address }}"]
# If SEND_LOGS is set to True, the admins (see the mail configuration) will
# recieve the error logs per email.
SEND_LOGS = False
LOG_CONF_FILE = {{ log_config_path }}


# FlaskBB Settings
Expand Down
39 changes: 37 additions & 2 deletions flaskbb/configs/default.py
Expand Up @@ -47,15 +47,48 @@ class DefaultConfig(object):
# This only affects the url generation with 'url_for'.
PREFERRED_URL_SCHEME = "http"

# Logging Settings
# ------------------------------
# This config section will deal with the logging settings
# for FlaskBB, adjust as needed.

# Logging Config Path
# see https://docs.python.org/library/logging.config.html#logging.config.fileConfig
# for more details. Should either be None or a path to a file
# If this is set to a path, consider setting USE_DEFAULT_LOGGING to False
# otherwise there may be interactions between the log configuration file
# and the default logging setting.
#
# If set to a file path, this should be an absolute file path
LOG_CONF_FILE = None

# When set to True this will enable the default
# FlaskBB logging configuration which uses the settings
# below to determine logging
USE_DEFAULT_LOGGING = True

# Log format FlaskBB will use
LOG_FORMAT = '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'

# Log level FlaskBB will use
LOG_LEVEL = "INFO"

# If SEND_LOGS is set to True, the admins (see the mail configuration) will
# recieve the error logs per email.
SEND_LOGS = False

# The filename for the info and error logs. The logfiles are stored at
# flaskbb/logs
# Path to store the INFO and ERROR logs
# If None this defaults to flaskbb/logs
#
# If set to a file path, this should be an absolute path
LOG_PATH = None

# The filename for the info and error logs. The logfiles are stored
# at the path specified in LOG_PATH
INFO_LOG = "info.log"
ERROR_LOG = "error.log"


# Database
# ------------------------------
# For PostgresSQL:
Expand Down Expand Up @@ -191,6 +224,8 @@ class DefaultConfig(object):
MESSAGE_URL_PREFIX = "/message"
AUTH_URL_PREFIX = "/auth"
ADMIN_URL_PREFIX = "/admin"


# Remove dead plugins - useful if you want to migrate your instance
# somewhere else and forgot to reinstall the plugins.
# If set to `False` it will NOT remove plugins that are NOT installed on
Expand Down
4 changes: 4 additions & 0 deletions flaskbb/email.py
Expand Up @@ -8,6 +8,7 @@
:copyright: (c) 2014 by the FlaskBB Team.
:license: BSD, see LICENSE for more details.
"""
import logging
from flask import render_template
from flask_mail import Message
from flask_babelplus import lazy_gettext as _
Expand All @@ -16,6 +17,9 @@
from flaskbb.utils.tokens import make_token


logger = logging.getLogger(__name__)


@celery.task
def send_reset_token(user):
"""Sends the reset token to the user's email address.
Expand Down
3 changes: 3 additions & 0 deletions flaskbb/forum/__init__.py
@@ -0,0 +1,3 @@
import logging

logger = logging.getLogger(__name__)
4 changes: 4 additions & 0 deletions flaskbb/forum/forms.py
Expand Up @@ -8,6 +8,7 @@
:copyright: (c) 2014 by the FlaskBB Team.
:license: BSD, see LICENSE for more details.
"""
import logging
from flask_wtf import FlaskForm
from wtforms import (TextAreaField, StringField, SelectMultipleField,
BooleanField, SubmitField)
Expand All @@ -18,6 +19,9 @@
from flaskbb.user.models import User


logger = logging.getLogger(__name__)


class QuickreplyForm(FlaskForm):
content = TextAreaField(_("Quick reply"), validators=[
DataRequired(message=_("You cannot post a reply without content."))])
Expand Down
4 changes: 4 additions & 0 deletions flaskbb/forum/models.py
Expand Up @@ -9,6 +9,7 @@
:license: BSD, see LICENSE for more details.
"""
from datetime import timedelta
import logging

from flask import abort, url_for
from sqlalchemy.orm import aliased
Expand All @@ -21,6 +22,9 @@
from flaskbb.utils.settings import flaskbb_config


logger = logging.getLogger(__name__)


moderators = db.Table(
'moderators',
db.Column('user_id', db.Integer(), db.ForeignKey('users.id'),
Expand Down
6 changes: 5 additions & 1 deletion flaskbb/forum/views.py
Expand Up @@ -9,6 +9,7 @@
:copyright: (c) 2014 by the FlaskBB Team.
:license: BSD, see LICENSE for more details.
'''
import logging
import math

from flask import (Blueprint, abort, current_app, flash, redirect, request,
Expand All @@ -35,7 +36,10 @@
IsAtleastModeratorInForum)
from flaskbb.utils.settings import flaskbb_config

forum = Blueprint('forum', __name__)
logger = logging.getLogger(__name__)


forum = Blueprint("forum", __name__)


class ForumIndex(MethodView):
Expand Down
3 changes: 3 additions & 0 deletions flaskbb/management/__init__.py
@@ -0,0 +1,3 @@
import logging

logger = logging.getLogger(__name__)
4 changes: 4 additions & 0 deletions flaskbb/management/forms.py
Expand Up @@ -8,6 +8,7 @@
:copyright: (c) 2014 by the FlaskBB Team.
:license: BSD, see LICENSE for more details.
"""
import logging
from flask_wtf import FlaskForm
from wtforms import (BooleanField, HiddenField, IntegerField, PasswordField,
SelectField, StringField, SubmitField, TextAreaField)
Expand All @@ -26,6 +27,9 @@
from flask_allows import Permission


logger = logging.getLogger(__name__)


USERNAME_RE = r'^[\w.+-]+$'
is_username = regexp(USERNAME_RE,
message=_("You can only use letters, numbers or dashes."))
Expand Down
13 changes: 10 additions & 3 deletions flaskbb/management/models.py
Expand Up @@ -8,10 +8,17 @@
:copyright: (c) 2014 by the FlaskBB Team.
:license: BSD, see LICENSE for more details.
"""
from flaskbb._compat import iteritems
from flaskbb.extensions import db, cache
import logging

from flask_wtf import FlaskForm
from flaskbb._compat import iteritems, text_type
from flaskbb.extensions import cache, db
from flaskbb.utils.database import CRUDMixin
from flaskbb.utils.forms import generate_settings_form, SettingValueType
from flaskbb.utils.forms import SettingValueType, generate_settings_form
from wtforms import (BooleanField, FloatField, IntegerField, SelectField,
SelectMultipleField, TextField, validators)

logger = logging.getLogger(__name__)


class SettingsGroup(db.Model, CRUDMixin):
Expand Down

0 comments on commit 984ce9d

Please sign in to comment.