Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DE-699 | Update global server logs retrieval #299

Merged
merged 3 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 76 additions & 1 deletion arango/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,10 @@ def read_log(
search: Optional[str] = None,
sort: Optional[str] = None,
) -> Result[Json]:
"""Read the global log from server.
"""Read the global log from server. This method is deprecated
in ArangoDB 3.8 and will be removed in a future version
of the driver. Use :func:`arango.database.Database.read_log_entries`
instead.
Comment on lines +618 to +621
Copy link
Member Author

@aMahanna aMahanna Nov 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to adjust the way we address this for a better solution (I am following this precedent).

We could for example use the @deprecated decorator if we add the Deprecated package as a dependency.

Copy link
Member

@apetenchea apetenchea Nov 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having the comment is great, but we should make it visible for users that are not going through the documentation. Or, for example, if they use another package that is built on top of python-arango, they should be able to figure out that there is a problem underneath (ok, this may be an exaggerated example, but you know what I mean).
Using the @deprecated decorator would do just fine. I'm not familiar with it, but a requirement that I find sensible is to allow to user to disable it the warning.
A slightly different approach that I used before is to emit a warning using the standard library, for example here. FutureWarning or DeprecatedWarning would be fit the bill (the latter is disabled by default).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense!

I've added a warn(..., DeprecationWarning) call in dd7383a


:param upto: Return the log entries up to the given level (mutually
exclusive with parameter **level**). Allowed values are "fatal",
Expand Down Expand Up @@ -671,6 +674,78 @@ def response_handler(resp: Response) -> Json:

return self._execute(request, response_handler)

def read_log_entries(
self,
upto: Optional[Union[int, str]] = None,
level: Optional[Union[int, str]] = None,
start: Optional[int] = None,
size: Optional[int] = None,
offset: Optional[int] = None,
search: Optional[str] = None,
sort: Optional[str] = None,
server_id: Optional[str] = None,
) -> Result[Json]:
"""Read the global log from server.

:param upto: Return the log entries up to the given level (mutually
exclusive with parameter **level**). Allowed values are "fatal",
"error", "warning", "info" (default) and "debug".
:type upto: int | str
:param level: Return the log entries of only the given level (mutually
exclusive with **upto**). Allowed values are "fatal", "error",
"warning", "info" (default) and "debug".
:type level: int | str
:param start: Return the log entries whose ID is greater or equal to
the given value.
:type start: int
:param size: Restrict the size of the result to the given value. This
can be used for pagination.
:type size: int
:param offset: Number of entries to skip (e.g. for pagination).
:type offset: int
:param search: Return only the log entries containing the given text.
:type search: str
:param sort: Sort the log entries according to the given fashion, which
can be "sort" or "desc".
:type sort: str
:param server_id: Returns all log entries of the specified server.
All other query parameters remain valid. If no serverId is given,
the asked server will reply. This parameter is only meaningful
on Coordinators.
:type server_id: str
:return: Server log entries.
:rtype: dict
:raise arango.exceptions.ServerReadLogError: If read fails.
"""
params = dict()
if upto is not None:
params["upto"] = upto
if level is not None:
params["level"] = level
if start is not None:
params["start"] = start
if size is not None:
params["size"] = size
if offset is not None:
params["offset"] = offset
if search is not None:
params["search"] = search
if sort is not None:
params["sort"] = sort
if server_id is not None:
params["serverId"] = server_id

request = Request(method="get", endpoint="/_admin/log/entries", params=params)

def response_handler(resp: Response) -> Json:
if not resp.is_success:
raise ServerReadLogError(resp, request)

result: Json = resp.body
return result

return self._execute(request, response_handler)

def log_levels(self, server_id: Optional[str] = None) -> Result[Json]:
"""Return current logging levels.

Expand Down
37 changes: 29 additions & 8 deletions tests/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,31 +167,52 @@ def test_database_misc_methods(sys_db, db, bad_db, cluster):
assert err.value.error_code in {11, 1228}

# Test read_log with default parameters
# Deprecated in 3.8.0
# TODO: Remove in future release
log = sys_db.read_log(upto="fatal")
assert "lid" in log
assert "level" in log
assert "text" in log
assert "total_amount" in log

log_entry = sys_db.read_log_entries(upto="fatal")
assert "total" in log_entry
assert "messages" in log_entry

kwargs = {
"level": "error",
"start": 0,
"size": 100000,
"offset": 0,
"search": "test",
"sort": "desc",
}

# Test read_log with specific parameters
log = sys_db.read_log(
level="error",
start=0,
size=100000,
offset=0,
search="test",
sort="desc",
)
# Deprecated in 3.8.0
# TODO: Remove in future release
log = sys_db.read_log(**kwargs)
assert "lid" in log
assert "level" in log
assert "text" in log
assert "total_amount" in log

log_entry = sys_db.read_log_entries(**kwargs)
assert "total" in log_entry
assert "messages" in log_entry

# Test read_log with bad database
# Deprecated in 3.8.0
# TODO: Remove in future release
with assert_raises(ServerReadLogError) as err:
bad_db.read_log()
assert err.value.error_code in {11, 1228}

# Test read_log_entries with bad database
with assert_raises(ServerReadLogError) as err:
bad_db.read_log_entries()
assert err.value.error_code in {11, 1228}

# Test reload routing
assert isinstance(db.reload_routing(), bool)

Expand Down
Loading