"""Flask backend for opencode-blog-showcase. Application factory only — routes live in routes/, business logic in services/, queries in repositories/. See config.py for env overrides. """ import logging import os import uuid from flask import Flask, g, has_request_context, request import config import security from extensions import close_db from routes import api_bp, pages_bp, watchdog_bp class _RequestIdFilter(logging.Filter): """Inject `request_id` into every LogRecord so the formatter can print it. Reads Flask `g.request_id` when a request context is active; falls back to "-" for log lines emitted outside a request (startup, daemon threads). """ def filter(self, record): if has_request_context(): record.request_id = getattr(g, "request_id", "-") else: record.request_id = "-" return True _LOG_FORMAT = "%(asctime)s [%(process)d] [%(request_id)s] %(levelname)s: %(message)s" _handler = logging.StreamHandler() _handler.setFormatter(logging.Formatter(_LOG_FORMAT)) _handler.addFilter(_RequestIdFilter()) _root = logging.getLogger() _root.setLevel(logging.INFO) if not any(isinstance(h, logging.StreamHandler) and h.formatter for h in _root.handlers): _root.addHandler(_handler) logger = logging.getLogger(__name__) def create_app(): app = Flask( __name__, template_folder=os.path.join(config.BASE_DIR, "templates"), static_folder=os.path.join(config.BASE_DIR, "static"), ) app.secret_key = config.SECRET_KEY @app.before_request def _assign_request_id(): g.request_id = uuid.uuid4().hex[:8] @app.after_request def _log_request(response): logger.info( "%s %s -> %s (%s)", request.method, request.path, response.status_code, g.request_id, ) return response app.teardown_appcontext(close_db) security.init_app(app) app.register_blueprint(api_bp) app.register_blueprint(pages_bp) app.register_blueprint(watchdog_bp) return app app = create_app() if __name__ == "__main__": app.run(host="0.0.0.0", port=8090, debug=False)