haiway 0.16.0__tar.gz → 0.18.0__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.16.0 → haiway-0.18.0}/Makefile +1 -1
- {haiway-0.16.0 → haiway-0.18.0}/PKG-INFO +9 -5
- haiway-0.18.0/junit/test-results.xml +1 -0
- {haiway-0.16.0 → haiway-0.18.0}/pyproject.toml +11 -7
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/__init__.py +18 -18
- haiway-0.18.0/src/haiway/context/__init__.py +34 -0
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/context/access.py +92 -144
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/context/disposables.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/context/identifier.py +4 -5
- haiway-0.18.0/src/haiway/context/observability.py +452 -0
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/context/state.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/context/tasks.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/context/types.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/helpers/__init__.py +7 -6
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/helpers/asynchrony.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/helpers/caching.py +2 -2
- haiway-0.18.0/src/haiway/helpers/observability.py +219 -0
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/helpers/retries.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/helpers/throttling.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/helpers/timeouted.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/helpers/tracing.py +25 -17
- haiway-0.18.0/src/haiway/opentelemetry/__init__.py +3 -0
- haiway-0.18.0/src/haiway/opentelemetry/observability.py +420 -0
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/state/__init__.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/state/attributes.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/state/path.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/state/requirement.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/state/structure.py +161 -30
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/state/validation.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/types/__init__.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/types/default.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/types/frozen.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/types/missing.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/__init__.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/always.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/collections.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/env.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/freezing.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/logs.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/mimic.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/noop.py +2 -2
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/queue.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/utils/stream.py +1 -3
- {haiway-0.16.0 → haiway-0.18.0}/tests/test_state.py +3 -3
- haiway-0.18.0/uv.lock +540 -0
- haiway-0.16.0/junit/test-results.xml +0 -1
- haiway-0.16.0/src/haiway/context/__init__.py +0 -30
- haiway-0.16.0/src/haiway/context/logging.py +0 -242
- haiway-0.16.0/src/haiway/context/metrics.py +0 -214
- haiway-0.16.0/src/haiway/helpers/metrics.py +0 -501
- haiway-0.16.0/uv.lock +0 -318
- {haiway-0.16.0 → haiway-0.18.0}/.github/workflows/ci.yml +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/.github/workflows/publish.yml +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/.gitignore +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/LICENSE +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/README.md +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/config/pre-push +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/.dockerignore +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/Dockerfile +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/Makefile +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/README.md +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/config/.env.example +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/config/unit.json +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/docker-compose.yml +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/pyproject.toml +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/features/__int__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/features/todos/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/features/todos/config.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/features/todos/state.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/features/todos/types.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/features/todos/user_tasks.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/integrations/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/integrations/postgres/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/integrations/postgres/client.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/integrations/postgres/config.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/integrations/postgres/state.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/integrations/postgres/types.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/migrations/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/migrations/__main__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/migrations/postgres/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/migrations/postgres/execution.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/migrations/postgres/migration_0.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/migrations/postgres/types.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/server/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/server/__main__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/server/application.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/server/config.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/server/middlewares/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/server/middlewares/context.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/server/routes/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/server/routes/technical.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/server/routes/todos.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/solutions/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/solutions/user_tasks/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/solutions/user_tasks/config.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/solutions/user_tasks/postgres.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/solutions/user_tasks/state.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/src/solutions/user_tasks/types.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/examples/fastAPI/uv.lock +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/guidelines/functionalities.md +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/guidelines/packages.md +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/src/haiway/py.typed +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/tests/__init__.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/tests/test_async_queue.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/tests/test_async_stream.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/tests/test_attribute_path.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/tests/test_auto_retry.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/tests/test_cache.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/tests/test_context.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/tests/test_streaming.py +0 -0
- {haiway-0.16.0 → haiway-0.18.0}/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.18.0
|
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
|
@@ -35,12 +35,16 @@ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
35
35
|
Classifier: Typing :: Typed
|
36
36
|
Requires-Python: >=3.12
|
37
37
|
Provides-Extra: dev
|
38
|
-
Requires-Dist: bandit~=1.
|
38
|
+
Requires-Dist: bandit~=1.8; extra == 'dev'
|
39
39
|
Requires-Dist: pyright~=1.1; extra == 'dev'
|
40
|
-
Requires-Dist: pytest-asyncio~=0.
|
41
|
-
Requires-Dist: pytest-cov~=
|
42
|
-
Requires-Dist: pytest~=
|
40
|
+
Requires-Dist: pytest-asyncio~=0.26; extra == 'dev'
|
41
|
+
Requires-Dist: pytest-cov~=6.1; extra == 'dev'
|
42
|
+
Requires-Dist: pytest~=8.3; extra == 'dev'
|
43
43
|
Requires-Dist: ruff~=0.11; extra == 'dev'
|
44
|
+
Provides-Extra: opentelemetry
|
45
|
+
Requires-Dist: opentelemetry-api; extra == 'opentelemetry'
|
46
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc; extra == 'opentelemetry'
|
47
|
+
Requires-Dist: opentelemetry-sdk; extra == 'opentelemetry'
|
44
48
|
Description-Content-Type: text/markdown
|
45
49
|
|
46
50
|
# 🚗 haiway 🚕 🚚 🚙
|
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="88" time="1.122" timestamp="2025-05-12T14:08:49.319975+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.007" /><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.001" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_limit_exceed" time="0.001" /><testcase classname="tests.test_cache" name="test_returns_same_value_with_repeating_argument" time="0.001" /><testcase classname="tests.test_cache" name="test_fails_with_error" time="0.001" /><testcase classname="tests.test_cache" name="test_returns_fresh_value_with_expiration_time_exceed" time="0.021" /><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.18.0"
|
9
9
|
readme = "README.md"
|
10
10
|
maintainers = [
|
11
11
|
{ name = "Kacper Kaliński", email = "kacper.kalinski@miquido.com" },
|
@@ -27,14 +27,18 @@ Homepage = "https://miquido.com"
|
|
27
27
|
Repository = "https://github.com/miquido/haiway.git"
|
28
28
|
|
29
29
|
[project.optional-dependencies]
|
30
|
+
opentelemetry = [
|
31
|
+
"opentelemetry-api",
|
32
|
+
"opentelemetry-sdk",
|
33
|
+
"opentelemetry-exporter-otlp-proto-grpc",
|
34
|
+
]
|
30
35
|
dev = [
|
31
|
-
"
|
32
|
-
"ruff~=0.11",
|
36
|
+
"bandit~=1.8",
|
33
37
|
"pyright~=1.1",
|
34
|
-
"
|
35
|
-
"pytest~=
|
36
|
-
"pytest-cov~=
|
37
|
-
"
|
38
|
+
"pytest~=8.3",
|
39
|
+
"pytest-asyncio~=0.26",
|
40
|
+
"pytest-cov~=6.1",
|
41
|
+
"ruff~=0.11",
|
38
42
|
]
|
39
43
|
|
40
44
|
[tool.ruff]
|
@@ -1,14 +1,16 @@
|
|
1
1
|
from haiway.context import (
|
2
2
|
Disposable,
|
3
3
|
Disposables,
|
4
|
-
MetricsContext,
|
5
|
-
MetricsHandler,
|
6
|
-
MetricsReading,
|
7
|
-
MetricsRecording,
|
8
|
-
MetricsScopeEntering,
|
9
|
-
MetricsScopeExiting,
|
10
4
|
MissingContext,
|
11
5
|
MissingState,
|
6
|
+
Observability,
|
7
|
+
ObservabilityContext,
|
8
|
+
ObservabilityEventRecording,
|
9
|
+
ObservabilityLevel,
|
10
|
+
ObservabilityLogRecording,
|
11
|
+
ObservabilityMetricRecording,
|
12
|
+
ObservabilityScopeEntering,
|
13
|
+
ObservabilityScopeExiting,
|
12
14
|
ScopeContext,
|
13
15
|
ScopeIdentifier,
|
14
16
|
StateContext,
|
@@ -16,8 +18,6 @@ from haiway.context import (
|
|
16
18
|
)
|
17
19
|
from haiway.helpers import (
|
18
20
|
ArgumentsTrace,
|
19
|
-
MetricsHolder,
|
20
|
-
MetricsLogger,
|
21
21
|
ResultTrace,
|
22
22
|
asynchronous,
|
23
23
|
cache,
|
@@ -61,7 +61,7 @@ from haiway.utils import (
|
|
61
61
|
without_missing,
|
62
62
|
)
|
63
63
|
|
64
|
-
__all__ =
|
64
|
+
__all__ = (
|
65
65
|
"MISSING",
|
66
66
|
"ArgumentsTrace",
|
67
67
|
"AsyncQueue",
|
@@ -72,17 +72,17 @@ __all__ = [
|
|
72
72
|
"DefaultValue",
|
73
73
|
"Disposable",
|
74
74
|
"Disposables",
|
75
|
-
"MetricsContext",
|
76
|
-
"MetricsHandler",
|
77
|
-
"MetricsHolder",
|
78
|
-
"MetricsLogger",
|
79
|
-
"MetricsReading",
|
80
|
-
"MetricsRecording",
|
81
|
-
"MetricsScopeEntering",
|
82
|
-
"MetricsScopeExiting",
|
83
75
|
"Missing",
|
84
76
|
"MissingContext",
|
85
77
|
"MissingState",
|
78
|
+
"Observability",
|
79
|
+
"ObservabilityContext",
|
80
|
+
"ObservabilityEventRecording",
|
81
|
+
"ObservabilityLevel",
|
82
|
+
"ObservabilityLogRecording",
|
83
|
+
"ObservabilityMetricRecording",
|
84
|
+
"ObservabilityScopeEntering",
|
85
|
+
"ObservabilityScopeExiting",
|
86
86
|
"ResultTrace",
|
87
87
|
"ScopeContext",
|
88
88
|
"ScopeIdentifier",
|
@@ -118,4 +118,4 @@ __all__ = [
|
|
118
118
|
"when_missing",
|
119
119
|
"without_missing",
|
120
120
|
"wrap_async",
|
121
|
-
|
121
|
+
)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from haiway.context.access import ScopeContext, ctx
|
2
|
+
from haiway.context.disposables import Disposable, Disposables
|
3
|
+
from haiway.context.identifier import ScopeIdentifier
|
4
|
+
from haiway.context.observability import (
|
5
|
+
Observability,
|
6
|
+
ObservabilityContext,
|
7
|
+
ObservabilityEventRecording,
|
8
|
+
ObservabilityLevel,
|
9
|
+
ObservabilityLogRecording,
|
10
|
+
ObservabilityMetricRecording,
|
11
|
+
ObservabilityScopeEntering,
|
12
|
+
ObservabilityScopeExiting,
|
13
|
+
)
|
14
|
+
from haiway.context.state import StateContext
|
15
|
+
from haiway.context.types import MissingContext, MissingState
|
16
|
+
|
17
|
+
__all__ = (
|
18
|
+
"Disposable",
|
19
|
+
"Disposables",
|
20
|
+
"MissingContext",
|
21
|
+
"MissingState",
|
22
|
+
"Observability",
|
23
|
+
"ObservabilityContext",
|
24
|
+
"ObservabilityEventRecording",
|
25
|
+
"ObservabilityLevel",
|
26
|
+
"ObservabilityLogRecording",
|
27
|
+
"ObservabilityMetricRecording",
|
28
|
+
"ObservabilityScopeEntering",
|
29
|
+
"ObservabilityScopeExiting",
|
30
|
+
"ScopeContext",
|
31
|
+
"ScopeIdentifier",
|
32
|
+
"StateContext",
|
33
|
+
"ctx",
|
34
|
+
)
|
@@ -18,17 +18,14 @@ from typing import Any, final, overload
|
|
18
18
|
|
19
19
|
from haiway.context.disposables import Disposable, Disposables
|
20
20
|
from haiway.context.identifier import ScopeIdentifier
|
21
|
-
from haiway.context.
|
22
|
-
from haiway.context.metrics import MetricsContext, MetricsHandler
|
21
|
+
from haiway.context.observability import Observability, ObservabilityContext, ObservabilityLevel
|
23
22
|
from haiway.context.state import ScopeState, StateContext
|
24
23
|
from haiway.context.tasks import TaskGroupContext
|
25
24
|
from haiway.state import State
|
26
25
|
from haiway.utils import mimic_function
|
27
26
|
from haiway.utils.stream import AsyncStream
|
28
27
|
|
29
|
-
__all__ =
|
30
|
-
"ctx",
|
31
|
-
]
|
28
|
+
__all__ = ("ctx",)
|
32
29
|
|
33
30
|
|
34
31
|
@final
|
@@ -36,8 +33,7 @@ class ScopeContext:
|
|
36
33
|
__slots__ = (
|
37
34
|
"_disposables",
|
38
35
|
"_identifier",
|
39
|
-
"
|
40
|
-
"_metrics_context",
|
36
|
+
"_observability_context",
|
41
37
|
"_state_context",
|
42
38
|
"_task_group_context",
|
43
39
|
)
|
@@ -45,11 +41,10 @@ class ScopeContext:
|
|
45
41
|
def __init__(
|
46
42
|
self,
|
47
43
|
label: str,
|
48
|
-
logger: Logger | None,
|
49
44
|
task_group: TaskGroup | None,
|
50
45
|
state: tuple[State, ...],
|
51
46
|
disposables: Disposables | None,
|
52
|
-
|
47
|
+
observability: Observability | Logger | None,
|
53
48
|
) -> None:
|
54
49
|
self._identifier: ScopeIdentifier
|
55
50
|
object.__setattr__(
|
@@ -57,23 +52,6 @@ class ScopeContext:
|
|
57
52
|
"_identifier",
|
58
53
|
ScopeIdentifier.scope(label),
|
59
54
|
)
|
60
|
-
self._logger_context: LoggerContext
|
61
|
-
object.__setattr__(
|
62
|
-
self,
|
63
|
-
"_logger_context",
|
64
|
-
LoggerContext(
|
65
|
-
self._identifier,
|
66
|
-
logger=logger,
|
67
|
-
),
|
68
|
-
)
|
69
|
-
self._task_group_context: TaskGroupContext | None
|
70
|
-
object.__setattr__(
|
71
|
-
self,
|
72
|
-
"_task_group_context",
|
73
|
-
TaskGroupContext(task_group=task_group)
|
74
|
-
if task_group is not None or self._identifier.is_root
|
75
|
-
else None,
|
76
|
-
)
|
77
55
|
# prepare state context to capture current state
|
78
56
|
self._state_context: StateContext
|
79
57
|
object.__setattr__(
|
@@ -87,16 +65,24 @@ class ScopeContext:
|
|
87
65
|
"_disposables",
|
88
66
|
disposables,
|
89
67
|
)
|
90
|
-
self.
|
68
|
+
self._observability_context: ObservabilityContext
|
91
69
|
object.__setattr__(
|
92
70
|
self,
|
93
|
-
"
|
94
|
-
# pre-building
|
95
|
-
|
71
|
+
"_observability_context",
|
72
|
+
# pre-building observability context to ensure nested context registering
|
73
|
+
ObservabilityContext.scope(
|
96
74
|
self._identifier,
|
97
|
-
|
75
|
+
observability=observability,
|
98
76
|
),
|
99
77
|
)
|
78
|
+
self._task_group_context: TaskGroupContext | None
|
79
|
+
object.__setattr__(
|
80
|
+
self,
|
81
|
+
"_task_group_context",
|
82
|
+
TaskGroupContext(task_group=task_group)
|
83
|
+
if task_group is not None or self._identifier.is_root
|
84
|
+
else None,
|
85
|
+
)
|
100
86
|
|
101
87
|
def __setattr__(
|
102
88
|
self,
|
@@ -123,9 +109,8 @@ class ScopeContext:
|
|
123
109
|
), "Can't enter synchronous context with task group"
|
124
110
|
assert self._disposables is None, "Can't enter synchronous context with disposables" # nosec: B101
|
125
111
|
self._identifier.__enter__()
|
126
|
-
self.
|
112
|
+
self._observability_context.__enter__()
|
127
113
|
self._state_context.__enter__()
|
128
|
-
self._metrics_context.__enter__()
|
129
114
|
|
130
115
|
return self._identifier.trace_id
|
131
116
|
|
@@ -135,24 +120,16 @@ class ScopeContext:
|
|
135
120
|
exc_val: BaseException | None,
|
136
121
|
exc_tb: TracebackType | None,
|
137
122
|
) -> None:
|
138
|
-
self._metrics_context.__exit__(
|
139
|
-
exc_type=exc_type,
|
140
|
-
exc_val=exc_val,
|
141
|
-
exc_tb=exc_tb,
|
142
|
-
)
|
143
|
-
|
144
123
|
self._state_context.__exit__(
|
145
124
|
exc_type=exc_type,
|
146
125
|
exc_val=exc_val,
|
147
126
|
exc_tb=exc_tb,
|
148
127
|
)
|
149
|
-
|
150
|
-
self._logger_context.__exit__(
|
128
|
+
self._observability_context.__exit__(
|
151
129
|
exc_type=exc_type,
|
152
130
|
exc_val=exc_val,
|
153
131
|
exc_tb=exc_tb,
|
154
132
|
)
|
155
|
-
|
156
133
|
self._identifier.__exit__(
|
157
134
|
exc_type=exc_type,
|
158
135
|
exc_val=exc_val,
|
@@ -161,7 +138,7 @@ class ScopeContext:
|
|
161
138
|
|
162
139
|
async def __aenter__(self) -> str:
|
163
140
|
self._identifier.__enter__()
|
164
|
-
self.
|
141
|
+
self._observability_context.__enter__()
|
165
142
|
|
166
143
|
if task_group := self._task_group_context:
|
167
144
|
await task_group.__aenter__()
|
@@ -183,7 +160,6 @@ class ScopeContext:
|
|
183
160
|
)
|
184
161
|
|
185
162
|
self._state_context.__enter__()
|
186
|
-
self._metrics_context.__enter__()
|
187
163
|
|
188
164
|
return self._identifier.trace_id
|
189
165
|
|
@@ -207,19 +183,13 @@ class ScopeContext:
|
|
207
183
|
exc_tb=exc_tb,
|
208
184
|
)
|
209
185
|
|
210
|
-
self._metrics_context.__exit__(
|
211
|
-
exc_type=exc_type,
|
212
|
-
exc_val=exc_val,
|
213
|
-
exc_tb=exc_tb,
|
214
|
-
)
|
215
|
-
|
216
186
|
self._state_context.__exit__(
|
217
187
|
exc_type=exc_type,
|
218
188
|
exc_val=exc_val,
|
219
189
|
exc_tb=exc_tb,
|
220
190
|
)
|
221
191
|
|
222
|
-
self.
|
192
|
+
self._observability_context.__exit__(
|
223
193
|
exc_type=exc_type,
|
224
194
|
exc_val=exc_val,
|
225
195
|
exc_tb=exc_tb,
|
@@ -288,9 +258,8 @@ class ctx:
|
|
288
258
|
/,
|
289
259
|
*state: State,
|
290
260
|
disposables: Disposables | Iterable[Disposable] | None = None,
|
291
|
-
logger: Logger | None = None,
|
292
261
|
task_group: TaskGroup | None = None,
|
293
|
-
|
262
|
+
observability: Observability | Logger | None = None,
|
294
263
|
) -> ScopeContext:
|
295
264
|
"""
|
296
265
|
Prepare scope context with given parameters. When called within an existing context\
|
@@ -310,18 +279,14 @@ class ctx:
|
|
310
279
|
be added to the scope state. Using asynchronous context is required if any disposables\
|
311
280
|
were provided.
|
312
281
|
|
313
|
-
logger: Logger | None
|
314
|
-
logger used within the scope context, when not provided current logger will be used\
|
315
|
-
if any, otherwise the logger with the scope name will be requested.
|
316
|
-
|
317
282
|
task_group: TaskGroup | None
|
318
283
|
task group used for spawning and joining tasks within the context. Root scope will
|
319
284
|
always have task group created even when not set.
|
320
285
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
286
|
+
observability: Observability | Logger | None = None
|
287
|
+
observability solution responsible for recording and storing metrics, logs and events.\
|
288
|
+
Assigning observability within existing context will result in an error.
|
289
|
+
When not provided, logger with the scope name will be requested and used.
|
325
290
|
|
326
291
|
Returns
|
327
292
|
-------
|
@@ -343,11 +308,10 @@ class ctx:
|
|
343
308
|
|
344
309
|
return ScopeContext(
|
345
310
|
label=label,
|
346
|
-
logger=logger,
|
347
311
|
task_group=task_group,
|
348
312
|
state=state,
|
349
313
|
disposables=resolved_disposables,
|
350
|
-
|
314
|
+
observability=observability,
|
351
315
|
)
|
352
316
|
|
353
317
|
@staticmethod
|
@@ -492,83 +456,6 @@ class ctx:
|
|
492
456
|
default=default,
|
493
457
|
)
|
494
458
|
|
495
|
-
@staticmethod
|
496
|
-
def record(
|
497
|
-
metric: State,
|
498
|
-
/,
|
499
|
-
) -> None:
|
500
|
-
"""
|
501
|
-
Record metric within current scope context.
|
502
|
-
|
503
|
-
Parameters
|
504
|
-
----------
|
505
|
-
metric: State
|
506
|
-
value of metric to be recorded. When a metric implements __add__ it will be added to\
|
507
|
-
current value if any, otherwise subsequent calls may replace existing value.
|
508
|
-
|
509
|
-
Returns
|
510
|
-
-------
|
511
|
-
None
|
512
|
-
"""
|
513
|
-
|
514
|
-
MetricsContext.record(metric)
|
515
|
-
|
516
|
-
@overload
|
517
|
-
@staticmethod
|
518
|
-
async def read[Metric: State](
|
519
|
-
metric: type[Metric],
|
520
|
-
/,
|
521
|
-
*,
|
522
|
-
merged: bool = False,
|
523
|
-
) -> Metric | None: ...
|
524
|
-
|
525
|
-
@overload
|
526
|
-
@staticmethod
|
527
|
-
async def read[Metric: State](
|
528
|
-
metric: type[Metric],
|
529
|
-
/,
|
530
|
-
*,
|
531
|
-
merged: bool = False,
|
532
|
-
default: Metric,
|
533
|
-
) -> Metric: ...
|
534
|
-
|
535
|
-
@staticmethod
|
536
|
-
async def read[Metric: State](
|
537
|
-
metric: type[Metric],
|
538
|
-
/,
|
539
|
-
*,
|
540
|
-
merged: bool = False,
|
541
|
-
default: Metric | None = None,
|
542
|
-
) -> Metric | None:
|
543
|
-
"""
|
544
|
-
Read metric within current scope context.
|
545
|
-
|
546
|
-
Parameters
|
547
|
-
----------
|
548
|
-
metric: type[Metric]
|
549
|
-
type of metric to be read from current context.
|
550
|
-
|
551
|
-
merged: bool
|
552
|
-
control wheather to merge metrics from nested scopes (True)\
|
553
|
-
or access only the current scope value (False) without combining them
|
554
|
-
|
555
|
-
default: Metric | None
|
556
|
-
default value to return when metric was not recorded yet.
|
557
|
-
|
558
|
-
Returns
|
559
|
-
-------
|
560
|
-
Metric | None
|
561
|
-
"""
|
562
|
-
|
563
|
-
value: Metric | None = await MetricsContext.read(
|
564
|
-
metric,
|
565
|
-
merged=merged,
|
566
|
-
)
|
567
|
-
if value is None:
|
568
|
-
return default
|
569
|
-
|
570
|
-
return value
|
571
|
-
|
572
459
|
@staticmethod
|
573
460
|
def log_error(
|
574
461
|
message: str,
|
@@ -596,7 +483,8 @@ class ctx:
|
|
596
483
|
None
|
597
484
|
"""
|
598
485
|
|
599
|
-
|
486
|
+
ObservabilityContext.record_log(
|
487
|
+
ObservabilityLevel.ERROR,
|
600
488
|
message,
|
601
489
|
*args,
|
602
490
|
exception=exception,
|
@@ -629,7 +517,8 @@ class ctx:
|
|
629
517
|
None
|
630
518
|
"""
|
631
519
|
|
632
|
-
|
520
|
+
ObservabilityContext.record_log(
|
521
|
+
ObservabilityLevel.WARNING,
|
633
522
|
message,
|
634
523
|
*args,
|
635
524
|
exception=exception,
|
@@ -658,9 +547,11 @@ class ctx:
|
|
658
547
|
None
|
659
548
|
"""
|
660
549
|
|
661
|
-
|
550
|
+
ObservabilityContext.record_log(
|
551
|
+
ObservabilityLevel.INFO,
|
662
552
|
message,
|
663
553
|
*args,
|
554
|
+
exception=None,
|
664
555
|
)
|
665
556
|
|
666
557
|
@staticmethod
|
@@ -690,8 +581,65 @@ class ctx:
|
|
690
581
|
None
|
691
582
|
"""
|
692
583
|
|
693
|
-
|
584
|
+
ObservabilityContext.record_log(
|
585
|
+
ObservabilityLevel.DEBUG,
|
694
586
|
message,
|
695
587
|
*args,
|
696
588
|
exception=exception,
|
697
589
|
)
|
590
|
+
|
591
|
+
@staticmethod
|
592
|
+
def event(
|
593
|
+
event: State,
|
594
|
+
/,
|
595
|
+
*,
|
596
|
+
level: ObservabilityLevel = ObservabilityLevel.INFO,
|
597
|
+
) -> None:
|
598
|
+
"""
|
599
|
+
Record event within current scope context.
|
600
|
+
|
601
|
+
Parameters
|
602
|
+
----------
|
603
|
+
event: State
|
604
|
+
contents of event to be recorded.
|
605
|
+
|
606
|
+
Returns
|
607
|
+
-------
|
608
|
+
None
|
609
|
+
"""
|
610
|
+
|
611
|
+
ObservabilityContext.record_event(
|
612
|
+
event,
|
613
|
+
level=level,
|
614
|
+
)
|
615
|
+
|
616
|
+
@staticmethod
|
617
|
+
def metric(
|
618
|
+
metric: str,
|
619
|
+
/,
|
620
|
+
*,
|
621
|
+
value: float | int,
|
622
|
+
unit: str | None = None,
|
623
|
+
) -> None:
|
624
|
+
"""
|
625
|
+
Record metric within current scope context.
|
626
|
+
|
627
|
+
Parameters
|
628
|
+
----------
|
629
|
+
metric: State
|
630
|
+
name of metric to be recorded.
|
631
|
+
value: float | int
|
632
|
+
value of metric to be recorded.
|
633
|
+
unit: str | None = None
|
634
|
+
unit of metric to be recorded.
|
635
|
+
|
636
|
+
Returns
|
637
|
+
-------
|
638
|
+
None
|
639
|
+
"""
|
640
|
+
|
641
|
+
ObservabilityContext.record_metric(
|
642
|
+
metric,
|
643
|
+
value=value,
|
644
|
+
unit=unit,
|
645
|
+
)
|
@@ -3,9 +3,7 @@ from types import TracebackType
|
|
3
3
|
from typing import Any, Self, final
|
4
4
|
from uuid import uuid4
|
5
5
|
|
6
|
-
__all__ =
|
7
|
-
"ScopeIdentifier",
|
8
|
-
]
|
6
|
+
__all__ = ("ScopeIdentifier",)
|
9
7
|
|
10
8
|
|
11
9
|
@final
|
@@ -33,10 +31,11 @@ class ScopeIdentifier:
|
|
33
31
|
except LookupError:
|
34
32
|
# create root scope when missing
|
35
33
|
trace_id: str = uuid4().hex
|
34
|
+
scope_id: str = uuid4().hex
|
36
35
|
return cls(
|
37
36
|
label=label,
|
38
|
-
scope_id=
|
39
|
-
parent_id=
|
37
|
+
scope_id=scope_id,
|
38
|
+
parent_id=scope_id, # own id is parent_id for root
|
40
39
|
trace_id=trace_id,
|
41
40
|
)
|
42
41
|
|