'Logging Flask Application in Heroku

I am trying to find a way to structure my code such that I can view logs in the production server hosted on Heroku.

Every tutorial I found seems to do logging like this:

How to show stdout logs in Heroku using Flask?

However, I am using the application factory pattern which utilizes Blueprints. As such here are some sample:

main.py

from app import create_app

app = create_app()

if __name__ == "__main__":
    app.run()

app/_ _ init _ _.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
...
db = SQLAlchemy() 
...
def create_app():
    app = Flask(__name__)
    ...
    db.init_app(app)

    from .routes.demo_blueprint import demo_blueprint 
    ...
    # Register the routes to the Flask object
    app.register_blueprint(demo_blueprint) 
    ...   

app/routes/demo_blueprint.py

from app import db
...
demo_blueprint = Blueprint('demo_blueprint', __name__)

@demo_blueprint.route('/demo', methods=['GET'])
...

In order to perform logging at the blueprint level, I would need to import app from main.py. However, this would cause an import error since __init__.py imports the blueprint before app is created. I was wondering if there were any work arounds for this.



Solution 1:[1]

Turns out it was a simple fix. To access the application context in the Blueprint, just use current_app. Following the example:

How to show stdout logs in Heroku using Flask?

main.py

from app import create_app

app = create_app()

if __name__ == "__main__":
    app.run()

app/_ _ init _ _.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
...
db = SQLAlchemy() 
...
def create_app():
    app = Flask(__name__)

    if __name__ != '__main__':
         gunicorn_logger = logging.getLogger('gunicorn.error')
         app.logger.handlers = gunicorn_logger.handlers
         app.logger.setLevel(gunicorn_logger.level)
    ...
    db.init_app(app)

    from .routes.demo_blueprint import demo_blueprint 
    ...
    # Register the routes to the Flask object
    app.register_blueprint(demo_blueprint) 
    ...   

app/routes/demo_blueprint.py

from flask import ***current_user***
from app import db
...
demo_blueprint = Blueprint('demo_blueprint', __name__)

@demo_blueprint.route('/demo', methods=['GET'])
def demo():
    current_app.logger.debug('debug message: %s', 'test')
...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jeff