google-api-core 2.42.0__tar.gz → 2.43.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.
- {google_api_core-2.42.0/google_api_core.egg-info → google_api_core-2.43.1}/PKG-INFO +1 -1
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/_observability.py +230 -1
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/_python_version_support.py +9 -20
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/gapic_v1/method.py +38 -24
- google_api_core-2.43.1/google/api_core/gapic_v1/method_async.py +120 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/grpc_helpers.py +219 -24
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/grpc_helpers_async.py +25 -19
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/version.py +1 -1
- {google_api_core-2.42.0 → google_api_core-2.43.1/google_api_core.egg-info}/PKG-INFO +1 -1
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google_api_core.egg-info/SOURCES.txt +1 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/gapic/test_method_async.py +60 -53
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/test_grpc_helpers_async.py +273 -0
- google_api_core-2.43.1/tests/asyncio/test_observability_async.py +176 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/conftest.py +30 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/gapic/test_method.py +38 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_grpc_helpers.py +411 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_observability.py +141 -85
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_python_version_support.py +39 -1
- google_api_core-2.42.0/google/api_core/gapic_v1/method_async.py +0 -245
- {google_api_core-2.42.0 → google_api_core-2.43.1}/LICENSE +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/MANIFEST.in +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/README.rst +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/_feature_gating_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/_python_package_support.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/_rest_streaming_base.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/bidi.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/bidi_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/bidi_base.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/client_info.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/client_logging.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/client_options.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/datetime_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/exceptions.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/extended_operation.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/future/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/future/_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/future/async_future.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/future/base.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/future/polling.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/gapic_v1/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/gapic_v1/client_info.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/gapic_v1/config.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/gapic_v1/config_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/gapic_v1/requests.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/gapic_v1/routing_header.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/general_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/iam.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operation.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operation_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/abstract_operations_base_client.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/abstract_operations_client.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/operations_async_client.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/operations_client.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/operations_client_config.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/operations_rest_client_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/pagers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/pagers_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/pagers_base.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/transports/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/transports/base.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/transports/rest.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/operations_v1/transports/rest_asyncio.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/page_iterator.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/page_iterator_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/path_template.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/protobuf_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/py.typed +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/rest_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/rest_streaming.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/rest_streaming_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/resumable_transfer/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/resumable_transfer/common.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/resumable_transfer/upload.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/resumable_transfer/upload_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/resumable_transfer/upload_state.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/retry/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/retry/retry_base.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/retry/retry_streaming.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/retry/retry_streaming_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/retry/retry_unary.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/retry/retry_unary_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/retry_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/timeout.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/universe.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/version_header.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google_api_core.egg-info/dependency_links.txt +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google_api_core.egg-info/requires.txt +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/google_api_core.egg-info/top_level.txt +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/pyproject.toml +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/setup.cfg +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/setup.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/future/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/future/test_async_future.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/gapic/test_config_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/operations_v1/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/operations_v1/test_operations_async_client.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/retry/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/retry/test_retry_streaming_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/retry/test_retry_unary_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/test_bidi_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/test_operation_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/test_page_iterator_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/test_rest_streaming_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/asyncio/test_resumable_transfer_async.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/future/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/future/test__helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/future/test_polling.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/gapic/test_client_info.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/gapic/test_config.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/gapic/test_requests.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/gapic/test_routing_header.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/operations_v1/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/operations_v1/test_operations_client.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/operations_v1/test_operations_rest_client.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/retry/__init__.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/retry/test_retry_base.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/retry/test_retry_imports.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/retry/test_retry_streaming.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/retry/test_retry_unary.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_bidi.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_client_info.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_client_logging.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_client_options.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_datetime_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_exceptions.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_extended_operation.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_feature_gating_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_iam.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_operation.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_packaging.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_page_iterator.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_path_template.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_protobuf_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_python_package_support.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_rest_helpers.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_rest_streaming.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_resumable_transfer.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_resumable_transfer_scenarios.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_timeout.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_universe.py +0 -0
- {google_api_core-2.42.0 → google_api_core-2.43.1}/tests/unit/test_version_header.py +0 -0
|
@@ -18,12 +18,20 @@
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
+
import contextlib
|
|
21
22
|
import urllib.parse
|
|
22
23
|
from typing import TYPE_CHECKING, Any, Callable, Sequence
|
|
23
24
|
|
|
24
25
|
from google.api_core import _feature_gating_helpers
|
|
25
26
|
from google.api_core.client_options import ClientOptions
|
|
26
27
|
|
|
28
|
+
try:
|
|
29
|
+
from opentelemetry.instrumentation.utils import (
|
|
30
|
+
suppress_instrumentation as _suppress_instrumentation,
|
|
31
|
+
)
|
|
32
|
+
except ImportError:
|
|
33
|
+
_suppress_instrumentation = contextlib.nullcontext
|
|
34
|
+
|
|
27
35
|
if TYPE_CHECKING:
|
|
28
36
|
# flake8: grpc, trace, and ClientInterceptor are imported only for static analysis and type annotations
|
|
29
37
|
# The 'noqa: F401' comment avoids flake8 "imported but not used" errors.
|
|
@@ -223,6 +231,140 @@ def _get_tracer_provider(
|
|
|
223
231
|
return None
|
|
224
232
|
|
|
225
233
|
|
|
234
|
+
try:
|
|
235
|
+
# flake8: `grpc` imported conditionally for runtime interceptor base classes
|
|
236
|
+
import grpc # noqa: F811
|
|
237
|
+
from grpc import (
|
|
238
|
+
StreamStreamClientInterceptor as _SyncStreamStreamClientInterceptor,
|
|
239
|
+
)
|
|
240
|
+
from grpc import (
|
|
241
|
+
StreamUnaryClientInterceptor as _SyncStreamUnaryClientInterceptor,
|
|
242
|
+
)
|
|
243
|
+
from grpc import (
|
|
244
|
+
UnaryStreamClientInterceptor as _SyncUnaryStreamClientInterceptor,
|
|
245
|
+
)
|
|
246
|
+
from grpc import (
|
|
247
|
+
UnaryUnaryClientInterceptor as _SyncUnaryUnaryClientInterceptor,
|
|
248
|
+
)
|
|
249
|
+
from grpc.aio import (
|
|
250
|
+
StreamStreamClientInterceptor as _AsyncStreamStreamClientInterceptor,
|
|
251
|
+
)
|
|
252
|
+
from grpc.aio import (
|
|
253
|
+
StreamUnaryClientInterceptor as _AsyncStreamUnaryClientInterceptor,
|
|
254
|
+
)
|
|
255
|
+
from grpc.aio import (
|
|
256
|
+
UnaryStreamClientInterceptor as _AsyncUnaryStreamClientInterceptor,
|
|
257
|
+
)
|
|
258
|
+
from grpc.aio import (
|
|
259
|
+
UnaryUnaryClientInterceptor as _AsyncUnaryUnaryClientInterceptor,
|
|
260
|
+
)
|
|
261
|
+
except ImportError: # pragma: NO COVER
|
|
262
|
+
# mypy: Fallbacks: grpc sentinel when optional grpc is not installed in the environment.
|
|
263
|
+
# and distinct empty classes avoid duplicate base class 'object' TypeError at runtime.
|
|
264
|
+
grpc = None # type: ignore[assignment]
|
|
265
|
+
|
|
266
|
+
class _SyncUnaryUnaryClientInterceptor: # type: ignore[no-redef]
|
|
267
|
+
__slots__ = ()
|
|
268
|
+
|
|
269
|
+
class _SyncUnaryStreamClientInterceptor: # type: ignore[no-redef]
|
|
270
|
+
__slots__ = ()
|
|
271
|
+
|
|
272
|
+
class _SyncStreamUnaryClientInterceptor: # type: ignore[no-redef]
|
|
273
|
+
__slots__ = ()
|
|
274
|
+
|
|
275
|
+
class _SyncStreamStreamClientInterceptor: # type: ignore[no-redef]
|
|
276
|
+
__slots__ = ()
|
|
277
|
+
|
|
278
|
+
class _AsyncUnaryUnaryClientInterceptor: # type: ignore[no-redef]
|
|
279
|
+
__slots__ = ()
|
|
280
|
+
|
|
281
|
+
class _AsyncUnaryStreamClientInterceptor: # type: ignore[no-redef]
|
|
282
|
+
__slots__ = ()
|
|
283
|
+
|
|
284
|
+
class _AsyncStreamUnaryClientInterceptor: # type: ignore[no-redef]
|
|
285
|
+
__slots__ = ()
|
|
286
|
+
|
|
287
|
+
class _AsyncStreamStreamClientInterceptor: # type: ignore[no-redef]
|
|
288
|
+
__slots__ = ()
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class _SuppressingClientInterceptor(
|
|
292
|
+
_SyncUnaryUnaryClientInterceptor,
|
|
293
|
+
_SyncUnaryStreamClientInterceptor,
|
|
294
|
+
_SyncStreamUnaryClientInterceptor,
|
|
295
|
+
_SyncStreamStreamClientInterceptor,
|
|
296
|
+
):
|
|
297
|
+
"""Client interceptor that suppresses redundant downstream generic auto-instrumentation spans.
|
|
298
|
+
|
|
299
|
+
When users enable global OpenTelemetry gRPC auto-instrumentation (e.g. GrpcInstrumentorClient),
|
|
300
|
+
the underlying channel is wrapped with generic interceptors that emit bare-bones spans.
|
|
301
|
+
This interceptor wraps downstream calls in OpenTelemetry's native `suppress_instrumentation`
|
|
302
|
+
context manager so that our feature-rich Google Cloud SDK T4 span is emitted while
|
|
303
|
+
redundant generic downstream spans are bypassed.
|
|
304
|
+
"""
|
|
305
|
+
|
|
306
|
+
__slots__ = ()
|
|
307
|
+
|
|
308
|
+
def intercept_unary_unary(
|
|
309
|
+
self, continuation: Any, client_call_details: Any, request: Any
|
|
310
|
+
) -> Any:
|
|
311
|
+
with _suppress_instrumentation():
|
|
312
|
+
return continuation(client_call_details, request)
|
|
313
|
+
|
|
314
|
+
def intercept_unary_stream(
|
|
315
|
+
self, continuation: Any, client_call_details: Any, request: Any
|
|
316
|
+
) -> Any:
|
|
317
|
+
with _suppress_instrumentation():
|
|
318
|
+
return continuation(client_call_details, request)
|
|
319
|
+
|
|
320
|
+
def intercept_stream_unary(
|
|
321
|
+
self, continuation: Any, client_call_details: Any, request_iterator: Any
|
|
322
|
+
) -> Any:
|
|
323
|
+
with _suppress_instrumentation():
|
|
324
|
+
return continuation(client_call_details, request_iterator)
|
|
325
|
+
|
|
326
|
+
def intercept_stream_stream(
|
|
327
|
+
self, continuation: Any, client_call_details: Any, request_iterator: Any
|
|
328
|
+
) -> Any:
|
|
329
|
+
with _suppress_instrumentation():
|
|
330
|
+
return continuation(client_call_details, request_iterator)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class _AsyncSuppressingClientInterceptor(
|
|
334
|
+
_AsyncUnaryUnaryClientInterceptor,
|
|
335
|
+
_AsyncUnaryStreamClientInterceptor,
|
|
336
|
+
_AsyncStreamUnaryClientInterceptor,
|
|
337
|
+
_AsyncStreamStreamClientInterceptor,
|
|
338
|
+
):
|
|
339
|
+
"""AsyncIO client interceptor that suppresses redundant downstream generic auto-instrumentation spans."""
|
|
340
|
+
|
|
341
|
+
__slots__ = ()
|
|
342
|
+
|
|
343
|
+
async def intercept_unary_unary(
|
|
344
|
+
self, continuation: Any, client_call_details: Any, request: Any
|
|
345
|
+
) -> Any:
|
|
346
|
+
with _suppress_instrumentation():
|
|
347
|
+
return await continuation(client_call_details, request)
|
|
348
|
+
|
|
349
|
+
async def intercept_unary_stream(
|
|
350
|
+
self, continuation: Any, client_call_details: Any, request: Any
|
|
351
|
+
) -> Any:
|
|
352
|
+
with _suppress_instrumentation():
|
|
353
|
+
return await continuation(client_call_details, request)
|
|
354
|
+
|
|
355
|
+
async def intercept_stream_unary(
|
|
356
|
+
self, continuation: Any, client_call_details: Any, request_iterator: Any
|
|
357
|
+
) -> Any:
|
|
358
|
+
with _suppress_instrumentation():
|
|
359
|
+
return await continuation(client_call_details, request_iterator)
|
|
360
|
+
|
|
361
|
+
async def intercept_stream_stream(
|
|
362
|
+
self, continuation: Any, client_call_details: Any, request_iterator: Any
|
|
363
|
+
) -> Any:
|
|
364
|
+
with _suppress_instrumentation():
|
|
365
|
+
return await continuation(client_call_details, request_iterator)
|
|
366
|
+
|
|
367
|
+
|
|
226
368
|
def get_otel_interceptor(
|
|
227
369
|
client_options: ClientOptions | dict[str, Any] | None = None,
|
|
228
370
|
) -> Callable[[grpc.Channel], grpc.Channel] | None:
|
|
@@ -249,8 +391,15 @@ def get_otel_interceptor(
|
|
|
249
391
|
request_hook=request_hook,
|
|
250
392
|
response_hook=_grpc_client_response_hook,
|
|
251
393
|
)
|
|
394
|
+
suppressor = _SuppressingClientInterceptor()
|
|
252
395
|
|
|
253
396
|
def otel_interceptor(channel: grpc.Channel) -> grpc.Channel:
|
|
397
|
+
if grpc is not None:
|
|
398
|
+
try:
|
|
399
|
+
channel = grpc.intercept_channel(channel, suppressor)
|
|
400
|
+
except (AttributeError, TypeError):
|
|
401
|
+
# Fallback if grpc lacks intercept_channel or custom channel type rejects it.
|
|
402
|
+
pass
|
|
254
403
|
return otel_grpc.intercept_channel(channel, interceptor)
|
|
255
404
|
|
|
256
405
|
otel_interceptor._is_otel_interceptor = True # type: ignore[attr-defined]
|
|
@@ -279,11 +428,91 @@ def get_otel_async_interceptor(
|
|
|
279
428
|
endpoint_attrs = _extract_endpoint_attributes(client_options)
|
|
280
429
|
request_hook = _make_grpc_client_request_hook(endpoint_attrs)
|
|
281
430
|
|
|
282
|
-
|
|
431
|
+
raw_interceptors = otel_grpc.aio_client_interceptors(
|
|
283
432
|
tracer_provider=_get_tracer_provider(client_options),
|
|
284
433
|
request_hook=request_hook,
|
|
285
434
|
response_hook=_grpc_client_response_hook,
|
|
286
435
|
)
|
|
436
|
+
interceptors = (
|
|
437
|
+
list(raw_interceptors)
|
|
438
|
+
if isinstance(raw_interceptors, (list, tuple))
|
|
439
|
+
else [raw_interceptors]
|
|
440
|
+
)
|
|
441
|
+
interceptors.append(_AsyncSuppressingClientInterceptor())
|
|
442
|
+
|
|
443
|
+
return interceptors
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
_CHANNEL_INTERCEPTOR_MAPPING = (
|
|
447
|
+
("intercept_unary_unary", "_unary_unary_interceptors"),
|
|
448
|
+
("intercept_unary_stream", "_unary_stream_interceptors"),
|
|
449
|
+
("intercept_stream_unary", "_stream_unary_interceptors"),
|
|
450
|
+
("intercept_stream_stream", "_stream_stream_interceptors"),
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def apply_otel_async_channel_interceptors(
|
|
455
|
+
channel: Any,
|
|
456
|
+
client_options: ClientOptions | dict[str, Any] | Sequence[Any] | None = None,
|
|
457
|
+
) -> Any:
|
|
458
|
+
"""Creates and attaches OpenTelemetry client interceptors to the front of an async gRPC channel.
|
|
459
|
+
|
|
460
|
+
In grpc.aio, channels maintain internal interceptor lists evaluated in index order.
|
|
461
|
+
To ensure Google Cloud SDK telemetry wraps outside downstream interceptors and
|
|
462
|
+
suppresses ambient generic auto-instrumentation, our interceptors are prepended
|
|
463
|
+
to the front of the channel's interceptor lists.
|
|
464
|
+
|
|
465
|
+
Args:
|
|
466
|
+
channel: The async gRPC channel to intercept.
|
|
467
|
+
client_options (Optional[Union[ClientOptions, dict[str, Any], Sequence[Any]]]): The client
|
|
468
|
+
options used to resolve feature flags and tracer provider, or a sequence of
|
|
469
|
+
pre-resolved interceptors.
|
|
470
|
+
|
|
471
|
+
Returns:
|
|
472
|
+
The channel with interceptors prepended to its internal lists,
|
|
473
|
+
or the original channel if tracing is disabled or not installed.
|
|
474
|
+
"""
|
|
475
|
+
otel_interceptors: Sequence[Any] | None
|
|
476
|
+
if isinstance(client_options, (ClientOptions, dict)) or client_options is None:
|
|
477
|
+
otel_interceptors = get_otel_async_interceptor(client_options)
|
|
478
|
+
elif isinstance(client_options, Sequence):
|
|
479
|
+
otel_interceptors = client_options
|
|
480
|
+
else:
|
|
481
|
+
otel_interceptors = None
|
|
482
|
+
|
|
483
|
+
if not otel_interceptors:
|
|
484
|
+
return channel
|
|
485
|
+
|
|
486
|
+
interceptor_list = list(otel_interceptors)
|
|
487
|
+
|
|
488
|
+
# Section 1: Typed interceptors - prepend matching interceptors to each
|
|
489
|
+
# corresponding channel list (unary-unary, unary-stream, etc.) in order.
|
|
490
|
+
# See note in the docstring about why prepending is important here.
|
|
491
|
+
for method_name, attr_name in _CHANNEL_INTERCEPTOR_MAPPING:
|
|
492
|
+
target_list = getattr(channel, attr_name, None)
|
|
493
|
+
if isinstance(target_list, list):
|
|
494
|
+
matching = [
|
|
495
|
+
i
|
|
496
|
+
for i in interceptor_list
|
|
497
|
+
if hasattr(i, method_name) and i not in target_list
|
|
498
|
+
]
|
|
499
|
+
if matching:
|
|
500
|
+
target_list[:0] = matching
|
|
501
|
+
|
|
502
|
+
# Section 2: Untyped/generic fallback - prepend any remaining interceptors
|
|
503
|
+
# lacking standard method names directly to the unary-unary list.
|
|
504
|
+
unary_list = getattr(channel, "_unary_unary_interceptors", None)
|
|
505
|
+
if isinstance(unary_list, list):
|
|
506
|
+
standard_methods = tuple(method for method, _ in _CHANNEL_INTERCEPTOR_MAPPING)
|
|
507
|
+
fallback_items = [
|
|
508
|
+
i
|
|
509
|
+
for i in interceptor_list
|
|
510
|
+
if not any(hasattr(i, m) for m in standard_methods) and i not in unary_list
|
|
511
|
+
]
|
|
512
|
+
if fallback_items:
|
|
513
|
+
unary_list[:0] = fallback_items
|
|
514
|
+
|
|
515
|
+
return channel
|
|
287
516
|
|
|
288
517
|
|
|
289
518
|
_TRACE_CONTEXT_PROPAGATOR: Any = None
|
{google_api_core-2.42.0 → google_api_core-2.43.1}/google/api_core/_python_version_support.py
RENAMED
|
@@ -16,12 +16,10 @@
|
|
|
16
16
|
|
|
17
17
|
import datetime
|
|
18
18
|
import enum
|
|
19
|
-
import functools
|
|
20
19
|
import logging
|
|
21
20
|
import sys
|
|
22
21
|
import textwrap
|
|
23
22
|
import warnings
|
|
24
|
-
from importlib import metadata
|
|
25
23
|
from typing import Any, Dict, List, NamedTuple, Optional, Tuple
|
|
26
24
|
|
|
27
25
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -124,7 +122,7 @@ _FAKE_FUTURE_VERSION = VersionInfo(
|
|
|
124
122
|
python_start=_FAKE_FUTURE_DATE,
|
|
125
123
|
python_eol=_FAKE_FUTURE_DATE,
|
|
126
124
|
)
|
|
127
|
-
DEPRECATION_WARNING_PERIOD = datetime.timedelta(days=
|
|
125
|
+
DEPRECATION_WARNING_PERIOD = datetime.timedelta(days=90)
|
|
128
126
|
EOL_GRACE_PERIOD = datetime.timedelta(weeks=1)
|
|
129
127
|
|
|
130
128
|
|
|
@@ -133,25 +131,16 @@ def _flatten_message(text: str) -> str:
|
|
|
133
131
|
return " ".join(textwrap.dedent(text).strip().split())
|
|
134
132
|
|
|
135
133
|
|
|
136
|
-
@functools.cache
|
|
137
|
-
def _cached_packages_distributions():
|
|
138
|
-
return metadata.packages_distributions()
|
|
139
|
-
|
|
140
|
-
|
|
141
134
|
def _get_pypi_package_name(module_name):
|
|
142
135
|
"""Determine the PyPI package name for a given module name."""
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
module_name,
|
|
152
|
-
e,
|
|
153
|
-
)
|
|
154
|
-
|
|
136
|
+
# NOTE(b/578467297, b/578099898): This function is intentionally a no-op
|
|
137
|
+
# that returns None. Calling `importlib.metadata.packages_distributions()`
|
|
138
|
+
# scans every `.dist-info` directory in `site-packages`, causing severe CPU
|
|
139
|
+
# and import-latency overhead across short-lived subprocesses (such as
|
|
140
|
+
# Cloud Composer / Airflow DAG parsing and task startups). Furthermore,
|
|
141
|
+
# `packages_distributions()` keys by top-level package ("google") rather
|
|
142
|
+
# than dotted namespace modules ("google.cloud.foo_v1"), so the lookup
|
|
143
|
+
# always missed for Google Cloud packages anyway.
|
|
155
144
|
return None
|
|
156
145
|
|
|
157
146
|
|
|
@@ -41,6 +41,10 @@ DEFAULT = _MethodDefault._DEFAULT_VALUE
|
|
|
41
41
|
"""Sentinel value indicating that a retry, timeout, or compression argument was unspecified,
|
|
42
42
|
so the default should be used."""
|
|
43
43
|
|
|
44
|
+
_TRANSPORT_KIND_GRPC = "grpc"
|
|
45
|
+
_TRANSPORT_KIND_REST = "rest"
|
|
46
|
+
_DEFAULT_TRANSPORT_KIND = _TRANSPORT_KIND_GRPC
|
|
47
|
+
|
|
44
48
|
|
|
45
49
|
def _is_not_none_or_false(value):
|
|
46
50
|
return value is not None and value is not False
|
|
@@ -122,7 +126,7 @@ def _extract_rpc_identity(
|
|
|
122
126
|
return method_str, service, method
|
|
123
127
|
|
|
124
128
|
|
|
125
|
-
def _extract_status_code(exc: Optional[
|
|
129
|
+
def _extract_status_code(exc: Optional[BaseException]) -> str:
|
|
126
130
|
"""Extract canonical status code name string from an exception.
|
|
127
131
|
|
|
128
132
|
Status code name strings are resolved by inspecting the following locations:
|
|
@@ -132,7 +136,7 @@ def _extract_status_code(exc: Optional[Exception]) -> str:
|
|
|
132
136
|
* Fallback: Defaults to the exception class name for standard Python errors.
|
|
133
137
|
|
|
134
138
|
Args:
|
|
135
|
-
exc (Optional[
|
|
139
|
+
exc (Optional[BaseException]): The exception to extract the status code name from.
|
|
136
140
|
|
|
137
141
|
Returns:
|
|
138
142
|
str: The canonical status code name (e.g. "NOT_FOUND", "UNAVAILABLE") or class name.
|
|
@@ -166,7 +170,7 @@ def _extract_status_code(exc: Optional[Exception]) -> str:
|
|
|
166
170
|
return target.__class__.__name__
|
|
167
171
|
|
|
168
172
|
|
|
169
|
-
def _extract_error_attributes(exc: Optional[
|
|
173
|
+
def _extract_error_attributes(exc: Optional[BaseException]) -> dict[str, Any]:
|
|
170
174
|
"""Extract gcp.errors.* and error.type attributes from an exception.
|
|
171
175
|
|
|
172
176
|
Error details and ErrorInfo structures are resolved by inspecting the following locations:
|
|
@@ -176,7 +180,7 @@ def _extract_error_attributes(exc: Optional[Exception]) -> dict[str, Any]:
|
|
|
176
180
|
* Unified attribute extraction: Extracts domain, reason, and metadata from ErrorInfo or exception attributes.
|
|
177
181
|
|
|
178
182
|
Args:
|
|
179
|
-
exc (Optional[
|
|
183
|
+
exc (Optional[BaseException]): An exception (such as GoogleAPICallError or grpc.RpcError) or ErrorInfo object.
|
|
180
184
|
|
|
181
185
|
Returns:
|
|
182
186
|
dict[str, Any]: Extracted error attributes (e.g. gcp.errors.domain, error.type, gcp.errors.metadata.*).
|
|
@@ -228,9 +232,10 @@ def _extract_error_attributes(exc: Optional[Exception]) -> dict[str, Any]:
|
|
|
228
232
|
|
|
229
233
|
# 5. Extract human-readable error description for cross-language PRD parity
|
|
230
234
|
message = getattr(target_exc, "message", None)
|
|
231
|
-
if not message and hasattr(target_exc, "details")
|
|
232
|
-
|
|
233
|
-
|
|
235
|
+
if not message and hasattr(target_exc, "details"):
|
|
236
|
+
details = target_exc.details
|
|
237
|
+
message = details() if callable(details) else details
|
|
238
|
+
if not message and isinstance(target_exc, BaseException):
|
|
234
239
|
message = str(target_exc)
|
|
235
240
|
if message:
|
|
236
241
|
attrs["status.message"] = str(message)
|
|
@@ -271,6 +276,8 @@ class _GapicCallable(object):
|
|
|
271
276
|
Allowed values for OpenTelemetry method tracing are "grpc" and "rest".
|
|
272
277
|
"""
|
|
273
278
|
|
|
279
|
+
_SUPPORTED_TRACING_KINDS = (_TRANSPORT_KIND_GRPC, _TRANSPORT_KIND_REST)
|
|
280
|
+
|
|
274
281
|
def __init__(
|
|
275
282
|
self,
|
|
276
283
|
target,
|
|
@@ -282,7 +289,7 @@ class _GapicCallable(object):
|
|
|
282
289
|
method_name=None,
|
|
283
290
|
is_streaming=False,
|
|
284
291
|
client_info=None,
|
|
285
|
-
kind=
|
|
292
|
+
kind=_DEFAULT_TRANSPORT_KIND,
|
|
286
293
|
):
|
|
287
294
|
self._target = target
|
|
288
295
|
self._retry = retry
|
|
@@ -301,11 +308,11 @@ class _GapicCallable(object):
|
|
|
301
308
|
self._default_metadata = self._static_metadata
|
|
302
309
|
|
|
303
310
|
# Configure the OpenTelemetry span factory once at initialization.
|
|
304
|
-
# For now, method tracing is gated to non-streaming
|
|
311
|
+
# For now, method tracing is gated to non-streaming calls where an explicit method_name is provided.
|
|
305
312
|
self._start_span_fn = None
|
|
306
313
|
if (
|
|
307
314
|
not is_streaming
|
|
308
|
-
and kind in
|
|
315
|
+
and kind in self._SUPPORTED_TRACING_KINDS
|
|
309
316
|
and method_name is not None
|
|
310
317
|
and _observability.is_otel_capabilities_enabled(client_options)
|
|
311
318
|
):
|
|
@@ -323,9 +330,8 @@ class _GapicCallable(object):
|
|
|
323
330
|
tracer = trace.get_tracer("google.api_core")
|
|
324
331
|
|
|
325
332
|
span_name, _, _ = _extract_rpc_identity(method_name)
|
|
326
|
-
is_rest = kind in ("rest", "rest_asyncio")
|
|
327
333
|
span_attributes = {
|
|
328
|
-
"rpc.system.name": "http" if
|
|
334
|
+
"rpc.system.name": "http" if kind.startswith("rest") else "grpc",
|
|
329
335
|
"rpc.method": span_name,
|
|
330
336
|
}
|
|
331
337
|
self._start_span_fn = functools.partial(
|
|
@@ -338,11 +344,7 @@ class _GapicCallable(object):
|
|
|
338
344
|
# Gracefully disable tracing if OpenTelemetry or custom provider fails
|
|
339
345
|
self._start_span_fn = None
|
|
340
346
|
|
|
341
|
-
def
|
|
342
|
-
self, *args, timeout=DEFAULT, retry=DEFAULT, compression=DEFAULT, **kwargs
|
|
343
|
-
):
|
|
344
|
-
"""Invoke the low-level RPC with retry, timeout, compression, and metadata."""
|
|
345
|
-
|
|
347
|
+
def _prepare_call(self, timeout, retry, compression, kwargs):
|
|
346
348
|
if retry is DEFAULT:
|
|
347
349
|
retry = self._retry
|
|
348
350
|
|
|
@@ -376,22 +378,26 @@ class _GapicCallable(object):
|
|
|
376
378
|
if compression is not None:
|
|
377
379
|
kwargs["compression"] = compression
|
|
378
380
|
|
|
381
|
+
return wrapped_func
|
|
382
|
+
|
|
383
|
+
@contextlib.contextmanager
|
|
384
|
+
def _trace_span(self):
|
|
379
385
|
span_cm = contextlib.nullcontext()
|
|
380
386
|
if self._start_span_fn is not None:
|
|
381
387
|
try:
|
|
382
388
|
span_cm = self._start_span_fn()
|
|
383
|
-
except
|
|
384
|
-
|
|
385
|
-
): # Fail-open: proceed without span if tracing initialization fails
|
|
389
|
+
except Exception:
|
|
390
|
+
# Fail-open: proceed without span if tracing initialization fails
|
|
386
391
|
span_cm = contextlib.nullcontext()
|
|
387
392
|
|
|
388
393
|
with span_cm as span:
|
|
389
394
|
try:
|
|
390
|
-
|
|
395
|
+
yield
|
|
391
396
|
if span is not None and hasattr(span, "set_attribute"):
|
|
392
397
|
span.set_attribute("rpc.response.status_code", "OK")
|
|
393
|
-
|
|
394
|
-
|
|
398
|
+
except (KeyboardInterrupt, SystemExit, GeneratorExit):
|
|
399
|
+
raise
|
|
400
|
+
except BaseException as exc:
|
|
395
401
|
if span is not None and hasattr(span, "set_attribute"):
|
|
396
402
|
span.set_attribute(
|
|
397
403
|
"rpc.response.status_code", _extract_status_code(exc)
|
|
@@ -400,6 +406,14 @@ class _GapicCallable(object):
|
|
|
400
406
|
span.set_attribute(k, v)
|
|
401
407
|
raise
|
|
402
408
|
|
|
409
|
+
def __call__(
|
|
410
|
+
self, *args, timeout=DEFAULT, retry=DEFAULT, compression=DEFAULT, **kwargs
|
|
411
|
+
):
|
|
412
|
+
"""Invoke the low-level RPC with retry, timeout, compression, and metadata."""
|
|
413
|
+
wrapped_func = self._prepare_call(timeout, retry, compression, kwargs)
|
|
414
|
+
with self._trace_span():
|
|
415
|
+
return wrapped_func(*args, **kwargs)
|
|
416
|
+
|
|
403
417
|
|
|
404
418
|
def wrap_method(
|
|
405
419
|
func,
|
|
@@ -412,7 +426,7 @@ def wrap_method(
|
|
|
412
426
|
client_options=None,
|
|
413
427
|
method_name=None,
|
|
414
428
|
is_streaming=False,
|
|
415
|
-
kind=
|
|
429
|
+
kind=_DEFAULT_TRANSPORT_KIND,
|
|
416
430
|
):
|
|
417
431
|
"""Wrap an RPC method with common behavior.
|
|
418
432
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Copyright 2020 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""AsyncIO helpers for wrapping gRPC and REST methods with common functionality.
|
|
15
|
+
|
|
16
|
+
This is used by gapic clients to provide common error mapping, retry, timeout,
|
|
17
|
+
compression, pagination, and long-running operations to methods.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import functools
|
|
21
|
+
import inspect
|
|
22
|
+
|
|
23
|
+
from google.api_core import grpc_helpers_async
|
|
24
|
+
from google.api_core.gapic_v1 import client_info
|
|
25
|
+
from google.api_core.gapic_v1.method import ( # noqa: F401
|
|
26
|
+
DEFAULT,
|
|
27
|
+
USE_DEFAULT_METADATA,
|
|
28
|
+
_GapicCallable,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
_TRANSPORT_KIND_GRPC_ASYNC = "grpc_asyncio"
|
|
32
|
+
_TRANSPORT_KIND_REST_ASYNC = "rest_asyncio"
|
|
33
|
+
_DEFAULT_ASYNC_TRANSPORT_KIND = _TRANSPORT_KIND_GRPC_ASYNC
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class _AsyncGapicCallable(_GapicCallable):
|
|
37
|
+
"""Async callable object that wraps an async RPC method with retry, timeout, metadata, and tracing."""
|
|
38
|
+
|
|
39
|
+
_SUPPORTED_TRACING_KINDS = (
|
|
40
|
+
_TRANSPORT_KIND_GRPC_ASYNC,
|
|
41
|
+
_TRANSPORT_KIND_REST_ASYNC,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
async def __call__(
|
|
45
|
+
self, *args, timeout=DEFAULT, retry=DEFAULT, compression=DEFAULT, **kwargs
|
|
46
|
+
):
|
|
47
|
+
"""Invoke the low-level async RPC with retry, timeout, compression, and metadata."""
|
|
48
|
+
wrapped_func = self._prepare_call(timeout, retry, compression, kwargs)
|
|
49
|
+
with self._trace_span():
|
|
50
|
+
res = wrapped_func(*args, **kwargs)
|
|
51
|
+
if inspect.isawaitable(res):
|
|
52
|
+
return await res
|
|
53
|
+
return res
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def wrap_method(
|
|
57
|
+
func,
|
|
58
|
+
default_retry=None,
|
|
59
|
+
default_timeout=None,
|
|
60
|
+
default_compression=None,
|
|
61
|
+
client_info=client_info.DEFAULT_CLIENT_INFO,
|
|
62
|
+
kind=_DEFAULT_ASYNC_TRANSPORT_KIND,
|
|
63
|
+
*,
|
|
64
|
+
client_options=None,
|
|
65
|
+
method_name=None,
|
|
66
|
+
is_streaming=False,
|
|
67
|
+
):
|
|
68
|
+
"""Wrap an async RPC method with common behavior.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
func (Callable): The low-level async RPC method.
|
|
72
|
+
default_retry (Optional[google.api_core.retry_async.AsyncRetry]): The default
|
|
73
|
+
retry strategy. If ``None``, the method will not retry by default.
|
|
74
|
+
default_timeout (Optional[Union[google.api_core.timeout.Timeout, float]]): The
|
|
75
|
+
default timeout strategy. Can also be specified as an int or float. If
|
|
76
|
+
``None``, the method will not have a timeout specified by default.
|
|
77
|
+
default_compression (Optional[grpc.Compression]): The default
|
|
78
|
+
grpc.Compression. If ``None``, the method will not have
|
|
79
|
+
compression specified by default.
|
|
80
|
+
client_info (Optional[google.api_core.gapic_v1.client_info.ClientInfo]):
|
|
81
|
+
Client information used to create a user-agent string that's
|
|
82
|
+
passed as gRPC metadata to the method. If unspecified, then
|
|
83
|
+
a sane default will be used. If ``None``, then no user agent
|
|
84
|
+
metadata will be provided to the RPC method.
|
|
85
|
+
kind (str): The transport kind for the RPC method. Defaults to "grpc_asyncio".
|
|
86
|
+
Allowed values for OpenTelemetry method tracing are "grpc_asyncio" and "rest_asyncio".
|
|
87
|
+
client_options
|
|
88
|
+
(Optional[google.api_core.client_options.ClientOptions]):
|
|
89
|
+
Client options used to configure client-level behavior, such as
|
|
90
|
+
custom OpenTelemetry tracer providers. Defaults to None.
|
|
91
|
+
method_name (Optional[str]): Optional explicit full RPC method name
|
|
92
|
+
(e.g. "/google.cloud.secretmanager.v1.SecretManagerService/AccessSecretVersion").
|
|
93
|
+
Used to identify the RPC for observability.
|
|
94
|
+
is_streaming (bool): Whether the RPC method is streaming. Defaults to False.
|
|
95
|
+
Streaming methods are currently gated and do not generate Tier 3 spans.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Callable: A new callable that takes optional ``retry``, ``timeout``,
|
|
99
|
+
and ``compression`` arguments and applies the common error mapping,
|
|
100
|
+
retry, timeout, metadata, and compression behavior to the low-level RPC method.
|
|
101
|
+
"""
|
|
102
|
+
if kind == _DEFAULT_ASYNC_TRANSPORT_KIND:
|
|
103
|
+
func = grpc_helpers_async.wrap_errors(func)
|
|
104
|
+
|
|
105
|
+
metadata = [client_info.to_grpc_metadata()] if client_info is not None else None
|
|
106
|
+
|
|
107
|
+
return functools.wraps(func)(
|
|
108
|
+
_AsyncGapicCallable(
|
|
109
|
+
func,
|
|
110
|
+
default_retry,
|
|
111
|
+
default_timeout,
|
|
112
|
+
default_compression,
|
|
113
|
+
metadata=metadata,
|
|
114
|
+
client_options=client_options,
|
|
115
|
+
method_name=method_name,
|
|
116
|
+
is_streaming=is_streaming,
|
|
117
|
+
client_info=client_info,
|
|
118
|
+
kind=kind,
|
|
119
|
+
)
|
|
120
|
+
)
|