|
28 | 28 | from typing import Optional
|
29 | 29 | import warnings
|
30 | 30 |
|
| 31 | +from ansys.geometry.core.errors import protect_grpc |
| 32 | + |
31 | 33 | # TODO: Remove this context and filter once the protobuf UserWarning issue is downgraded to INFO
|
32 | 34 | # https://github.com/grpc/grpc/issues/37609
|
33 | 35 | with warnings.catch_warnings():
|
|
43 | 45 | from beartype import beartype as check_input_types
|
44 | 46 | import semver
|
45 | 47 |
|
46 |
| -from ansys.api.dbu.v0.admin_pb2 import BackendType as GRPCBackendType |
| 48 | +from ansys.api.dbu.v0.admin_pb2 import ( |
| 49 | + BackendType as GRPCBackendType, |
| 50 | + LogsRequest, |
| 51 | + LogsTarget, |
| 52 | + PeriodType, |
| 53 | +) |
47 | 54 | from ansys.api.dbu.v0.admin_pb2_grpc import AdminStub
|
48 | 55 | from ansys.geometry.core.connection.backend import BackendType
|
49 | 56 | from ansys.geometry.core.connection.defaults import DEFAULT_HOST, DEFAULT_PORT, MAX_MESSAGE_LENGTH
|
@@ -327,3 +334,71 @@ def target(self) -> str:
|
327 | 334 | def get_name(self) -> str:
|
328 | 335 | """Get the target name of the connection."""
|
329 | 336 | return self._target
|
| 337 | + |
| 338 | + @check_input_types |
| 339 | + @protect_grpc |
| 340 | + def _get_service_logs( |
| 341 | + self, |
| 342 | + all_logs: bool = False, |
| 343 | + dump_to_file: bool = False, |
| 344 | + logs_folder: str | Path | None = None, |
| 345 | + ) -> str | dict[str, str] | Path: |
| 346 | + """Get the service logs. |
| 347 | +
|
| 348 | + Parameters |
| 349 | + ---------- |
| 350 | + all_logs : bool, default: False |
| 351 | + Flag indicating whether all logs should be retrieved. By default, |
| 352 | + only the current logs are retrieved. |
| 353 | + dump_to_file : bool, default: False |
| 354 | + Flag indicating whether the logs should be dumped to a file. |
| 355 | + By default, the logs are not dumped to a file. |
| 356 | + logs_folder : str, Path or None, default: None |
| 357 | + Name of the folder where the logs should be dumped. This parameter |
| 358 | + is only used if the ``dump_to_file`` parameter is set to ``True``. |
| 359 | +
|
| 360 | + Returns |
| 361 | + ------- |
| 362 | + str |
| 363 | + Service logs as a string. This is returned if the ``dump_to_file`` parameter |
| 364 | + is set to ``False``. |
| 365 | + dict[str, str] |
| 366 | + Dictionary containing the logs. The keys are the logs names, |
| 367 | + and the values are the logs as strings. This is returned if the ``all_logs`` |
| 368 | + parameter is set to ``True`` and the ``dump_to_file`` parameter |
| 369 | + is set to ``False``. |
| 370 | + Path |
| 371 | + Path to the folder containing the logs (if the ``all_logs`` |
| 372 | + parameter is set to ``True``) or the path to the log file (if only |
| 373 | + the current logs are retrieved). The ``dump_to_file`` parameter |
| 374 | + must be set to ``True``. |
| 375 | + """ |
| 376 | + request = LogsRequest( |
| 377 | + target=LogsTarget.CLIENT, |
| 378 | + period_type=PeriodType.CURRENT if not all_logs else PeriodType.ALL, |
| 379 | + null_path=None, |
| 380 | + null_period=None, |
| 381 | + ) |
| 382 | + logs_generator = self._admin_stub.GetLogs(request) |
| 383 | + logs: dict[str, str] = {} |
| 384 | + |
| 385 | + for chunk in logs_generator: |
| 386 | + if chunk.log_name not in logs: |
| 387 | + logs[chunk.log_name] = "" |
| 388 | + logs[chunk.log_name] += chunk.log_chunk.decode() |
| 389 | + |
| 390 | + # Let's handle the various scenarios... |
| 391 | + if not dump_to_file: |
| 392 | + return logs if all_logs else next(iter(logs.values())) |
| 393 | + else: |
| 394 | + if logs_folder is None: |
| 395 | + logs_folder = Path.cwd() |
| 396 | + elif isinstance(logs_folder, str): |
| 397 | + logs_folder = Path(logs_folder) |
| 398 | + |
| 399 | + logs_folder.mkdir(parents=True, exist_ok=True) |
| 400 | + for log_name, log_content in logs.items(): |
| 401 | + with (logs_folder / log_name).open("w") as f: |
| 402 | + f.write(log_content) |
| 403 | + |
| 404 | + return (logs_folder / log_name) if len(logs) == 1 else logs_folder |
0 commit comments