Better logging. New log for exceptions: /opt/scodoc-data/log/scodoc_exc.log

This commit is contained in:
Emmanuel Viennet 2021-09-15 00:33:30 +02:00
parent de206674d9
commit 3fbda90a2f
5 changed files with 72 additions and 10 deletions

View File

@ -17,7 +17,7 @@ from flask import render_template
from flask.logging import default_handler from flask.logging import default_handler
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate from flask_migrate import Migrate
from flask_login import LoginManager from flask_login import LoginManager, current_user
from flask_mail import Mail from flask_mail import Mail
from flask_bootstrap import Bootstrap from flask_bootstrap import Bootstrap
from flask_moment import Moment 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 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""" """Ajoute URL et remote_addr for logging"""
def format(self, record): def format(self, record):
@ -92,6 +92,31 @@ class RequestFormatter(logging.Formatter):
else: else:
record.url = None record.url = None
record.remote_addr = 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) return super().format(record)
@ -148,9 +173,16 @@ def create_app(config_class=DevConfig):
absences_bp, url_prefix="/ScoDoc/<scodoc_dept>/Scolarite/Absences" absences_bp, url_prefix="/ScoDoc/<scodoc_dept>/Scolarite/Absences"
) )
app.register_blueprint(api_bp, url_prefix="/ScoDoc/api") app.register_blueprint(api_bp, url_prefix="/ScoDoc/api")
scodoc_exc_formatter = RequestFormatter( scodoc_log_formatter = LogRequestFormatter(
"[%(asctime)s] %(remote_addr)s requested %(url)s\n" "[%(asctime)s] %(sco_user)s@%(remote_addr)s requested %(url)s\n"
"%(levelname)s in %(module)s: %(message)s" "%(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.testing:
if not app.debug: if not app.debug:
@ -179,7 +211,7 @@ def create_app(config_class=DevConfig):
app.logger.addHandler(mail_handler) app.logger.addHandler(mail_handler)
else: else:
# Pour logs en DEV uniquement: # Pour logs en DEV uniquement:
default_handler.setFormatter(scodoc_exc_formatter) default_handler.setFormatter(scodoc_log_formatter)
# Config logs pour DEV et PRODUCTION # Config logs pour DEV et PRODUCTION
# Configuration des logs (actifs aussi en mode development) # Configuration des logs (actifs aussi en mode development)
@ -188,9 +220,17 @@ def create_app(config_class=DevConfig):
file_handler = WatchedFileHandler( file_handler = WatchedFileHandler(
app.config["SCODOC_LOG_FILE"], encoding="utf-8" 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) file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler) 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.setLevel(logging.INFO)
app.logger.info(f"{sco_version.SCONAME} {sco_version.SCOVERSION} startup") app.logger.info(f"{sco_version.SCONAME} {sco_version.SCOVERSION} startup")

View File

@ -53,7 +53,7 @@ from flask import g, current_app
from PIL import Image as PILImage 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 config import Config
from app import log 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) 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(): def get_scodoc_version():
"return a string identifying ScoDoc version" "return a string identifying ScoDoc version"
return sco_version.SCOVERSION return sco_version.SCOVERSION

View File

@ -30,6 +30,8 @@ class Config:
SCODOC_DIR = os.environ.get("SCODOC_DIR", "/opt/scodoc") SCODOC_DIR = os.environ.get("SCODOC_DIR", "/opt/scodoc")
SCODOC_VAR_DIR = os.environ.get("SCODOC_VAR_DIR", "/opt/scodoc-data") SCODOC_VAR_DIR = os.environ.get("SCODOC_VAR_DIR", "/opt/scodoc-data")
SCODOC_LOG_FILE = os.path.join(SCODOC_VAR_DIR, "log", "scodoc.log") 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 MAX_CONTENT_LENGTH = 10 * 1024 * 1024 # Flask uploads

View File

@ -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 weekly
missingok missingok
rotate 64 rotate 64