haiway 0.18.2__tar.gz → 0.19.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {haiway-0.18.2 → haiway-0.19.1}/PKG-INFO +1 -1
- {haiway-0.18.2 → haiway-0.19.1}/junit/test-results.xml +1 -1
- {haiway-0.18.2 → haiway-0.19.1}/pyproject.toml +1 -1
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/__init__.py +0 -2
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/access.py +53 -64
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/observability.py +53 -48
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/__init__.py +1 -2
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/observability.py +53 -35
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/tracing.py +50 -43
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/opentelemetry/observability.py +53 -31
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/structure.py +3 -151
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/__init__.py +2 -0
- haiway-0.19.1/src/haiway/utils/formatting.py +151 -0
- {haiway-0.18.2 → haiway-0.19.1}/uv.lock +1 -1
- {haiway-0.18.2 → haiway-0.19.1}/.github/workflows/ci.yml +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/.github/workflows/publish.yml +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/.gitignore +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/LICENSE +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/Makefile +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/README.md +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/config/pre-push +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/.dockerignore +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/Dockerfile +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/Makefile +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/README.md +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/config/.env.example +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/config/unit.json +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/docker-compose.yml +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/pyproject.toml +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/__int__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/config.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/features/todos/user_tasks.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/client.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/config.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/integrations/postgres/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/__main__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/postgres/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/postgres/execution.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/postgres/migration_0.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/migrations/postgres/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/__main__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/application.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/config.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/middlewares/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/middlewares/context.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/routes/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/routes/technical.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/server/routes/todos.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/config.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/postgres.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/src/solutions/user_tasks/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/examples/fastAPI/uv.lock +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/guidelines/functionalities.md +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/guidelines/packages.md +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/disposables.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/identifier.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/tasks.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/context/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/asynchrony.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/caching.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/retries.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/throttling.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/helpers/timeouted.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/opentelemetry/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/py.typed +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/attributes.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/path.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/requirement.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/state/validation.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/types/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/types/default.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/types/frozen.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/types/missing.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/always.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/collections.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/env.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/freezing.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/logs.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/mimic.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/noop.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/queue.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/src/haiway/utils/stream.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/test_async_queue.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/test_async_stream.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/test_attribute_path.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/test_auto_retry.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/test_cache.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/test_context.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/test_state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/test_streaming.py +0 -0
- {haiway-0.18.2 → haiway-0.19.1}/tests/test_timeout.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: haiway
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.19.1
|
4
4
|
Summary: Framework for dependency injection and state management within structured concurrency model.
|
5
5
|
Project-URL: Homepage, https://miquido.com
|
6
6
|
Project-URL: Repository, https://github.com/miquido/haiway.git
|
@@ -1 +1 @@
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="88" time="1.
|
1
|
+
<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="88" time="1.104" timestamp="2025-05-13T10:10:00.079778+00:00" hostname="pkrvmberfyhpb9w"><testcase classname="tests.test_async_queue" name="test_fails_when_stream_fails" time="0.001" /><testcase classname="tests.test_async_queue" name="test_cancels_when_iteration_cancels" time="0.001" /><testcase classname="tests.test_async_queue" name="test_ends_when_stream_ends" time="0.001" /><testcase classname="tests.test_async_queue" name="test_buffers_values_when_not_reading" time="0.001" /><testcase classname="tests.test_async_queue" name="test_delivers_buffer_when_streaming_fails" time="0.001" /><testcase classname="tests.test_async_queue" name="test_delivers_updates_when_sending" time="0.001" /><testcase classname="tests.test_async_queue" name="test_fails_when_sending_to_finished" time="0.001" /><testcase classname="tests.test_async_queue" name="test_ignores_when_finishing_when_finished" time="0.001" /><testcase classname="tests.test_async_stream" name="test_fails_when_stream_fails" time="0.001" /><testcase classname="tests.test_async_stream" name="test_cancels_when_iteration_cancels" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ends_when_stream_ends" time="0.001" /><testcase classname="tests.test_async_stream" name="test_finishes_without_buffer" time="0.001" /><testcase classname="tests.test_async_stream" name="test_fails_without_buffer" time="0.001" /><testcase classname="tests.test_async_stream" name="test_delivers_updates_when_sending" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ignores_when_sending_to_finished" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ignores_when_sending_to_failed" time="0.001" /><testcase classname="tests.test_async_stream" name="test_ignores_when_finishing_when_finished" time="0.001" /><testcase classname="tests.test_async_stream" name="test_delivers_all_when_sending_async" time="0.001" /><testcase classname="tests.test_attribute_path" name="test_id_path_points_to_self" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_attribute_path_points_to_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_nested_attribute_path_points_to_nested_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_recursive_attribute_path_points_to_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_list_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_tuple_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_mixed_tuple_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_dict_item_path_points_to_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_id_path_set_updates_self" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_attribute_path_set_updates_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_nested_attribute_path_set_updates_nested_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_recursive_attribute_set_updates_attribute" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_list_item_path_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_tuple_item_path_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_mixed_tuple_item_set_updates_item" time="0.000" /><testcase classname="tests.test_attribute_path" name="test_dict_item_path_set_updates_item" time="0.000" /><testcase classname="tests.test_auto_retry" name="test_returns_value_without_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_retries_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_logs_issue_with_errors" time="0.005" /><testcase classname="tests.test_auto_retry" name="test_fails_with_exceeding_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_fails_with_cancellation" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_retries_with_selected_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_fails_with_not_selected_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_returns_value_without_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_retries_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_with_exceeding_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_with_cancellation" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_when_cancelled" time="0.021" /><testcase classname="tests.test_auto_retry" name="test_async_uses_delay_with_errors" time="0.102" /><testcase classname="tests.test_auto_retry" name="test_async_uses_computed_delay_with_errors" time="0.107" /><testcase classname="tests.test_auto_retry" name="test_async_logs_issue_with_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_retries_with_selected_errors" time="0.001" /><testcase classname="tests.test_auto_retry" name="test_async_fails_with_not_selected_errors" time="0.001" /><testcase classname="tests.test_cache" name="test_returns_cache_value_with_same_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_different_argument" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_limit_exceed" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_same_value_with_repeating_argument" time="0.000" /><testcase classname="tests.test_cache" name="test_fails_with_error" time="0.000" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_expiration_time_exceed" time="0.020" /><testcase classname="tests.test_cache" name="test_async_returns_cache_value_with_same_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_fresh_value_with_different_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_fresh_value_with_limit_exceed" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_same_value_with_repeating_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_async_returns_fresh_value_with_expiration_time_exceed" time="0.021" /><testcase classname="tests.test_cache" name="test_async_cancel_waiting_does_not_cancel_task" time="0.502" /><testcase classname="tests.test_cache" name="test_async_expiration_does_not_cancel_task" time="0.021" /><testcase classname="tests.test_cache" name="test_async_fails_with_error" time="0.001" /><testcase classname="tests.test_context" name="test_state_is_available_according_to_context" time="0.001" /><testcase classname="tests.test_context" name="test_state_update_updates_local_context" time="0.001" /><testcase classname="tests.test_context" name="test_exceptions_are_propagated" time="0.001" /><testcase classname="tests.test_state" name="test_basic_initializes_with_arguments" time="0.002" /><testcase classname="tests.test_state" name="test_basic_initializes_with_defaults" time="0.001" /><testcase classname="tests.test_state" name="test_basic_equals_checks_properties" time="0.000" /><testcase classname="tests.test_state" name="test_basic_initializes_with_arguments_and_defaults" time="0.000" /><testcase classname="tests.test_state" name="test_parametrized_initializes_with_proper_parameters" time="0.000" /><testcase classname="tests.test_state" name="test_nested_initializes_with_proper_arguments" time="0.001" /><testcase classname="tests.test_state" name="test_dict_skips_missing_properties" time="0.000" /><testcase classname="tests.test_state" name="test_initialization_allows_missing_properties" time="0.000" /><testcase classname="tests.test_state" name="test_generic_subtypes_validation" time="0.002" /><testcase classname="tests.test_state" name="test_copying_leaves_same_object" time="0.000" /><testcase classname="tests.test_streaming" name="test_fails_when_generator_fails" time="0.001" /><testcase classname="tests.test_streaming" name="test_cancels_when_iteration_cancels" time="0.001" /><testcase classname="tests.test_streaming" name="test_ends_when_generator_ends" time="0.001" /><testcase classname="tests.test_streaming" name="test_delivers_updates_when_generating" time="0.001" /><testcase classname="tests.test_streaming" name="test_streaming_context_variables_access_is_preserved" time="0.001" /><testcase classname="tests.test_streaming" name="test_nested_streaming_streams_correctly" time="0.001" /><testcase classname="tests.test_timeout" name="test_returns_result_when_returning_value" time="0.001" /><testcase classname="tests.test_timeout" name="test_raises_with_error" time="0.001" /><testcase classname="tests.test_timeout" name="test_raises_with_cancel" time="0.011" /><testcase classname="tests.test_timeout" name="test_raises_with_timeout" time="0.011" /></testsuite></testsuites>
|
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
|
|
5
5
|
[project]
|
6
6
|
name = "haiway"
|
7
7
|
description = "Framework for dependency injection and state management within structured concurrency model."
|
8
|
-
version = "0.
|
8
|
+
version = "0.19.1"
|
9
9
|
readme = "README.md"
|
10
10
|
maintainers = [
|
11
11
|
{ name = "Kacper Kaliński", email = "kacper.kalinski@miquido.com" },
|
@@ -20,7 +20,6 @@ from haiway.context import (
|
|
20
20
|
)
|
21
21
|
from haiway.helpers import (
|
22
22
|
LoggerObservability,
|
23
|
-
ResultTrace,
|
24
23
|
asynchronous,
|
25
24
|
cache,
|
26
25
|
retry,
|
@@ -87,7 +86,6 @@ __all__ = (
|
|
87
86
|
"ObservabilityMetricRecording",
|
88
87
|
"ObservabilityScopeEntering",
|
89
88
|
"ObservabilityScopeExiting",
|
90
|
-
"ResultTrace",
|
91
89
|
"ScopeContext",
|
92
90
|
"ScopeIdentifier",
|
93
91
|
"State",
|
@@ -11,6 +11,7 @@ from collections.abc import (
|
|
11
11
|
Callable,
|
12
12
|
Coroutine,
|
13
13
|
Iterable,
|
14
|
+
Mapping,
|
14
15
|
)
|
15
16
|
from logging import Logger
|
16
17
|
from types import TracebackType
|
@@ -597,81 +598,69 @@ class ctx:
|
|
597
598
|
ObservabilityLevel.DEBUG, message, *args, exception=exception, **extra
|
598
599
|
)
|
599
600
|
|
601
|
+
@overload
|
600
602
|
@staticmethod
|
601
|
-
def
|
602
|
-
|
603
|
+
def record(
|
604
|
+
level: ObservabilityLevel = ObservabilityLevel.DEBUG,
|
603
605
|
/,
|
604
606
|
*,
|
605
|
-
|
606
|
-
|
607
|
-
) -> None:
|
608
|
-
"""
|
609
|
-
Record event within current scope context.
|
610
|
-
|
611
|
-
Parameters
|
612
|
-
----------
|
613
|
-
event: State
|
614
|
-
contents of event to be recorded.
|
607
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
608
|
+
) -> None: ...
|
615
609
|
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
)
|
610
|
+
@overload
|
611
|
+
@staticmethod
|
612
|
+
def record(
|
613
|
+
level: ObservabilityLevel = ObservabilityLevel.DEBUG,
|
614
|
+
/,
|
615
|
+
*,
|
616
|
+
event: str,
|
617
|
+
attributes: Mapping[str, ObservabilityAttribute] | None = None,
|
618
|
+
) -> None: ...
|
626
619
|
|
620
|
+
@overload
|
627
621
|
@staticmethod
|
628
|
-
def
|
629
|
-
|
622
|
+
def record(
|
623
|
+
level: ObservabilityLevel = ObservabilityLevel.DEBUG,
|
630
624
|
/,
|
631
625
|
*,
|
626
|
+
metric: str,
|
632
627
|
value: float | int,
|
633
628
|
unit: str | None = None,
|
634
|
-
|
635
|
-
) -> None:
|
636
|
-
"""
|
637
|
-
Record metric within current scope context.
|
638
|
-
|
639
|
-
Parameters
|
640
|
-
----------
|
641
|
-
metric: State
|
642
|
-
name of metric to be recorded.
|
643
|
-
value: float | int
|
644
|
-
value of metric to be recorded.
|
645
|
-
unit: str | None = None
|
646
|
-
unit of metric to be recorded.
|
647
|
-
|
648
|
-
Returns
|
649
|
-
-------
|
650
|
-
None
|
651
|
-
"""
|
652
|
-
|
653
|
-
ObservabilityContext.record_metric(
|
654
|
-
metric,
|
655
|
-
value=value,
|
656
|
-
unit=unit,
|
657
|
-
**extra,
|
658
|
-
)
|
629
|
+
attributes: Mapping[str, ObservabilityAttribute] | None = None,
|
630
|
+
) -> None: ...
|
659
631
|
|
660
632
|
@staticmethod
|
661
|
-
def
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
633
|
+
def record(
|
634
|
+
level: ObservabilityLevel = ObservabilityLevel.DEBUG,
|
635
|
+
/,
|
636
|
+
*,
|
637
|
+
event: str | None = None,
|
638
|
+
metric: str | None = None,
|
639
|
+
value: float | int | None = None,
|
640
|
+
unit: str | None = None,
|
641
|
+
attributes: Mapping[str, ObservabilityAttribute] | None = None,
|
642
|
+
) -> None:
|
643
|
+
if event is not None:
|
644
|
+
assert metric is None # nosec: B101
|
645
|
+
ObservabilityContext.record_event(
|
646
|
+
level,
|
647
|
+
event,
|
648
|
+
attributes=attributes or {},
|
649
|
+
)
|
669
650
|
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
651
|
+
elif metric is not None:
|
652
|
+
assert event is None # nosec: B101
|
653
|
+
assert value is not None # nosec: B101
|
654
|
+
ObservabilityContext.record_metric(
|
655
|
+
level,
|
656
|
+
metric,
|
657
|
+
value=value,
|
658
|
+
unit=unit,
|
659
|
+
attributes=attributes or {},
|
660
|
+
)
|
674
661
|
|
675
|
-
|
676
|
-
|
677
|
-
|
662
|
+
else:
|
663
|
+
ObservabilityContext.record_attributes(
|
664
|
+
level,
|
665
|
+
attributes=attributes or {},
|
666
|
+
)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from collections.abc import Sequence
|
1
|
+
from collections.abc import Mapping, Sequence
|
2
2
|
from contextvars import ContextVar, Token
|
3
3
|
from enum import IntEnum
|
4
4
|
from logging import DEBUG as DEBUG_LOGGING
|
@@ -7,17 +7,14 @@ from logging import INFO as INFO_LOGGING
|
|
7
7
|
from logging import WARNING as WARNING_LOGGING
|
8
8
|
from logging import Logger, getLogger
|
9
9
|
from types import TracebackType
|
10
|
-
from typing import Any,
|
10
|
+
from typing import Any, Protocol, Self, final, runtime_checkable
|
11
11
|
|
12
12
|
from haiway.context.identifier import ScopeIdentifier
|
13
13
|
from haiway.state import State
|
14
|
-
from haiway.types import
|
14
|
+
from haiway.types import Missing
|
15
|
+
from haiway.utils.formatting import format_str
|
15
16
|
|
16
17
|
__all__ = (
|
17
|
-
"DEBUG",
|
18
|
-
"ERROR",
|
19
|
-
"INFO",
|
20
|
-
"WARNING",
|
21
18
|
"Observability",
|
22
19
|
"ObservabilityAttribute",
|
23
20
|
"ObservabilityAttributesRecording",
|
@@ -39,11 +36,6 @@ class ObservabilityLevel(IntEnum):
|
|
39
36
|
DEBUG = DEBUG_LOGGING
|
40
37
|
|
41
38
|
|
42
|
-
ERROR: Final[int] = ObservabilityLevel.ERROR
|
43
|
-
WARNING: Final[int] = ObservabilityLevel.WARNING
|
44
|
-
INFO: Final[int] = ObservabilityLevel.INFO
|
45
|
-
DEBUG: Final[int] = ObservabilityLevel.DEBUG
|
46
|
-
|
47
39
|
type ObservabilityAttribute = (
|
48
40
|
Sequence[str]
|
49
41
|
| Sequence[float]
|
@@ -68,7 +60,6 @@ class ObservabilityLogRecording(Protocol):
|
|
68
60
|
message: str,
|
69
61
|
*args: Any,
|
70
62
|
exception: BaseException | None,
|
71
|
-
**extra: Any,
|
72
63
|
) -> None: ...
|
73
64
|
|
74
65
|
|
@@ -78,10 +69,10 @@ class ObservabilityEventRecording(Protocol):
|
|
78
69
|
self,
|
79
70
|
scope: ScopeIdentifier,
|
80
71
|
/,
|
81
|
-
*,
|
82
72
|
level: ObservabilityLevel,
|
83
|
-
|
84
|
-
|
73
|
+
*,
|
74
|
+
event: str,
|
75
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
85
76
|
) -> None: ...
|
86
77
|
|
87
78
|
|
@@ -91,11 +82,12 @@ class ObservabilityMetricRecording(Protocol):
|
|
91
82
|
self,
|
92
83
|
scope: ScopeIdentifier,
|
93
84
|
/,
|
85
|
+
level: ObservabilityLevel,
|
94
86
|
*,
|
95
87
|
metric: str,
|
96
88
|
value: float | int,
|
97
89
|
unit: str | None,
|
98
|
-
|
90
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
99
91
|
) -> None: ...
|
100
92
|
|
101
93
|
|
@@ -105,7 +97,8 @@ class ObservabilityAttributesRecording(Protocol):
|
|
105
97
|
self,
|
106
98
|
scope: ScopeIdentifier,
|
107
99
|
/,
|
108
|
-
|
100
|
+
level: ObservabilityLevel,
|
101
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
109
102
|
) -> None: ...
|
110
103
|
|
111
104
|
|
@@ -217,7 +210,6 @@ def _logger_observability(
|
|
217
210
|
message: str,
|
218
211
|
*args: Any,
|
219
212
|
exception: BaseException | None,
|
220
|
-
**extra: Any,
|
221
213
|
) -> None:
|
222
214
|
logger.log(
|
223
215
|
level,
|
@@ -229,42 +221,51 @@ def _logger_observability(
|
|
229
221
|
def event_recording(
|
230
222
|
scope: ScopeIdentifier,
|
231
223
|
/,
|
232
|
-
*,
|
233
224
|
level: ObservabilityLevel,
|
234
|
-
|
235
|
-
|
225
|
+
*,
|
226
|
+
event: str,
|
227
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
236
228
|
) -> None:
|
237
229
|
logger.log(
|
238
230
|
level,
|
239
|
-
f"{scope.unique_name} Recorded event
|
231
|
+
f"{scope.unique_name} Recorded event: {event} {format_str(attributes)}",
|
240
232
|
)
|
241
233
|
|
242
234
|
def metric_recording(
|
243
235
|
scope: ScopeIdentifier,
|
244
236
|
/,
|
237
|
+
level: ObservabilityLevel,
|
245
238
|
*,
|
246
239
|
metric: str,
|
247
240
|
value: float | int,
|
248
241
|
unit: str | None,
|
249
|
-
|
242
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
250
243
|
) -> None:
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
244
|
+
if attributes:
|
245
|
+
logger.log(
|
246
|
+
level,
|
247
|
+
f"{scope.unique_name} Recorded metric: {metric}={value}{unit or ''}"
|
248
|
+
f"\n{format_str(attributes)}",
|
249
|
+
)
|
250
|
+
|
251
|
+
else:
|
252
|
+
logger.log(
|
253
|
+
level,
|
254
|
+
f"{scope.unique_name} Recorded metric: {metric}={value}{unit or ''}",
|
255
|
+
)
|
255
256
|
|
256
257
|
def attributes_recording(
|
257
258
|
scope: ScopeIdentifier,
|
258
259
|
/,
|
259
|
-
|
260
|
+
level: ObservabilityLevel,
|
261
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
260
262
|
) -> None:
|
261
263
|
if not attributes:
|
262
264
|
return
|
263
265
|
|
264
266
|
logger.log(
|
265
|
-
|
266
|
-
f"{scope.unique_name} Recorded attributes:"
|
267
|
-
f"\n{'\n'.join(f'{k}: {v}' for k, v in attributes.items() if v is not None and v is not MISSING)}", # noqa: E501
|
267
|
+
level,
|
268
|
+
f"{scope.unique_name} Recorded attributes: {format_str(attributes)}",
|
268
269
|
)
|
269
270
|
|
270
271
|
def scope_entering[Metric: State](
|
@@ -272,7 +273,7 @@ def _logger_observability(
|
|
272
273
|
/,
|
273
274
|
) -> None:
|
274
275
|
logger.log(
|
275
|
-
DEBUG,
|
276
|
+
ObservabilityLevel.DEBUG,
|
276
277
|
f"{scope.unique_name} Entering scope: {scope.label}",
|
277
278
|
)
|
278
279
|
|
@@ -283,7 +284,7 @@ def _logger_observability(
|
|
283
284
|
exception: BaseException | None,
|
284
285
|
) -> None:
|
285
286
|
logger.log(
|
286
|
-
DEBUG,
|
287
|
+
ObservabilityLevel.DEBUG,
|
287
288
|
f"{scope.unique_name} Exiting scope: {scope.label}",
|
288
289
|
exc_info=exception,
|
289
290
|
)
|
@@ -357,7 +358,6 @@ class ObservabilityContext:
|
|
357
358
|
/,
|
358
359
|
*args: Any,
|
359
360
|
exception: BaseException | None,
|
360
|
-
**extra: Any,
|
361
361
|
) -> None:
|
362
362
|
try: # catch exceptions - we don't wan't to blow up on observability
|
363
363
|
context: Self = cls._context.get()
|
@@ -369,7 +369,6 @@ class ObservabilityContext:
|
|
369
369
|
message,
|
370
370
|
*args,
|
371
371
|
exception=exception,
|
372
|
-
**extra,
|
373
372
|
)
|
374
373
|
|
375
374
|
except LookupError:
|
@@ -383,11 +382,11 @@ class ObservabilityContext:
|
|
383
382
|
@classmethod
|
384
383
|
def record_event(
|
385
384
|
cls,
|
386
|
-
|
385
|
+
level: ObservabilityLevel,
|
386
|
+
event: str,
|
387
387
|
/,
|
388
388
|
*,
|
389
|
-
|
390
|
-
**extra: Any,
|
389
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
391
390
|
) -> None:
|
392
391
|
try: # catch exceptions - we don't wan't to blow up on observability
|
393
392
|
context: Self = cls._context.get()
|
@@ -397,12 +396,12 @@ class ObservabilityContext:
|
|
397
396
|
context._scope,
|
398
397
|
level=level,
|
399
398
|
event=event,
|
400
|
-
|
399
|
+
attributes=attributes,
|
401
400
|
)
|
402
401
|
|
403
402
|
except Exception as exc:
|
404
403
|
cls.record_log(
|
405
|
-
ERROR,
|
404
|
+
ObservabilityLevel.ERROR,
|
406
405
|
f"Failed to record event: {type(event).__qualname__}",
|
407
406
|
exception=exc,
|
408
407
|
)
|
@@ -410,12 +409,13 @@ class ObservabilityContext:
|
|
410
409
|
@classmethod
|
411
410
|
def record_metric(
|
412
411
|
cls,
|
412
|
+
level: ObservabilityLevel,
|
413
413
|
metric: str,
|
414
414
|
/,
|
415
415
|
*,
|
416
416
|
value: float | int,
|
417
417
|
unit: str | None,
|
418
|
-
|
418
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
419
419
|
) -> None:
|
420
420
|
try: # catch exceptions - we don't wan't to blow up on observability
|
421
421
|
context: Self = cls._context.get()
|
@@ -423,15 +423,16 @@ class ObservabilityContext:
|
|
423
423
|
if context.observability is not None:
|
424
424
|
context.observability.metric_recording(
|
425
425
|
context._scope,
|
426
|
+
level=level,
|
426
427
|
metric=metric,
|
427
428
|
value=value,
|
428
429
|
unit=unit,
|
429
|
-
|
430
|
+
attributes=attributes,
|
430
431
|
)
|
431
432
|
|
432
433
|
except Exception as exc:
|
433
434
|
cls.record_log(
|
434
|
-
ERROR,
|
435
|
+
ObservabilityLevel.ERROR,
|
435
436
|
f"Failed to record metric: {metric}",
|
436
437
|
exception=exc,
|
437
438
|
)
|
@@ -439,7 +440,10 @@ class ObservabilityContext:
|
|
439
440
|
@classmethod
|
440
441
|
def record_attributes(
|
441
442
|
cls,
|
442
|
-
|
443
|
+
level: ObservabilityLevel,
|
444
|
+
/,
|
445
|
+
*,
|
446
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
443
447
|
) -> None:
|
444
448
|
try: # catch exceptions - we don't wan't to blow up on observability
|
445
449
|
context: Self = cls._context.get()
|
@@ -447,13 +451,14 @@ class ObservabilityContext:
|
|
447
451
|
if context.observability is not None:
|
448
452
|
context.observability.attributes_recording(
|
449
453
|
context._scope,
|
450
|
-
|
454
|
+
level=level,
|
455
|
+
attributes=attributes,
|
451
456
|
)
|
452
457
|
|
453
458
|
except Exception as exc:
|
454
459
|
cls.record_log(
|
455
|
-
ERROR,
|
456
|
-
|
460
|
+
ObservabilityLevel.ERROR,
|
461
|
+
"Failed to record attributes",
|
457
462
|
exception=exc,
|
458
463
|
)
|
459
464
|
|
@@ -4,14 +4,13 @@ from haiway.helpers.observability import LoggerObservability
|
|
4
4
|
from haiway.helpers.retries import retry
|
5
5
|
from haiway.helpers.throttling import throttle
|
6
6
|
from haiway.helpers.timeouted import timeout
|
7
|
-
from haiway.helpers.tracing import
|
7
|
+
from haiway.helpers.tracing import traced
|
8
8
|
|
9
9
|
__all__ = (
|
10
10
|
"CacheMakeKey",
|
11
11
|
"CacheRead",
|
12
12
|
"CacheWrite",
|
13
13
|
"LoggerObservability",
|
14
|
-
"ResultTrace",
|
15
14
|
"asynchronous",
|
16
15
|
"cache",
|
17
16
|
"retry",
|