haiway 0.18.2__tar.gz → 0.19.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.18.2 → haiway-0.19.0}/PKG-INFO +1 -1
- {haiway-0.18.2 → haiway-0.19.0}/junit/test-results.xml +1 -1
- {haiway-0.18.2 → haiway-0.19.0}/pyproject.toml +1 -1
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/__init__.py +0 -2
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/context/access.py +53 -64
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/context/observability.py +47 -33
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/helpers/__init__.py +1 -2
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/helpers/observability.py +53 -35
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/helpers/tracing.py +35 -43
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/opentelemetry/observability.py +53 -31
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/state/structure.py +3 -151
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/__init__.py +2 -0
- haiway-0.19.0/src/haiway/utils/formatting.py +148 -0
- {haiway-0.18.2 → haiway-0.19.0}/uv.lock +1 -1
- {haiway-0.18.2 → haiway-0.19.0}/.github/workflows/ci.yml +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/.github/workflows/publish.yml +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/.gitignore +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/LICENSE +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/Makefile +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/README.md +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/config/pre-push +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/.dockerignore +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/Dockerfile +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/Makefile +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/README.md +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/config/.env.example +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/config/unit.json +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/docker-compose.yml +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/pyproject.toml +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/features/__int__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/features/todos/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/features/todos/config.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/features/todos/state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/features/todos/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/features/todos/user_tasks.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/integrations/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/integrations/postgres/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/integrations/postgres/client.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/integrations/postgres/config.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/integrations/postgres/state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/integrations/postgres/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/migrations/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/migrations/__main__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/migrations/postgres/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/migrations/postgres/execution.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/migrations/postgres/migration_0.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/migrations/postgres/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/server/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/server/__main__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/server/application.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/server/config.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/server/middlewares/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/server/middlewares/context.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/server/routes/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/server/routes/technical.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/server/routes/todos.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/solutions/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/solutions/user_tasks/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/solutions/user_tasks/config.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/solutions/user_tasks/postgres.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/solutions/user_tasks/state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/src/solutions/user_tasks/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/examples/fastAPI/uv.lock +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/guidelines/functionalities.md +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/guidelines/packages.md +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/context/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/context/disposables.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/context/identifier.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/context/state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/context/tasks.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/context/types.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/helpers/asynchrony.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/helpers/caching.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/helpers/retries.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/helpers/throttling.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/helpers/timeouted.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/opentelemetry/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/py.typed +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/state/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/state/attributes.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/state/path.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/state/requirement.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/state/validation.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/types/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/types/default.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/types/frozen.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/types/missing.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/always.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/collections.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/env.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/freezing.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/logs.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/mimic.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/noop.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/queue.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/src/haiway/utils/stream.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/tests/__init__.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/tests/test_async_queue.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/tests/test_async_stream.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/tests/test_attribute_path.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/tests/test_auto_retry.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/tests/test_cache.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/tests/test_context.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/tests/test_state.py +0 -0
- {haiway-0.18.2 → haiway-0.19.0}/tests/test_streaming.py +0 -0
- {haiway-0.18.2 → haiway-0.19.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.19.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
|
@@ -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.142" timestamp="2025-05-13T08:24:06.016960+00:00" hostname="pkrvmberfyhpb9w"><testcase classname="tests.test_async_queue" name="test_fails_when_stream_fails" time="0.002" /><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.000" /><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.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.001" /><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.0"
|
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
|
@@ -11,7 +11,8 @@ from typing import Any, Final, 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
18
|
"DEBUG",
|
@@ -68,7 +69,6 @@ class ObservabilityLogRecording(Protocol):
|
|
68
69
|
message: str,
|
69
70
|
*args: Any,
|
70
71
|
exception: BaseException | None,
|
71
|
-
**extra: Any,
|
72
72
|
) -> None: ...
|
73
73
|
|
74
74
|
|
@@ -78,10 +78,10 @@ class ObservabilityEventRecording(Protocol):
|
|
78
78
|
self,
|
79
79
|
scope: ScopeIdentifier,
|
80
80
|
/,
|
81
|
-
*,
|
82
81
|
level: ObservabilityLevel,
|
83
|
-
|
84
|
-
|
82
|
+
*,
|
83
|
+
event: str,
|
84
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
85
85
|
) -> None: ...
|
86
86
|
|
87
87
|
|
@@ -91,11 +91,12 @@ class ObservabilityMetricRecording(Protocol):
|
|
91
91
|
self,
|
92
92
|
scope: ScopeIdentifier,
|
93
93
|
/,
|
94
|
+
level: ObservabilityLevel,
|
94
95
|
*,
|
95
96
|
metric: str,
|
96
97
|
value: float | int,
|
97
98
|
unit: str | None,
|
98
|
-
|
99
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
99
100
|
) -> None: ...
|
100
101
|
|
101
102
|
|
@@ -105,7 +106,8 @@ class ObservabilityAttributesRecording(Protocol):
|
|
105
106
|
self,
|
106
107
|
scope: ScopeIdentifier,
|
107
108
|
/,
|
108
|
-
|
109
|
+
level: ObservabilityLevel,
|
110
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
109
111
|
) -> None: ...
|
110
112
|
|
111
113
|
|
@@ -217,7 +219,6 @@ def _logger_observability(
|
|
217
219
|
message: str,
|
218
220
|
*args: Any,
|
219
221
|
exception: BaseException | None,
|
220
|
-
**extra: Any,
|
221
222
|
) -> None:
|
222
223
|
logger.log(
|
223
224
|
level,
|
@@ -229,42 +230,51 @@ def _logger_observability(
|
|
229
230
|
def event_recording(
|
230
231
|
scope: ScopeIdentifier,
|
231
232
|
/,
|
232
|
-
*,
|
233
233
|
level: ObservabilityLevel,
|
234
|
-
|
235
|
-
|
234
|
+
*,
|
235
|
+
event: str,
|
236
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
236
237
|
) -> None:
|
237
238
|
logger.log(
|
238
239
|
level,
|
239
|
-
f"{scope.unique_name} Recorded event
|
240
|
+
f"{scope.unique_name} Recorded event: {event} {format_str(attributes)}",
|
240
241
|
)
|
241
242
|
|
242
243
|
def metric_recording(
|
243
244
|
scope: ScopeIdentifier,
|
244
245
|
/,
|
246
|
+
level: ObservabilityLevel,
|
245
247
|
*,
|
246
248
|
metric: str,
|
247
249
|
value: float | int,
|
248
250
|
unit: str | None,
|
249
|
-
|
251
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
250
252
|
) -> None:
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
253
|
+
if attributes:
|
254
|
+
logger.log(
|
255
|
+
level,
|
256
|
+
f"{scope.unique_name} Recorded metric: {metric}={value}{unit or ''}"
|
257
|
+
f"\n{format_str(attributes)}",
|
258
|
+
)
|
259
|
+
|
260
|
+
else:
|
261
|
+
logger.log(
|
262
|
+
level,
|
263
|
+
f"{scope.unique_name} Recorded metric: {metric}={value}{unit or ''}",
|
264
|
+
)
|
255
265
|
|
256
266
|
def attributes_recording(
|
257
267
|
scope: ScopeIdentifier,
|
258
268
|
/,
|
259
|
-
|
269
|
+
level: ObservabilityLevel,
|
270
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
260
271
|
) -> None:
|
261
272
|
if not attributes:
|
262
273
|
return
|
263
274
|
|
264
275
|
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
|
276
|
+
level,
|
277
|
+
f"{scope.unique_name} Recorded attributes: {format_str(attributes)}",
|
268
278
|
)
|
269
279
|
|
270
280
|
def scope_entering[Metric: State](
|
@@ -357,7 +367,6 @@ class ObservabilityContext:
|
|
357
367
|
/,
|
358
368
|
*args: Any,
|
359
369
|
exception: BaseException | None,
|
360
|
-
**extra: Any,
|
361
370
|
) -> None:
|
362
371
|
try: # catch exceptions - we don't wan't to blow up on observability
|
363
372
|
context: Self = cls._context.get()
|
@@ -369,7 +378,6 @@ class ObservabilityContext:
|
|
369
378
|
message,
|
370
379
|
*args,
|
371
380
|
exception=exception,
|
372
|
-
**extra,
|
373
381
|
)
|
374
382
|
|
375
383
|
except LookupError:
|
@@ -383,11 +391,11 @@ class ObservabilityContext:
|
|
383
391
|
@classmethod
|
384
392
|
def record_event(
|
385
393
|
cls,
|
386
|
-
|
394
|
+
level: ObservabilityLevel,
|
395
|
+
event: str,
|
387
396
|
/,
|
388
397
|
*,
|
389
|
-
|
390
|
-
**extra: Any,
|
398
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
391
399
|
) -> None:
|
392
400
|
try: # catch exceptions - we don't wan't to blow up on observability
|
393
401
|
context: Self = cls._context.get()
|
@@ -397,7 +405,7 @@ class ObservabilityContext:
|
|
397
405
|
context._scope,
|
398
406
|
level=level,
|
399
407
|
event=event,
|
400
|
-
|
408
|
+
attributes=attributes,
|
401
409
|
)
|
402
410
|
|
403
411
|
except Exception as exc:
|
@@ -410,12 +418,13 @@ class ObservabilityContext:
|
|
410
418
|
@classmethod
|
411
419
|
def record_metric(
|
412
420
|
cls,
|
421
|
+
level: ObservabilityLevel,
|
413
422
|
metric: str,
|
414
423
|
/,
|
415
424
|
*,
|
416
425
|
value: float | int,
|
417
426
|
unit: str | None,
|
418
|
-
|
427
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
419
428
|
) -> None:
|
420
429
|
try: # catch exceptions - we don't wan't to blow up on observability
|
421
430
|
context: Self = cls._context.get()
|
@@ -423,10 +432,11 @@ class ObservabilityContext:
|
|
423
432
|
if context.observability is not None:
|
424
433
|
context.observability.metric_recording(
|
425
434
|
context._scope,
|
435
|
+
level=level,
|
426
436
|
metric=metric,
|
427
437
|
value=value,
|
428
438
|
unit=unit,
|
429
|
-
|
439
|
+
attributes=attributes,
|
430
440
|
)
|
431
441
|
|
432
442
|
except Exception as exc:
|
@@ -439,7 +449,10 @@ class ObservabilityContext:
|
|
439
449
|
@classmethod
|
440
450
|
def record_attributes(
|
441
451
|
cls,
|
442
|
-
|
452
|
+
level: ObservabilityLevel,
|
453
|
+
/,
|
454
|
+
*,
|
455
|
+
attributes: Mapping[str, ObservabilityAttribute],
|
443
456
|
) -> None:
|
444
457
|
try: # catch exceptions - we don't wan't to blow up on observability
|
445
458
|
context: Self = cls._context.get()
|
@@ -447,13 +460,14 @@ class ObservabilityContext:
|
|
447
460
|
if context.observability is not None:
|
448
461
|
context.observability.attributes_recording(
|
449
462
|
context._scope,
|
450
|
-
|
463
|
+
level=level,
|
464
|
+
attributes=attributes,
|
451
465
|
)
|
452
466
|
|
453
467
|
except Exception as exc:
|
454
468
|
cls.record_log(
|
455
469
|
ERROR,
|
456
|
-
|
470
|
+
"Failed to record attributes",
|
457
471
|
exception=exc,
|
458
472
|
)
|
459
473
|
|
@@ -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",
|