Skip to content

Commit 692fec7

Browse files
Merge branch 'master' into is8102/add-search-api-in-storage
2 parents b4a3ca1 + 18249a4 commit 692fec7

File tree

71 files changed

+433
-282
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+433
-282
lines changed

packages/pytest-simcore/src/pytest_simcore/helpers/faker_factories.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727

2828
def random_service_key(fake: Faker = DEFAULT_FAKER, *, name: str | None = None) -> str:
29-
suffix = fake.unique.word() if name is None else name
29+
suffix = fake.unique.pystr(min_chars=2) if name is None else name
3030
return f"simcore/services/{fake.random_element(['dynamic', 'comp', 'frontend'])}/{suffix.lower()}"
3131

3232

packages/service-library/src/servicelib/aiohttp/rest_middlewares.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from models_library.basic_types import IDStr
1818
from models_library.rest_error import ErrorGet, ErrorItemType, LogMessageType
1919

20-
from ..logging_errors import create_troubleshootting_log_kwargs
20+
from ..logging_errors import create_troubleshooting_log_kwargs
2121
from ..mimetype_constants import MIMETYPE_APPLICATION_JSON
2222
from ..rest_constants import RESPONSE_MODEL_POLICY
2323
from ..rest_responses import is_enveloped_from_text
@@ -72,7 +72,7 @@ def _log_5xx_server_error(
7272
error_code, error_context = _create_error_context(request, exception)
7373

7474
_logger.exception(
75-
**create_troubleshootting_log_kwargs(
75+
**create_troubleshooting_log_kwargs(
7676
user_error_msg,
7777
error=exception,
7878
error_context=error_context,

packages/service-library/src/servicelib/exception_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from pydantic import BaseModel, Field, NonNegativeFloat, PrivateAttr
99

10-
from .logging_errors import create_troubleshootting_log_kwargs
10+
from .logging_errors import create_troubleshooting_log_kwargs
1111

1212
_logger = logging.getLogger(__name__)
1313

@@ -93,7 +93,7 @@ def _should_suppress_exception(
9393
# the predicate function raised an exception
9494
# log it and do not suppress the original exception
9595
_logger.warning(
96-
**create_troubleshootting_log_kwargs(
96+
**create_troubleshooting_log_kwargs(
9797
f"Predicate function raised exception {type(predicate_exc).__name__}:{predicate_exc} in {func_name}. "
9898
f"Original exception will be re-raised: {type(exc).__name__}",
9999
error=predicate_exc,

packages/service-library/src/servicelib/fastapi/http_error.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from fastapi.responses import JSONResponse
1212
from pydantic import ValidationError
1313

14-
from ..logging_errors import create_troubleshootting_log_kwargs
14+
from ..logging_errors import create_troubleshooting_log_kwargs
1515
from ..status_codes_utils import is_5xx_server_error
1616

1717
validation_error_response_definition["properties"] = {
@@ -57,7 +57,7 @@ async def _http_error_handler(request: Request, exc: Exception) -> JSONResponse:
5757

5858
if is_5xx_server_error(status_code):
5959
_logger.exception(
60-
create_troubleshootting_log_kwargs(
60+
create_troubleshooting_log_kwargs(
6161
f"A 5XX server error happened in current service. Responding with {error_content} and {status_code} status code",
6262
error=exc,
6363
error_context={

packages/service-library/src/servicelib/fastapi/long_running_tasks/_context_manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from pydantic import PositiveFloat
99

10-
from ...logging_errors import create_troubleshootting_log_message
10+
from ...logging_errors import create_troubleshooting_log_message
1111
from ...long_running_tasks.errors import TaskClientTimeoutError, TaskExceptionError
1212
from ...long_running_tasks.models import (
1313
ProgressCallback,
@@ -137,7 +137,7 @@ async def _wait_for_task_result() -> Any:
137137
) from e
138138
except Exception as e:
139139
_logger.warning(
140-
create_troubleshootting_log_message(
140+
create_troubleshooting_log_message(
141141
user_error_msg=f"{task_id=} raised an exception",
142142
error=e,
143143
tip=f"Check the logs of the service responding to '{client.base_url}'",
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from typing import NotRequired, TypedDict
2+
3+
4+
class LogExtra(TypedDict):
5+
log_uid: NotRequired[str]
6+
log_oec: NotRequired[str]
7+
8+
9+
def get_log_record_extra(
10+
*,
11+
user_id: int | str | None = None,
12+
error_code: str | None = None,
13+
) -> LogExtra | None:
14+
extra: LogExtra = {}
15+
16+
if user_id:
17+
assert int(user_id) > 0 # nosec
18+
extra["log_uid"] = f"{user_id}"
19+
if error_code:
20+
extra["log_oec"] = error_code
21+
22+
return extra or None

packages/service-library/src/servicelib/logging_errors.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
from common_library.errors_classes import OsparcErrorMixin
66
from common_library.json_serialization import json_dumps, representation_encoder
77

8-
from .logging_utils import LogExtra, get_log_record_extra
8+
from .logging_base import LogExtra, get_log_record_extra
99

1010
_logger = logging.getLogger(__name__)
1111

1212

13-
def create_troubleshootting_log_message(
13+
def create_troubleshooting_log_message(
1414
user_error_msg: str,
1515
*,
1616
error: BaseException,
@@ -31,9 +31,14 @@ def create_troubleshootting_log_message(
3131
def _collect_causes(exc: BaseException) -> str:
3232
causes = []
3333
current = exc.__cause__
34-
while current is not None:
34+
seen = set() # Prevent infinite loops
35+
while current is not None and id(current) not in seen:
36+
seen.add(id(current))
3537
causes.append(f"[{type(current).__name__}]'{current}'")
3638
current = getattr(current, "__cause__", None)
39+
if len(causes) > 10: # Prevent excessive chains
40+
causes.append("[... truncated]")
41+
break
3742
return " <- ".join(causes)
3843

3944
debug_data = json_dumps(
@@ -57,7 +62,7 @@ class LogKwargs(TypedDict):
5762
extra: LogExtra | None
5863

5964

60-
def create_troubleshootting_log_kwargs(
65+
def create_troubleshooting_log_kwargs(
6166
user_error_msg: str,
6267
*,
6368
error: BaseException,
@@ -74,7 +79,7 @@ def create_troubleshootting_log_kwargs(
7479
...
7580
except MyException as exc
7681
_logger.exception(
77-
**create_troubleshootting_log_kwargs(
82+
**create_troubleshooting_log_kwargs(
7883
user_error_msg=frontend_msg,
7984
error=exc,
8085
error_context={
@@ -92,7 +97,7 @@ def create_troubleshootting_log_kwargs(
9297
context.update(error.error_context())
9398

9499
# compose as log message
95-
log_msg = create_troubleshootting_log_message(
100+
log_msg = create_troubleshooting_log_message(
96101
user_error_msg,
97102
error=error,
98103
error_code=error_code,

packages/service-library/src/servicelib/logging_utils.py

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
from datetime import datetime
1818
from inspect import getframeinfo, stack
1919
from pathlib import Path
20-
from typing import Any, Final, NotRequired, TypeAlias, TypedDict, TypeVar
20+
from typing import Any, Final, TypeAlias, TypedDict, TypeVar
2121

2222
from common_library.json_serialization import json_dumps
2323
from settings_library.tracing import TracingSettings
2424

25+
from .logging_base import LogExtra
26+
from .logging_errors import create_troubleshooting_log_kwargs
2527
from .logging_utils_filtering import GeneralLogFilter, LoggerName, MessageSubstring
2628
from .tracing import setup_log_tracing
2729
from .utils_secrets import mask_sensitive_data
@@ -60,27 +62,6 @@
6062
}
6163

6264

63-
class LogExtra(TypedDict):
64-
log_uid: NotRequired[str]
65-
log_oec: NotRequired[str]
66-
67-
68-
def get_log_record_extra(
69-
*,
70-
user_id: int | str | None = None,
71-
error_code: str | None = None,
72-
) -> LogExtra | None:
73-
extra: LogExtra = {}
74-
75-
if user_id:
76-
assert int(user_id) > 0 # nosec
77-
extra["log_uid"] = f"{user_id}"
78-
if error_code:
79-
extra["log_oec"] = error_code
80-
81-
return extra or None
82-
83-
8465
class CustomFormatter(logging.Formatter):
8566
"""Custom Formatter does these 2 things:
8667
1. Overrides 'funcName' with the value of 'func_name_override', if it exists.
@@ -97,7 +78,8 @@ def format(self, record) -> str:
9778
if hasattr(record, "file_name_override"):
9879
record.filename = record.file_name_override
9980

100-
optional_keys = LogExtra.__optional_keys__ | frozenset( # pylint: disable=no-member
81+
# pylint: disable=no-member
82+
optional_keys = LogExtra.__optional_keys__ | frozenset(
10183
["otelTraceID", "otelSpanID"]
10284
)
10385
for name in optional_keys:
@@ -572,7 +554,12 @@ def log_catch(logger: logging.Logger, *, reraise: bool = True) -> Iterator[None]
572554
logger.debug("call was cancelled")
573555
raise
574556
except Exception as exc: # pylint: disable=broad-except
575-
logger.exception("Unhandled exception:")
557+
logger.exception(
558+
**create_troubleshooting_log_kwargs(
559+
"Caught unhandled exception",
560+
error=exc,
561+
)
562+
)
576563
if reraise:
577564
raise exc from exc
578565

packages/service-library/src/servicelib/long_running_tasks/task.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
)
2121

2222
from ..background_task import create_periodic_task
23-
from ..logging_errors import create_troubleshootting_log_kwargs
23+
from ..logging_errors import create_troubleshooting_log_kwargs
2424
from ..logging_utils import log_catch, log_context
2525
from ..redis import RedisClientSDK, exclusive
2626
from ..utils import limited_gather
@@ -353,7 +353,7 @@ async def _tasks_monitor(self) -> None: # noqa: C901
353353
)
354354
if type(e) not in allowed_errors:
355355
_logger.exception(
356-
**create_troubleshootting_log_kwargs(
356+
**create_troubleshooting_log_kwargs(
357357
(
358358
f"Execution of {task_id=} finished with unexpected error, "
359359
f"only the following {allowed_errors=} are permitted"
@@ -372,7 +372,7 @@ async def _tasks_monitor(self) -> None: # noqa: C901
372372
Exception # pylint:disable=broad-except
373373
) as serialization_error:
374374
_logger.exception(
375-
**create_troubleshootting_log_kwargs(
375+
**create_troubleshooting_log_kwargs(
376376
(
377377
f"Execution of {task_id=} finished with an error "
378378
f"which could not be serialized"

packages/service-library/src/servicelib/rabbitmq/_rpc_router.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from common_library.error_codes import create_error_code
1010
from models_library.rabbitmq_basic_types import RPCMethodName
11-
from servicelib.logging_errors import create_troubleshootting_log_kwargs
11+
from servicelib.logging_errors import create_troubleshooting_log_kwargs
1212

1313
from ..logging_utils import log_context
1414
from ._errors import RPCServerError
@@ -74,7 +74,7 @@ async def _wrapper(*args, **kwargs):
7474
error_code = create_error_code(exc)
7575
_logger.exception(
7676
# NOTE: equivalent to a 500 http status code error
77-
**create_troubleshootting_log_kwargs(
77+
**create_troubleshooting_log_kwargs(
7878
f"Unhandled exception on the rpc-server side for '{func.__name__}'",
7979
error=exc,
8080
error_code=error_code,

0 commit comments

Comments
 (0)