Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔊 configure logging #51

Merged
merged 4 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 58 additions & 16 deletions flask-data/smarter/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
@author: Paolo Cozzi <[email protected]>
"""

import os

from bson import ObjectId
import logging
from logging.config import dictConfig
from logging.handlers import SMTPHandler

from flask import Flask, redirect, url_for
from decouple import config
from flask import Flask, redirect, url_for, has_request_context, request
from flask.logging import default_handler
from flask_restful import Api
from flask.json import JSONEncoder
from flask_cors import CORS
Expand Down Expand Up @@ -40,6 +42,43 @@
}
})

mail_handler = SMTPHandler(
mailhost=(
config('EMAIL_HOST', default='localhost'),
config('EMAIL_PORT', cast=int, default=1025)
),
fromaddr=config('DEFAULT_FROM_EMAIL', default="[email protected]"),
toaddrs=[email.strip() for email in config(
'ADMINS', default="[email protected]").split(',')],
subject='SMARTER-backend Application Error',
credentials=(
config('EMAIL_HOST_USER', default=None),
config('EMAIL_HOST_PASSWORD', default=None)
),
secure=()
)
mail_handler.setLevel(logging.ERROR)


class RequestFormatter(logging.Formatter):
def format(self, record):
if has_request_context():
record.url = request.url
record.remote_addr = request.remote_addr
else:
record.url = None
record.remote_addr = None

return super().format(record)


formatter = RequestFormatter(
'[%(asctime)s] %(remote_addr)s requested %(url)s\n'
'%(levelname)s in %(module)s: %(message)s'
)
mail_handler.setFormatter(formatter)
default_handler.setFormatter(formatter)


class CustomJSONEncoder(JSONEncoder):
def default(self, obj):
Expand All @@ -51,17 +90,14 @@ def default(self, obj):


# https://stackoverflow.com/a/56474420/4385116
def create_app(config={}):
def create_app():
"""This function create Flask app. Is required by wsgi because it need to
be called after service is started and forked, not when importing the
module during initialization. To start the flask app, first import
the module and then create all the stuff by invoking this function
You need call the run method on the returned values to start acception
You need call the run method on the returned values to start accepting
requests

Args:
config (dict): pass parameters to this app (not yet defined)

Returns:
Flask: a flask initialized application
"""
Expand All @@ -70,6 +106,11 @@ def create_app(config={}):
CORS(app)
api = Api(app, errors=errors)

# check debug mode
if config('DEBUG', cast=bool, default=True):
# in debug mode, the default logging will be set to DEBUG level
app.debug = True

# deal with ObjectId in json responses
app.json_encoder = CustomJSONEncoder

Expand Down Expand Up @@ -107,21 +148,19 @@ def create_app(config={}):

# http://docs.mongoengine.org/projects/flask-mongoengine/en/latest/#configuration
app.config['MONGODB_SETTINGS'] = {
'host': 'mongodb://mongo/smarter',
'username': os.getenv("MONGODB_SMARTER_USER"),
'password': os.getenv("MONGODB_SMARTER_PASS"),
'host': config(
'MONGODB_SMARTER_DB',
default='mongodb://mongo/smarter'
),
'username': config('MONGODB_SMARTER_USER'),
'password': config("MONGODB_SMARTER_PASS"),
'authentication_source': 'admin',
'alias': DB_ALIAS,
# NOTE: This fixes "UserWarning: MongoClient opened before fork."
# I'm not aware of side effects yet. Default value is/was "True"
'connect': False
}

# override configuration with custom values
if 'host' in config:
app.logger.error(f"Setting custom host: {config['host']}")
app.config['MONGODB_SETTINGS']['host'] = config['host']

# connect to database
initialize_db(app)

Expand All @@ -133,6 +172,9 @@ def create_app(config={}):

app.logger.debug("Routes initialized")

if not app.debug:
app.logger.addHandler(mail_handler)

# add a redirect for the index page
@app.route('/smarter-api/')
def index():
Expand Down
6 changes: 4 additions & 2 deletions flask-data/smarter/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@author: Paolo Cozzi <[email protected]>
"""

import os
import json
import logging
import unittest
Expand All @@ -18,8 +19,9 @@
from app import create_app
from database.db import db, DB_ALIAS

# start application with custom values
app = create_app(config={'host': 'mongodb://mongo/test'})
# start application an override the default configuration
os.environ['MONGODB_SMARTER_DB'] = 'mongodb://mongo/test'
app = create_app()

# Get an instance of a logger
logger = logging.getLogger(__name__)
Expand Down
13 changes: 12 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ flask-mongoengine = "^1.0.0"
werkzeug = "~2.0"
coveralls = "^3.3.1"
coverage = "5.*"
python-decouple = "^3.8"

[build-system]
requires = ["poetry-core"]
Expand Down
Loading