diff --git a/README.md b/README.md index 895147ea..8912f04e 100644 --- a/README.md +++ b/README.md @@ -599,20 +599,31 @@ This config includes: `setup_logging` is called during the initialization of the Flask app. ### Usage +We use two loggers in this application: -We can utilise the Flask logger by accessing Flask's `app.logger`. Since we define our routes with blueprints rather than the app directly, we can call access app through +- app_logger for application-related logs +- audit_logger for audit-specific logs + +Both are attached to the Flask app instance for easy access across the app. Since we define routes using blueprints instead of directly on the app, we access these loggers through Flaskā€™s current_app. + +To use these loggers in your code, import current_app from Flask: ```python from flask import current_app ``` -for example: +Then, call the appropriate logger as follows: ```python -current_app.logger.info('Some info message') -current_app.logger.debug('Some debug message') -current_app.logger.warning('Some warning message') -current_app.logger.error('Some error message') +current_app.app_logger.info('Some info message') +current_app.app_logger.debug('Some debug message') +current_app.app_logger.warning('Some warning message') +current_app.app_logger.error('Some error message') + +current_app.audit_logger.info('Some info message') +current_app.audit_logger.debug('Some debug message') +current_app.audit_logger.warning('Some warning message') +current_app.audit_logger.error('Some error message') ``` ### Output diff --git a/app/logger_config.py b/app/logger_config.py index d8209399..99cc093b 100644 --- a/app/logger_config.py +++ b/app/logger_config.py @@ -1,7 +1,6 @@ import logging from flask import has_request_context, request -from flask.logging import default_handler class RequestFormatter(logging.Formatter): @@ -12,15 +11,33 @@ def format(self, record): else: record.url = None record.remote_addr = None - return super().format(record) +def setup_logger(name, level, formatter): + """Helper function to set up a logger.""" + logger = logging.getLogger(name) + logger.setLevel(level) + handler = logging.StreamHandler() + handler.setFormatter(formatter) + logger.addHandler(handler) + return logger + + def setup_logging(app): - formatter = RequestFormatter( + """Set up loggers for the app.""" + audit_log_formatter = RequestFormatter( + "AUDIT_LOG\n" "[%(asctime)s] %(remote_addr)s requested %(url)s\n" "%(levelname)s in %(module)s: %(message)s" ) - default_handler.setFormatter(formatter) + app.audit_logger = setup_logger( + "audit_logger", logging.INFO, audit_log_formatter + ) - app.logger.setLevel(logging.INFO) + app_log_formatter = RequestFormatter( + "APP_LOG\n" + "[%(asctime)s] %(remote_addr)s requested %(url)s\n" + "%(levelname)s in %(module)s: %(message)s" + ) + app.app_logger = setup_logger("app_logger", logging.INFO, app_log_formatter) diff --git a/app/main/routes.py b/app/main/routes.py index 46079eaf..4015d61f 100644 --- a/app/main/routes.py +++ b/app/main/routes.py @@ -687,7 +687,7 @@ def record(record_id: uuid.UUID): try: presigned_url = create_presigned_url(file) except Exception as e: - current_app.logger.info( + current_app.app_logger.info( f"Failed to create presigned url for document render non-javascript fallback {e}" ) @@ -732,7 +732,7 @@ def download_record(record_id: uuid.UUID): try: s3_file_object = s3.get_object(Bucket=bucket, Key=key) except Exception as e: - current_app.logger.error(f"Failed to get object from S3: {e}") + current_app.app_logger.error(f"Failed to get object from S3: {e}") abort(404) download_filename = file.FileName @@ -747,7 +747,7 @@ def download_record(record_id: uuid.UUID): file_content = s3_file_object["Body"].read() file_type = download_filename.split(".")[-1].lower() except Exception as e: - current_app.logger.error(f"Error reading S3 file content: {e}") + current_app.app_logger.error(f"Error reading S3 file content: {e}") abort(500) content_type = s3_file_object.get("ContentType", "application/octet-stream") @@ -766,7 +766,7 @@ def download_record(record_id: uuid.UUID): as_attachment=True, download_name=download_filename, ) - current_app.logger.info( + current_app.audit_logger.info( json.dumps({"user_id": session["user_id"], "file": key}) ) return response diff --git a/app/main/util/render_utils.py b/app/main/util/render_utils.py index fa319e27..cab2d187 100644 --- a/app/main/util/render_utils.py +++ b/app/main/util/render_utils.py @@ -57,7 +57,7 @@ def get_download_filename(file): def create_presigned_url(file): file_extension = file.FileName.split(".")[-1].lower() if file_extension not in current_app.config["SUPPORTED_RENDER_EXTENSIONS"]: - current_app.logger.warning( + current_app.app_logger.warning( f"Rendering file format '{file_extension}' is not currently supported by AYR." ) return None @@ -88,7 +88,7 @@ def generate_pdf_manifest(record_id): try: presigned_url = create_presigned_url(file) except Exception as e: - current_app.logger.info( + current_app.app_logger.info( f"Failed to create presigned url for document render non-javascript fallback {e}" ) @@ -166,7 +166,7 @@ def generate_image_manifest(s3_file_object, record_id): try: presigned_url = create_presigned_url(file) except Exception as e: - current_app.logger.info( + current_app.app_logger.info( f"Failed to create presigned url for document render non-javascript fallback {e}" )