diff --git a/arango/aql.py b/arango/aql.py index 2578630..fdf92f8 100644 --- a/arango/aql.py +++ b/arango/aql.py @@ -17,6 +17,7 @@ AQLQueryClearError, AQLQueryExecuteError, AQLQueryExplainError, + AQLQueryHistoryError, AQLQueryKillError, AQLQueryListError, AQLQueryRulesGetError, @@ -627,6 +628,23 @@ def response_handler(resp: Response) -> Json: return self._execute(request, response_handler) + def history(self) -> Result[Json]: + """Return recently executed AQL queries (admin only). + + :return: AQL query history. + :rtype: dict + :raise arango.exceptions.AQLQueryHistoryError: If retrieval fails. + """ + request = Request(method="get", endpoint="/_admin/server/aql-queries") + + def response_handler(resp: Response) -> Json: + if not resp.is_success: + raise AQLQueryHistoryError(resp, request) + res: Json = resp.body["result"] + return res + + return self._execute(request, response_handler) + def functions(self) -> Result[Jsons]: """List the AQL functions defined in the database. diff --git a/arango/database.py b/arango/database.py index 766161d..130b7b5 100644 --- a/arango/database.py +++ b/arango/database.py @@ -44,6 +44,7 @@ PermissionListError, PermissionResetError, PermissionUpdateError, + ServerAPICallsError, ServerAvailableOptionsGetError, ServerCheckAvailabilityError, ServerCurrentOptionsGetError, @@ -463,6 +464,26 @@ def response_handler(resp: Response) -> Json: return self._execute(request, response_handler) + def api_calls(self) -> Result[Json]: + """Return recent API calls (admin only). + + :return: API calls history. + :rtype: dict + :raise arango.exceptions.ServerAPICallsError: If retrieval fails. + """ + request = Request( + method="get", + endpoint="/_admin/server/api-calls", + ) + + def response_handler(resp: Response) -> Json: + if not resp.is_success: + raise ServerAPICallsError(resp, request) + res: Json = resp.body["result"] + return res + + return self._execute(request, response_handler) + def status(self) -> Result[Json]: """Return ArangoDB server status. diff --git a/arango/exceptions.py b/arango/exceptions.py index 891c813..7fc6298 100644 --- a/arango/exceptions.py +++ b/arango/exceptions.py @@ -121,6 +121,10 @@ class AQLQueryTrackingGetError(ArangoServerError): """Failed to retrieve AQL tracking properties.""" +class AQLQueryHistoryError(ArangoServerError): + """Failed to retrieve recent AQL queries.""" + + class AQLQueryTrackingSetError(ArangoServerError): """Failed to configure AQL tracking properties.""" @@ -638,6 +642,10 @@ class ServerDetailsError(ArangoServerError): """Failed to retrieve server details.""" +class ServerAPICallsError(ArangoServerError): + """Failed to retrieve recent API calls.""" + + class ServerLicenseGetError(ArangoServerError): """Failed to retrieve server license.""" diff --git a/arango/request.py b/arango/request.py index 4bb135a..1c0e6cc 100644 --- a/arango/request.py +++ b/arango/request.py @@ -12,7 +12,7 @@ def normalize_headers( if driver_flags is not None: for flag in driver_flags: flags = flags + flag + ";" - driver_version = "8.2.2" + driver_version = "8.2.3" driver_header = "python-arango/" + driver_version + " (" + flags + ")" normalized_headers: Headers = { "charset": "utf-8", diff --git a/starter.sh b/starter.sh index a5126f5..faf8561 100755 --- a/starter.sh +++ b/starter.sh @@ -8,8 +8,8 @@ # Example: # ./starter.sh cluster enterprise 3.12.5 -setup="${1:-single}" -license="${2:-community}" +setup="${1:-cluster}" +license="${2:-enterprise}" version="${3:-latest}" extra_ports="" diff --git a/tests/test_aql.py b/tests/test_aql.py index 6c1d3ea..f4074d6 100644 --- a/tests/test_aql.py +++ b/tests/test_aql.py @@ -13,6 +13,7 @@ AQLQueryClearError, AQLQueryExecuteError, AQLQueryExplainError, + AQLQueryHistoryError, AQLQueryKillError, AQLQueryListError, AQLQueryTrackingGetError, @@ -30,7 +31,7 @@ def test_aql_attributes(db, username): assert repr(db.aql.cache) == f"" -def test_aql_query_management(db_version, db, bad_db, col, docs): +def test_aql_query_management(db_version, db, sys_db, bad_db, col, docs): explain_fields = [ "estimatedNrItems", "estimatedCost", @@ -192,6 +193,12 @@ def test_aql_query_management(db_version, db, bad_db, col, docs): db.begin_async_execution().aql.execute("RETURN SLEEP(100)") db.begin_async_execution().aql.execute("RETURN SLEEP(50)") + # Test query history + with assert_raises(AQLQueryHistoryError): + bad_db.aql.history() + history = sys_db.aql.history() + assert isinstance(history, dict) + # Test list queries queries = db.aql.queries() for query in queries: diff --git a/tests/test_database.py b/tests/test_database.py index 4e8a160..1006df3 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -20,6 +20,7 @@ DatabaseListError, DatabasePropertiesError, DatabaseSupportInfoError, + ServerAPICallsError, ServerCheckAvailabilityError, ServerDetailsError, ServerEchoError, @@ -314,6 +315,12 @@ def test_database_misc_methods(client, sys_db, db, bad_db, cluster, secret, db_v with assert_raises(ServerLogLevelResetError): bad_db.reset_log_levels() + # Test api calls history + with assert_raises(ServerAPICallsError): + bad_db.api_calls() + history = sys_db.api_calls() + assert isinstance(history, dict) + # Test get storage engine engine = db.engine() assert engine["name"] in ["rocksdb"]