From 2566d6c92e956cf29c752e0b525e4e9abdb3af46 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20K=C3=BCnzel?= <simonk@fsmpi.rwth-aachen.de>
Date: Mon, 10 Feb 2025 00:43:16 +0100
Subject: [PATCH] Better client error logging

---
 config/api_example_config.py   |  3 +++
 config/test_config_override.py |  5 +----
 src/api/routes/route.py        | 21 +++++++++++++++------
 submodules/backend_common_py   |  2 +-
 4 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/config/api_example_config.py b/config/api_example_config.py
index dbf8a4b..b30711d 100644
--- a/config/api_example_config.py
+++ b/config/api_example_config.py
@@ -17,6 +17,9 @@ PERMANENT_MEDIA_DIR = "permanent_media"
 # Defaults for development, do not use in production!
 DEBUG = True
 
+# Logs client errors when HTTP request fails (usually because of a client's mistake, e.g. bad request)
+LOG_CLIENT_ERRORS_WHEN_DEBUGGING = True
+
 # Name of this instance
 API_SERVER_NAME = "dev"
 
diff --git a/config/test_config_override.py b/config/test_config_override.py
index 8f699b2..a00bca0 100644
--- a/config/test_config_override.py
+++ b/config/test_config_override.py
@@ -1,8 +1,5 @@
-import os
-import tempfile
-import atexit
-
 DEBUG = True
+LOG_CLIENT_ERRORS_WHEN_DEBUGGING = False
 DISABLE_SCHEDULER = True
 API_ROULETTE_MODE = 0
 
diff --git a/src/api/routes/route.py b/src/api/routes/route.py
index dacc958..faf3117 100644
--- a/src/api/routes/route.py
+++ b/src/api/routes/route.py
@@ -20,6 +20,9 @@ _DEFAULT_CACHE_CONTROL_MAX_AGE_SECONDS = api.config["DEFAULT_CACHE_CONTROL_MAX_A
 _SERVER_NAME = api.config["API_SERVER_NAME"]
 
 
+_LOG_CLIENT_ERRORS: bool = DEBUG_ENABLED and api.config.get("LOG_CLIENT_ERRORS_WHEN_DEBUGGING", True)
+
+
 def get_client_json(request: Request) -> CJsonObject:
     json = request.get_json(force=False, silent=True, cache=False)
     if json is None:
@@ -86,24 +89,24 @@ def api_request_get_query_boolean(id: str, default: bool or None) -> int or None
 
 @api.app.errorhandler(400)
 def _handle_bad_request(e=None):
-    if DEBUG_ENABLED and e is not None:
-        print(f"An exception occurred while handling api request '{request.path}':")
+    if _LOG_CLIENT_ERRORS and e is not None:
+        print(f"A client exception occurred while handling api request '{request.path}':")
         traceback.print_exception(e)
     return api_on_error(ERROR_BAD_REQUEST("Bad request"))
 
 
 @api.app.errorhandler(404)
 def _handle_not_found(e=None):
-    if DEBUG_ENABLED and e is not None:
-        print(f"An exception occurred while handling api request '{request.path}':")
+    if _LOG_CLIENT_ERRORS and e is not None:
+        print(f"A client exception occurred while handling api request '{request.path}':")
         traceback.print_exception(e)
     return api_on_error(ERROR_UNKNOWN_REQUEST_PATH)
 
 
 @api.app.errorhandler(405)
 def _handle_method_not_allowed(e=None):
-    if DEBUG_ENABLED and e is not None:
-        print(f"An exception occurred while handling api request '{request.path}':")
+    if _LOG_CLIENT_ERRORS and e is not None:
+        print(f"A client exception occurred while handling api request '{request.path}':")
         traceback.print_exception(e)
     return api_on_error(ERROR_METHOD_NOT_ALLOWED)
 
@@ -389,8 +392,14 @@ def api_function(track_in_diagnostics: bool = True,
                 else:  # pragma: no cover
                     raise Exception(f"Api route {truncate_string(request.path)} returned result of unknown type: {str(result)}")
             except CJsonException as e:
+                if _LOG_CLIENT_ERRORS:
+                    print(f"A client exception occurred while handling api request '{request.path}':")
+                    traceback.print_exception(e)
                 return api_on_error(ERROR_REQUEST_INVALID_PARAMETER(e.path, e.message))
             except ApiClientException as e:
+                if _LOG_CLIENT_ERRORS:
+                    print(f"A client exception occurred while handling api request '{request.path}':")
+                    traceback.print_exception(e)
                 return api_on_error(e.error)
             except TransactionConflictError as e:
                 print(f"An transaction conflict occurred while handling api request '{truncate_string(request.path, 200)}':")
diff --git a/submodules/backend_common_py b/submodules/backend_common_py
index 6c08b47..abf6b47 160000
--- a/submodules/backend_common_py
+++ b/submodules/backend_common_py
@@ -1 +1 @@
-Subproject commit 6c08b477832da79999473a3ae26c4162684c75f2
+Subproject commit abf6b47372735f79050479c7e222689df213571f
-- 
GitLab