diff --git a/app/__init__.py b/app/__init__.py index ae4c0be1..327976b4 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -17,7 +17,7 @@ from flask import render_template from flask.logging import default_handler from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate -from flask_login import LoginManager +from flask_login import LoginManager, current_user from flask_mail import Mail from flask_bootstrap import Bootstrap from flask_moment import Moment @@ -82,7 +82,7 @@ def postgresql_server_error(e): return render_raw_html("error_503.html", SCOVERSION=sco_version.SCOVERSION), 503 -class RequestFormatter(logging.Formatter): +class LogRequestFormatter(logging.Formatter): """Ajoute URL et remote_addr for logging""" def format(self, record): @@ -92,6 +92,31 @@ class RequestFormatter(logging.Formatter): else: record.url = None record.remote_addr = None + record.sco_user = current_user + + return super().format(record) + + +class LogExceptionFormatter(logging.Formatter): + """Formatteur pour les exceptions: ajoute détails""" + + def format(self, record): + if has_request_context(): + record.url = request.url + record.remote_addr = request.remote_addr + record.http_referrer = request.referrer + record.http_method = request.method + if request.method == "GET": + record.http_params = str(request.args) + else: + record.http_params = "(post data not loggued)" + else: + record.url = None + record.remote_addr = None + record.http_referrer = None + record.http_method = None + record.http_params = None + record.sco_user = current_user return super().format(record) @@ -148,9 +173,16 @@ def create_app(config_class=DevConfig): absences_bp, url_prefix="/ScoDoc//Scolarite/Absences" ) app.register_blueprint(api_bp, url_prefix="/ScoDoc/api") - scodoc_exc_formatter = RequestFormatter( - "[%(asctime)s] %(remote_addr)s requested %(url)s\n" - "%(levelname)s in %(module)s: %(message)s" + scodoc_log_formatter = LogRequestFormatter( + "[%(asctime)s] %(sco_user)s@%(remote_addr)s requested %(url)s\n" + "%(levelname)s: %(message)s" + ) + scodoc_exc_formatter = LogExceptionFormatter( + "[%(asctime)s] %(sco_user)s@%(remote_addr)s requested %(url)s\n" + "%(levelname)s: %(message)s\n" + "Referrer: %(http_referrer)s\n" + "Method: %(http_method)s\n" + "Params: %(http_params)s\n" ) if not app.testing: if not app.debug: @@ -179,7 +211,7 @@ def create_app(config_class=DevConfig): app.logger.addHandler(mail_handler) else: # Pour logs en DEV uniquement: - default_handler.setFormatter(scodoc_exc_formatter) + default_handler.setFormatter(scodoc_log_formatter) # Config logs pour DEV et PRODUCTION # Configuration des logs (actifs aussi en mode development) @@ -188,9 +220,17 @@ def create_app(config_class=DevConfig): file_handler = WatchedFileHandler( app.config["SCODOC_LOG_FILE"], encoding="utf-8" ) - file_handler.setFormatter(scodoc_exc_formatter) + file_handler.setFormatter(scodoc_log_formatter) file_handler.setLevel(logging.INFO) app.logger.addHandler(file_handler) + # Log pour les erreurs (exceptions) uniquement: + # usually /opt/scodoc-data/log/scodoc_exc.log + file_handler = WatchedFileHandler( + app.config["SCODOC_ERR_FILE"], encoding="utf-8" + ) + file_handler.setFormatter(scodoc_exc_formatter) + file_handler.setLevel(logging.ERROR) + app.logger.addHandler(file_handler) # app.logger.setLevel(logging.INFO) app.logger.info(f"{sco_version.SCONAME} {sco_version.SCOVERSION} startup") diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index fc5138cf..f4efae92 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -53,7 +53,7 @@ from flask import g, current_app from PIL import Image as PILImage -from flask import g, url_for, request +from flask import g, url_for, request, make_response from config import Config from app import log @@ -558,6 +558,17 @@ def sendResult(REQUEST, data, name=None, format=None, force_outer_xml_tag=True): raise ValueError("invalid format: %s" % format) +def send_file(self, data, filename, suffix="", mime=None, attached=False): + if suffix: + filename += suffix + filename = make_filename(filename) + response = make_response(data) + response.headers["Content-Type"] = mime + if attached: + response.headers["Content-Disposition"] = 'attachment; filename="%s"' % filename + return response + + def get_scodoc_version(): "return a string identifying ScoDoc version" return sco_version.SCOVERSION diff --git a/app/templates/error_500.html b/app/templates/error_500.html index e093a6af..23963376 100644 --- a/app/templates/error_500.html +++ b/app/templates/error_500.html @@ -11,7 +11,7 @@ ou écrire la liste "notes" notes@listes.univ-paris13.fr en indiquant la version du logiciel
- (plus d'informations sur les listes de diffusionvoir + (plus d'informations sur les listes de diffusion voir cette page).

diff --git a/config.py b/config.py index 2e424a58..78e81711 100755 --- a/config.py +++ b/config.py @@ -30,6 +30,8 @@ class Config: SCODOC_DIR = os.environ.get("SCODOC_DIR", "/opt/scodoc") SCODOC_VAR_DIR = os.environ.get("SCODOC_VAR_DIR", "/opt/scodoc-data") SCODOC_LOG_FILE = os.path.join(SCODOC_VAR_DIR, "log", "scodoc.log") + # evite confusion avec le log nginx scodoc_error.log: + SCODOC_ERR_FILE = os.path.join(SCODOC_VAR_DIR, "log", "scodoc_exc.log") # MAX_CONTENT_LENGTH = 10 * 1024 * 1024 # Flask uploads diff --git a/tools/etc/scodoc-logrotate b/tools/etc/scodoc-logrotate index 59e94103..275679c1 100644 --- a/tools/etc/scodoc-logrotate +++ b/tools/etc/scodoc-logrotate @@ -1,4 +1,13 @@ -/opt/scodoc-datalog/scodoc.log { +/opt/scodoc-data/log/scodoc.log { + weekly + missingok + rotate 64 + compress + notifempty + dateext + create 0644 scodoc scodoc +} +/opt/scodoc-datalog/scodoc_exc.log { weekly missingok rotate 64