structure saas with tools

This commit is contained in:
Davidson Gomes
2025-04-25 15:30:54 -03:00
commit 1aef473937
16434 changed files with 6584257 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

View File

@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from .async_client import TraceServiceAsyncClient
from .client import TraceServiceClient
__all__ = (
"TraceServiceClient",
"TraceServiceAsyncClient",
)

View File

@@ -0,0 +1,670 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from collections import OrderedDict
import logging as std_logging
import re
from typing import (
Callable,
Dict,
Mapping,
MutableMapping,
MutableSequence,
Optional,
Sequence,
Tuple,
Type,
Union,
)
from google.api_core import exceptions as core_exceptions
from google.api_core import gapic_v1
from google.api_core import retry_async as retries
from google.api_core.client_options import ClientOptions
from google.auth import credentials as ga_credentials # type: ignore
from google.oauth2 import service_account # type: ignore
from google.cloud.trace_v1 import gapic_version as package_version
try:
OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None]
except AttributeError: # pragma: NO COVER
OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore
from google.cloud.trace_v1.services.trace_service import pagers
from google.cloud.trace_v1.types import trace
from .client import TraceServiceClient
from .transports.base import DEFAULT_CLIENT_INFO, TraceServiceTransport
from .transports.grpc_asyncio import TraceServiceGrpcAsyncIOTransport
try:
from google.api_core import client_logging # type: ignore
CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
except ImportError: # pragma: NO COVER
CLIENT_LOGGING_SUPPORTED = False
_LOGGER = std_logging.getLogger(__name__)
class TraceServiceAsyncClient:
"""This file describes an API for collecting and viewing traces
and spans within a trace. A Trace is a collection of spans
corresponding to a single operation or set of operations for an
application. A span is an individual timed event which forms a
node of the trace tree. Spans for a single trace may span
multiple services.
"""
_client: TraceServiceClient
# Copy defaults from the synchronous client for use here.
# Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead.
DEFAULT_ENDPOINT = TraceServiceClient.DEFAULT_ENDPOINT
DEFAULT_MTLS_ENDPOINT = TraceServiceClient.DEFAULT_MTLS_ENDPOINT
_DEFAULT_ENDPOINT_TEMPLATE = TraceServiceClient._DEFAULT_ENDPOINT_TEMPLATE
_DEFAULT_UNIVERSE = TraceServiceClient._DEFAULT_UNIVERSE
common_billing_account_path = staticmethod(
TraceServiceClient.common_billing_account_path
)
parse_common_billing_account_path = staticmethod(
TraceServiceClient.parse_common_billing_account_path
)
common_folder_path = staticmethod(TraceServiceClient.common_folder_path)
parse_common_folder_path = staticmethod(TraceServiceClient.parse_common_folder_path)
common_organization_path = staticmethod(TraceServiceClient.common_organization_path)
parse_common_organization_path = staticmethod(
TraceServiceClient.parse_common_organization_path
)
common_project_path = staticmethod(TraceServiceClient.common_project_path)
parse_common_project_path = staticmethod(
TraceServiceClient.parse_common_project_path
)
common_location_path = staticmethod(TraceServiceClient.common_location_path)
parse_common_location_path = staticmethod(
TraceServiceClient.parse_common_location_path
)
@classmethod
def from_service_account_info(cls, info: dict, *args, **kwargs):
"""Creates an instance of this client using the provided credentials
info.
Args:
info (dict): The service account private key info.
args: Additional arguments to pass to the constructor.
kwargs: Additional arguments to pass to the constructor.
Returns:
TraceServiceAsyncClient: The constructed client.
"""
return TraceServiceClient.from_service_account_info.__func__(TraceServiceAsyncClient, info, *args, **kwargs) # type: ignore
@classmethod
def from_service_account_file(cls, filename: str, *args, **kwargs):
"""Creates an instance of this client using the provided credentials
file.
Args:
filename (str): The path to the service account private key json
file.
args: Additional arguments to pass to the constructor.
kwargs: Additional arguments to pass to the constructor.
Returns:
TraceServiceAsyncClient: The constructed client.
"""
return TraceServiceClient.from_service_account_file.__func__(TraceServiceAsyncClient, filename, *args, **kwargs) # type: ignore
from_service_account_json = from_service_account_file
@classmethod
def get_mtls_endpoint_and_cert_source(
cls, client_options: Optional[ClientOptions] = None
):
"""Return the API endpoint and client cert source for mutual TLS.
The client cert source is determined in the following order:
(1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the
client cert source is None.
(2) if `client_options.client_cert_source` is provided, use the provided one; if the
default client cert source exists, use the default one; otherwise the client cert
source is None.
The API endpoint is determined in the following order:
(1) if `client_options.api_endpoint` if provided, use the provided one.
(2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the
default mTLS endpoint; if the environment variable is "never", use the default API
endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise
use the default API endpoint.
More details can be found at https://google.aip.dev/auth/4114.
Args:
client_options (google.api_core.client_options.ClientOptions): Custom options for the
client. Only the `api_endpoint` and `client_cert_source` properties may be used
in this method.
Returns:
Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the
client cert source to use.
Raises:
google.auth.exceptions.MutualTLSChannelError: If any errors happen.
"""
return TraceServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore
@property
def transport(self) -> TraceServiceTransport:
"""Returns the transport used by the client instance.
Returns:
TraceServiceTransport: The transport used by the client instance.
"""
return self._client.transport
@property
def api_endpoint(self):
"""Return the API endpoint used by the client instance.
Returns:
str: The API endpoint used by the client instance.
"""
return self._client._api_endpoint
@property
def universe_domain(self) -> str:
"""Return the universe domain used by the client instance.
Returns:
str: The universe domain used
by the client instance.
"""
return self._client._universe_domain
get_transport_class = TraceServiceClient.get_transport_class
def __init__(
self,
*,
credentials: Optional[ga_credentials.Credentials] = None,
transport: Optional[
Union[str, TraceServiceTransport, Callable[..., TraceServiceTransport]]
] = "grpc_asyncio",
client_options: Optional[ClientOptions] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
) -> None:
"""Instantiates the trace service async client.
Args:
credentials (Optional[google.auth.credentials.Credentials]): The
authorization credentials to attach to requests. These
credentials identify the application to the service; if none
are specified, the client will attempt to ascertain the
credentials from the environment.
transport (Optional[Union[str,TraceServiceTransport,Callable[..., TraceServiceTransport]]]):
The transport to use, or a Callable that constructs and returns a new transport to use.
If a Callable is given, it will be called with the same set of initialization
arguments as used in the TraceServiceTransport constructor.
If set to None, a transport is chosen automatically.
client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]):
Custom options for the client.
1. The ``api_endpoint`` property can be used to override the
default endpoint provided by the client when ``transport`` is
not explicitly provided. Only if this property is not set and
``transport`` was not explicitly provided, the endpoint is
determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment
variable, which have one of the following values:
"always" (always use the default mTLS endpoint), "never" (always
use the default regular endpoint) and "auto" (auto-switch to the
default mTLS endpoint if client certificate is present; this is
the default value).
2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
is "true", then the ``client_cert_source`` property can be used
to provide a client certificate for mTLS transport. If
not provided, the default SSL client certificate will be used if
present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
set, no client certificate will be used.
3. The ``universe_domain`` property can be used to override the
default "googleapis.com" universe. Note that ``api_endpoint``
property still takes precedence; and ``universe_domain`` is
currently not supported for mTLS.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
The client info used to send a user-agent string along with
API requests. If ``None``, then default info will be used.
Generally, you only need to set this if you're developing
your own client library.
Raises:
google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
creation failed for any reason.
"""
self._client = TraceServiceClient(
credentials=credentials,
transport=transport,
client_options=client_options,
client_info=client_info,
)
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
std_logging.DEBUG
): # pragma: NO COVER
_LOGGER.debug(
"Created client `google.devtools.cloudtrace_v1.TraceServiceAsyncClient`.",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"universeDomain": getattr(
self._client._transport._credentials, "universe_domain", ""
),
"credentialsType": f"{type(self._client._transport._credentials).__module__}.{type(self._client._transport._credentials).__qualname__}",
"credentialsInfo": getattr(
self.transport._credentials, "get_cred_info", lambda: None
)(),
}
if hasattr(self._client._transport, "_credentials")
else {
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"credentialsType": None,
},
)
async def list_traces(
self,
request: Optional[Union[trace.ListTracesRequest, dict]] = None,
*,
project_id: Optional[str] = None,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> pagers.ListTracesAsyncPager:
r"""Returns of a list of traces that match the specified
filter conditions.
.. code-block:: python
# This snippet has been automatically generated and should be regarded as a
# code template only.
# It will require modifications to work:
# - It may require correct/in-range values for request initialization.
# - It may require specifying regional endpoints when creating the service
# client as shown in:
# https://googleapis.dev/python/google-api-core/latest/client_options.html
from google.cloud import trace_v1
async def sample_list_traces():
# Create a client
client = trace_v1.TraceServiceAsyncClient()
# Initialize request argument(s)
request = trace_v1.ListTracesRequest(
project_id="project_id_value",
)
# Make the request
page_result = client.list_traces(request=request)
# Handle the response
async for response in page_result:
print(response)
Args:
request (Optional[Union[google.cloud.trace_v1.types.ListTracesRequest, dict]]):
The request object. The request message for the ``ListTraces`` method. All
fields are required unless specified.
project_id (:class:`str`):
Required. ID of the Cloud project
where the trace data is stored.
This corresponds to the ``project_id`` field
on the ``request`` instance; if ``request`` is provided, this
should not be set.
retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any,
should be retried.
timeout (float): The timeout for this request.
metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
sent along with the request as metadata. Normally, each value must be of type `str`,
but for metadata keys ending with the suffix `-bin`, the corresponding values must
be of type `bytes`.
Returns:
google.cloud.trace_v1.services.trace_service.pagers.ListTracesAsyncPager:
The response message for the ListTraces method.
Iterating over this object will yield results and
resolve additional pages automatically.
"""
# Create or coerce a protobuf request object.
# - Quick check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
flattened_params = [project_id]
has_flattened_params = (
len([param for param in flattened_params if param is not None]) > 0
)
if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
# - Use the request object if provided (there's no risk of modifying the input as
# there are no flattened fields), or create one.
if not isinstance(request, trace.ListTracesRequest):
request = trace.ListTracesRequest(request)
# If we have keyword arguments corresponding to fields on the
# request, apply these.
if project_id is not None:
request.project_id = project_id
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
rpc = self._client._transport._wrapped_methods[
self._client._transport.list_traces
]
# Certain fields should be provided within the metadata header;
# add these here.
metadata = tuple(metadata) + (
gapic_v1.routing_header.to_grpc_metadata(
(("project_id", request.project_id),)
),
)
# Validate the universe domain.
self._client._validate_universe_domain()
# Send the request.
response = await rpc(
request,
retry=retry,
timeout=timeout,
metadata=metadata,
)
# This method is paged; wrap the response in a pager, which provides
# an `__aiter__` convenience method.
response = pagers.ListTracesAsyncPager(
method=rpc,
request=request,
response=response,
retry=retry,
timeout=timeout,
metadata=metadata,
)
# Done; return the response.
return response
async def get_trace(
self,
request: Optional[Union[trace.GetTraceRequest, dict]] = None,
*,
project_id: Optional[str] = None,
trace_id: Optional[str] = None,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> trace.Trace:
r"""Gets a single trace by its ID.
.. code-block:: python
# This snippet has been automatically generated and should be regarded as a
# code template only.
# It will require modifications to work:
# - It may require correct/in-range values for request initialization.
# - It may require specifying regional endpoints when creating the service
# client as shown in:
# https://googleapis.dev/python/google-api-core/latest/client_options.html
from google.cloud import trace_v1
async def sample_get_trace():
# Create a client
client = trace_v1.TraceServiceAsyncClient()
# Initialize request argument(s)
request = trace_v1.GetTraceRequest(
project_id="project_id_value",
trace_id="trace_id_value",
)
# Make the request
response = await client.get_trace(request=request)
# Handle the response
print(response)
Args:
request (Optional[Union[google.cloud.trace_v1.types.GetTraceRequest, dict]]):
The request object. The request message for the ``GetTrace`` method.
project_id (:class:`str`):
Required. ID of the Cloud project
where the trace data is stored.
This corresponds to the ``project_id`` field
on the ``request`` instance; if ``request`` is provided, this
should not be set.
trace_id (:class:`str`):
Required. ID of the trace to return.
This corresponds to the ``trace_id`` field
on the ``request`` instance; if ``request`` is provided, this
should not be set.
retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any,
should be retried.
timeout (float): The timeout for this request.
metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
sent along with the request as metadata. Normally, each value must be of type `str`,
but for metadata keys ending with the suffix `-bin`, the corresponding values must
be of type `bytes`.
Returns:
google.cloud.trace_v1.types.Trace:
A trace describes how long it takes
for an application to perform an
operation. It consists of a set of
spans, each of which represent a single
timed event within the operation.
"""
# Create or coerce a protobuf request object.
# - Quick check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
flattened_params = [project_id, trace_id]
has_flattened_params = (
len([param for param in flattened_params if param is not None]) > 0
)
if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
# - Use the request object if provided (there's no risk of modifying the input as
# there are no flattened fields), or create one.
if not isinstance(request, trace.GetTraceRequest):
request = trace.GetTraceRequest(request)
# If we have keyword arguments corresponding to fields on the
# request, apply these.
if project_id is not None:
request.project_id = project_id
if trace_id is not None:
request.trace_id = trace_id
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
rpc = self._client._transport._wrapped_methods[
self._client._transport.get_trace
]
# Certain fields should be provided within the metadata header;
# add these here.
metadata = tuple(metadata) + (
gapic_v1.routing_header.to_grpc_metadata(
(
("project_id", request.project_id),
("trace_id", request.trace_id),
)
),
)
# Validate the universe domain.
self._client._validate_universe_domain()
# Send the request.
response = await rpc(
request,
retry=retry,
timeout=timeout,
metadata=metadata,
)
# Done; return the response.
return response
async def patch_traces(
self,
request: Optional[Union[trace.PatchTracesRequest, dict]] = None,
*,
project_id: Optional[str] = None,
traces: Optional[trace.Traces] = None,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> None:
r"""Sends new traces to Stackdriver Trace or updates
existing traces. If the ID of a trace that you send
matches that of an existing trace, any fields in the
existing trace and its spans are overwritten by the
provided values, and any new fields provided are merged
with the existing trace data. If the ID does not match,
a new trace is created.
.. code-block:: python
# This snippet has been automatically generated and should be regarded as a
# code template only.
# It will require modifications to work:
# - It may require correct/in-range values for request initialization.
# - It may require specifying regional endpoints when creating the service
# client as shown in:
# https://googleapis.dev/python/google-api-core/latest/client_options.html
from google.cloud import trace_v1
async def sample_patch_traces():
# Create a client
client = trace_v1.TraceServiceAsyncClient()
# Initialize request argument(s)
request = trace_v1.PatchTracesRequest(
project_id="project_id_value",
)
# Make the request
await client.patch_traces(request=request)
Args:
request (Optional[Union[google.cloud.trace_v1.types.PatchTracesRequest, dict]]):
The request object. The request message for the ``PatchTraces`` method.
project_id (:class:`str`):
Required. ID of the Cloud project
where the trace data is stored.
This corresponds to the ``project_id`` field
on the ``request`` instance; if ``request`` is provided, this
should not be set.
traces (:class:`google.cloud.trace_v1.types.Traces`):
Required. The body of the message.
This corresponds to the ``traces`` field
on the ``request`` instance; if ``request`` is provided, this
should not be set.
retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any,
should be retried.
timeout (float): The timeout for this request.
metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
sent along with the request as metadata. Normally, each value must be of type `str`,
but for metadata keys ending with the suffix `-bin`, the corresponding values must
be of type `bytes`.
"""
# Create or coerce a protobuf request object.
# - Quick check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
flattened_params = [project_id, traces]
has_flattened_params = (
len([param for param in flattened_params if param is not None]) > 0
)
if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
# - Use the request object if provided (there's no risk of modifying the input as
# there are no flattened fields), or create one.
if not isinstance(request, trace.PatchTracesRequest):
request = trace.PatchTracesRequest(request)
# If we have keyword arguments corresponding to fields on the
# request, apply these.
if project_id is not None:
request.project_id = project_id
if traces is not None:
request.traces = traces
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
rpc = self._client._transport._wrapped_methods[
self._client._transport.patch_traces
]
# Certain fields should be provided within the metadata header;
# add these here.
metadata = tuple(metadata) + (
gapic_v1.routing_header.to_grpc_metadata(
(("project_id", request.project_id),)
),
)
# Validate the universe domain.
self._client._validate_universe_domain()
# Send the request.
await rpc(
request,
retry=retry,
timeout=timeout,
metadata=metadata,
)
async def __aenter__(self) -> "TraceServiceAsyncClient":
return self
async def __aexit__(self, exc_type, exc, tb):
await self.transport.close()
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
gapic_version=package_version.__version__
)
__all__ = ("TraceServiceAsyncClient",)

View File

@@ -0,0 +1,197 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from typing import (
Any,
AsyncIterator,
Awaitable,
Callable,
Iterator,
Optional,
Sequence,
Tuple,
Union,
)
from google.api_core import gapic_v1
from google.api_core import retry as retries
from google.api_core import retry_async as retries_async
try:
OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None]
OptionalAsyncRetry = Union[
retries_async.AsyncRetry, gapic_v1.method._MethodDefault, None
]
except AttributeError: # pragma: NO COVER
OptionalRetry = Union[retries.Retry, object, None] # type: ignore
OptionalAsyncRetry = Union[retries_async.AsyncRetry, object, None] # type: ignore
from google.cloud.trace_v1.types import trace
class ListTracesPager:
"""A pager for iterating through ``list_traces`` requests.
This class thinly wraps an initial
:class:`google.cloud.trace_v1.types.ListTracesResponse` object, and
provides an ``__iter__`` method to iterate through its
``traces`` field.
If there are more pages, the ``__iter__`` method will make additional
``ListTraces`` requests and continue to iterate
through the ``traces`` field on the
corresponding responses.
All the usual :class:`google.cloud.trace_v1.types.ListTracesResponse`
attributes are available on the pager. If multiple requests are made, only
the most recent response is retained, and thus used for attribute lookup.
"""
def __init__(
self,
method: Callable[..., trace.ListTracesResponse],
request: trace.ListTracesRequest,
response: trace.ListTracesResponse,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = ()
):
"""Instantiate the pager.
Args:
method (Callable): The method that was originally called, and
which instantiated this pager.
request (google.cloud.trace_v1.types.ListTracesRequest):
The initial request object.
response (google.cloud.trace_v1.types.ListTracesResponse):
The initial response object.
retry (google.api_core.retry.Retry): Designation of what errors,
if any, should be retried.
timeout (float): The timeout for this request.
metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
sent along with the request as metadata. Normally, each value must be of type `str`,
but for metadata keys ending with the suffix `-bin`, the corresponding values must
be of type `bytes`.
"""
self._method = method
self._request = trace.ListTracesRequest(request)
self._response = response
self._retry = retry
self._timeout = timeout
self._metadata = metadata
def __getattr__(self, name: str) -> Any:
return getattr(self._response, name)
@property
def pages(self) -> Iterator[trace.ListTracesResponse]:
yield self._response
while self._response.next_page_token:
self._request.page_token = self._response.next_page_token
self._response = self._method(
self._request,
retry=self._retry,
timeout=self._timeout,
metadata=self._metadata,
)
yield self._response
def __iter__(self) -> Iterator[trace.Trace]:
for page in self.pages:
yield from page.traces
def __repr__(self) -> str:
return "{0}<{1!r}>".format(self.__class__.__name__, self._response)
class ListTracesAsyncPager:
"""A pager for iterating through ``list_traces`` requests.
This class thinly wraps an initial
:class:`google.cloud.trace_v1.types.ListTracesResponse` object, and
provides an ``__aiter__`` method to iterate through its
``traces`` field.
If there are more pages, the ``__aiter__`` method will make additional
``ListTraces`` requests and continue to iterate
through the ``traces`` field on the
corresponding responses.
All the usual :class:`google.cloud.trace_v1.types.ListTracesResponse`
attributes are available on the pager. If multiple requests are made, only
the most recent response is retained, and thus used for attribute lookup.
"""
def __init__(
self,
method: Callable[..., Awaitable[trace.ListTracesResponse]],
request: trace.ListTracesRequest,
response: trace.ListTracesResponse,
*,
retry: OptionalAsyncRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = ()
):
"""Instantiates the pager.
Args:
method (Callable): The method that was originally called, and
which instantiated this pager.
request (google.cloud.trace_v1.types.ListTracesRequest):
The initial request object.
response (google.cloud.trace_v1.types.ListTracesResponse):
The initial response object.
retry (google.api_core.retry.AsyncRetry): Designation of what errors,
if any, should be retried.
timeout (float): The timeout for this request.
metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
sent along with the request as metadata. Normally, each value must be of type `str`,
but for metadata keys ending with the suffix `-bin`, the corresponding values must
be of type `bytes`.
"""
self._method = method
self._request = trace.ListTracesRequest(request)
self._response = response
self._retry = retry
self._timeout = timeout
self._metadata = metadata
def __getattr__(self, name: str) -> Any:
return getattr(self._response, name)
@property
async def pages(self) -> AsyncIterator[trace.ListTracesResponse]:
yield self._response
while self._response.next_page_token:
self._request.page_token = self._response.next_page_token
self._response = await self._method(
self._request,
retry=self._retry,
timeout=self._timeout,
metadata=self._metadata,
)
yield self._response
def __aiter__(self) -> AsyncIterator[trace.Trace]:
async def async_generator():
async for page in self.pages:
for response in page.traces:
yield response
return async_generator()
def __repr__(self) -> str:
return "{0}<{1!r}>".format(self.__class__.__name__, self._response)

View File

@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from collections import OrderedDict
from typing import Dict, Type
from .base import TraceServiceTransport
from .grpc import TraceServiceGrpcTransport
from .grpc_asyncio import TraceServiceGrpcAsyncIOTransport
from .rest import TraceServiceRestInterceptor, TraceServiceRestTransport
# Compile a registry of transports.
_transport_registry = OrderedDict() # type: Dict[str, Type[TraceServiceTransport]]
_transport_registry["grpc"] = TraceServiceGrpcTransport
_transport_registry["grpc_asyncio"] = TraceServiceGrpcAsyncIOTransport
_transport_registry["rest"] = TraceServiceRestTransport
__all__ = (
"TraceServiceTransport",
"TraceServiceGrpcTransport",
"TraceServiceGrpcAsyncIOTransport",
"TraceServiceRestTransport",
"TraceServiceRestInterceptor",
)

View File

@@ -0,0 +1,220 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import abc
from typing import Awaitable, Callable, Dict, Optional, Sequence, Union
import google.api_core
from google.api_core import exceptions as core_exceptions
from google.api_core import gapic_v1
from google.api_core import retry as retries
import google.auth # type: ignore
from google.auth import credentials as ga_credentials # type: ignore
from google.oauth2 import service_account # type: ignore
from google.protobuf import empty_pb2 # type: ignore
from google.cloud.trace_v1 import gapic_version as package_version
from google.cloud.trace_v1.types import trace
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
gapic_version=package_version.__version__
)
class TraceServiceTransport(abc.ABC):
"""Abstract transport class for TraceService."""
AUTH_SCOPES = (
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/trace.append",
"https://www.googleapis.com/auth/trace.readonly",
)
DEFAULT_HOST: str = "cloudtrace.googleapis.com"
def __init__(
self,
*,
host: str = DEFAULT_HOST,
credentials: Optional[ga_credentials.Credentials] = None,
credentials_file: Optional[str] = None,
scopes: Optional[Sequence[str]] = None,
quota_project_id: Optional[str] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
always_use_jwt_access: Optional[bool] = False,
api_audience: Optional[str] = None,
**kwargs,
) -> None:
"""Instantiate the transport.
Args:
host (Optional[str]):
The hostname to connect to (default: 'cloudtrace.googleapis.com').
credentials (Optional[google.auth.credentials.Credentials]): The
authorization credentials to attach to requests. These
credentials identify the application to the service; if none
are specified, the client will attempt to ascertain the
credentials from the environment.
credentials_file (Optional[str]): A file with credentials that can
be loaded with :func:`google.auth.load_credentials_from_file`.
This argument is mutually exclusive with credentials.
scopes (Optional[Sequence[str]]): A list of scopes.
quota_project_id (Optional[str]): An optional project to use for billing
and quota.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
The client info used to send a user-agent string along with
API requests. If ``None``, then default info will be used.
Generally, you only need to set this if you're developing
your own client library.
always_use_jwt_access (Optional[bool]): Whether self signed JWT should
be used for service account credentials.
"""
scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES}
# Save the scopes.
self._scopes = scopes
if not hasattr(self, "_ignore_credentials"):
self._ignore_credentials: bool = False
# If no credentials are provided, then determine the appropriate
# defaults.
if credentials and credentials_file:
raise core_exceptions.DuplicateCredentialArgs(
"'credentials_file' and 'credentials' are mutually exclusive"
)
if credentials_file is not None:
credentials, _ = google.auth.load_credentials_from_file(
credentials_file, **scopes_kwargs, quota_project_id=quota_project_id
)
elif credentials is None and not self._ignore_credentials:
credentials, _ = google.auth.default(
**scopes_kwargs, quota_project_id=quota_project_id
)
# Don't apply audience if the credentials file passed from user.
if hasattr(credentials, "with_gdch_audience"):
credentials = credentials.with_gdch_audience(
api_audience if api_audience else host
)
# If the credentials are service account credentials, then always try to use self signed JWT.
if (
always_use_jwt_access
and isinstance(credentials, service_account.Credentials)
and hasattr(service_account.Credentials, "with_always_use_jwt_access")
):
credentials = credentials.with_always_use_jwt_access(True)
# Save the credentials.
self._credentials = credentials
# Save the hostname. Default to port 443 (HTTPS) if none is specified.
if ":" not in host:
host += ":443"
self._host = host
@property
def host(self):
return self._host
def _prep_wrapped_messages(self, client_info):
# Precompute the wrapped methods.
self._wrapped_methods = {
self.list_traces: gapic_v1.method.wrap_method(
self.list_traces,
default_retry=retries.Retry(
initial=0.1,
maximum=1.0,
multiplier=1.2,
predicate=retries.if_exception_type(
core_exceptions.DeadlineExceeded,
core_exceptions.ServiceUnavailable,
),
deadline=45.0,
),
default_timeout=45.0,
client_info=client_info,
),
self.get_trace: gapic_v1.method.wrap_method(
self.get_trace,
default_retry=retries.Retry(
initial=0.1,
maximum=1.0,
multiplier=1.2,
predicate=retries.if_exception_type(
core_exceptions.DeadlineExceeded,
core_exceptions.ServiceUnavailable,
),
deadline=45.0,
),
default_timeout=45.0,
client_info=client_info,
),
self.patch_traces: gapic_v1.method.wrap_method(
self.patch_traces,
default_retry=retries.Retry(
initial=0.1,
maximum=1.0,
multiplier=1.2,
predicate=retries.if_exception_type(
core_exceptions.DeadlineExceeded,
core_exceptions.ServiceUnavailable,
),
deadline=45.0,
),
default_timeout=45.0,
client_info=client_info,
),
}
def close(self):
"""Closes resources associated with the transport.
.. warning::
Only call this method if the transport is NOT shared
with other clients - this may cause errors in other clients!
"""
raise NotImplementedError()
@property
def list_traces(
self,
) -> Callable[
[trace.ListTracesRequest],
Union[trace.ListTracesResponse, Awaitable[trace.ListTracesResponse]],
]:
raise NotImplementedError()
@property
def get_trace(
self,
) -> Callable[[trace.GetTraceRequest], Union[trace.Trace, Awaitable[trace.Trace]]]:
raise NotImplementedError()
@property
def patch_traces(
self,
) -> Callable[
[trace.PatchTracesRequest], Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]]
]:
raise NotImplementedError()
@property
def kind(self) -> str:
raise NotImplementedError()
__all__ = ("TraceServiceTransport",)

View File

@@ -0,0 +1,418 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
import logging as std_logging
import pickle
from typing import Callable, Dict, Optional, Sequence, Tuple, Union
import warnings
from google.api_core import gapic_v1, grpc_helpers
import google.auth # type: ignore
from google.auth import credentials as ga_credentials # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore
from google.protobuf import empty_pb2 # type: ignore
from google.protobuf.json_format import MessageToJson
import google.protobuf.message
import grpc # type: ignore
import proto # type: ignore
from google.cloud.trace_v1.types import trace
from .base import DEFAULT_CLIENT_INFO, TraceServiceTransport
try:
from google.api_core import client_logging # type: ignore
CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
except ImportError: # pragma: NO COVER
CLIENT_LOGGING_SUPPORTED = False
_LOGGER = std_logging.getLogger(__name__)
class _LoggingClientInterceptor(grpc.UnaryUnaryClientInterceptor): # pragma: NO COVER
def intercept_unary_unary(self, continuation, client_call_details, request):
logging_enabled = CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
std_logging.DEBUG
)
if logging_enabled: # pragma: NO COVER
request_metadata = client_call_details.metadata
if isinstance(request, proto.Message):
request_payload = type(request).to_json(request)
elif isinstance(request, google.protobuf.message.Message):
request_payload = MessageToJson(request)
else:
request_payload = f"{type(request).__name__}: {pickle.dumps(request)}"
request_metadata = {
key: value.decode("utf-8") if isinstance(value, bytes) else value
for key, value in request_metadata
}
grpc_request = {
"payload": request_payload,
"requestMethod": "grpc",
"metadata": dict(request_metadata),
}
_LOGGER.debug(
f"Sending request for {client_call_details.method}",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"rpcName": client_call_details.method,
"request": grpc_request,
"metadata": grpc_request["metadata"],
},
)
response = continuation(client_call_details, request)
if logging_enabled: # pragma: NO COVER
response_metadata = response.trailing_metadata()
# Convert gRPC metadata `<class 'grpc.aio._metadata.Metadata'>` to list of tuples
metadata = (
dict([(k, str(v)) for k, v in response_metadata])
if response_metadata
else None
)
result = response.result()
if isinstance(result, proto.Message):
response_payload = type(result).to_json(result)
elif isinstance(result, google.protobuf.message.Message):
response_payload = MessageToJson(result)
else:
response_payload = f"{type(result).__name__}: {pickle.dumps(result)}"
grpc_response = {
"payload": response_payload,
"metadata": metadata,
"status": "OK",
}
_LOGGER.debug(
f"Received response for {client_call_details.method}.",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"rpcName": client_call_details.method,
"response": grpc_response,
"metadata": grpc_response["metadata"],
},
)
return response
class TraceServiceGrpcTransport(TraceServiceTransport):
"""gRPC backend transport for TraceService.
This file describes an API for collecting and viewing traces
and spans within a trace. A Trace is a collection of spans
corresponding to a single operation or set of operations for an
application. A span is an individual timed event which forms a
node of the trace tree. Spans for a single trace may span
multiple services.
This class defines the same methods as the primary client, so the
primary client can load the underlying transport implementation
and call it.
It sends protocol buffers over the wire using gRPC (which is built on
top of HTTP/2); the ``grpcio`` package must be installed.
"""
_stubs: Dict[str, Callable]
def __init__(
self,
*,
host: str = "cloudtrace.googleapis.com",
credentials: Optional[ga_credentials.Credentials] = None,
credentials_file: Optional[str] = None,
scopes: Optional[Sequence[str]] = None,
channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None,
api_mtls_endpoint: Optional[str] = None,
client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None,
client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
quota_project_id: Optional[str] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
always_use_jwt_access: Optional[bool] = False,
api_audience: Optional[str] = None,
) -> None:
"""Instantiate the transport.
Args:
host (Optional[str]):
The hostname to connect to (default: 'cloudtrace.googleapis.com').
credentials (Optional[google.auth.credentials.Credentials]): The
authorization credentials to attach to requests. These
credentials identify the application to the service; if none
are specified, the client will attempt to ascertain the
credentials from the environment.
This argument is ignored if a ``channel`` instance is provided.
credentials_file (Optional[str]): A file with credentials that can
be loaded with :func:`google.auth.load_credentials_from_file`.
This argument is ignored if a ``channel`` instance is provided.
scopes (Optional(Sequence[str])): A list of scopes. This argument is
ignored if a ``channel`` instance is provided.
channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]):
A ``Channel`` instance through which to make calls, or a Callable
that constructs and returns one. If set to None, ``self.create_channel``
is used to create the channel. If a Callable is given, it will be called
with the same arguments as used in ``self.create_channel``.
api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
If provided, it overrides the ``host`` argument and tries to create
a mutual TLS channel with client SSL credentials from
``client_cert_source`` or application default SSL credentials.
client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
Deprecated. A callback to provide client SSL certificate bytes and
private key bytes, both in PEM format. It is ignored if
``api_mtls_endpoint`` is None.
ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
for the grpc channel. It is ignored if a ``channel`` instance is provided.
client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]):
A callback to provide client certificate bytes and private key bytes,
both in PEM format. It is used to configure a mutual TLS channel. It is
ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided.
quota_project_id (Optional[str]): An optional project to use for billing
and quota.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
The client info used to send a user-agent string along with
API requests. If ``None``, then default info will be used.
Generally, you only need to set this if you're developing
your own client library.
always_use_jwt_access (Optional[bool]): Whether self signed JWT should
be used for service account credentials.
Raises:
google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
creation failed for any reason.
google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
and ``credentials_file`` are passed.
"""
self._grpc_channel = None
self._ssl_channel_credentials = ssl_channel_credentials
self._stubs: Dict[str, Callable] = {}
if api_mtls_endpoint:
warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning)
if client_cert_source:
warnings.warn("client_cert_source is deprecated", DeprecationWarning)
if isinstance(channel, grpc.Channel):
# Ignore credentials if a channel was passed.
credentials = None
self._ignore_credentials = True
# If a channel was explicitly provided, set it.
self._grpc_channel = channel
self._ssl_channel_credentials = None
else:
if api_mtls_endpoint:
host = api_mtls_endpoint
# Create SSL credentials with client_cert_source or application
# default SSL credentials.
if client_cert_source:
cert, key = client_cert_source()
self._ssl_channel_credentials = grpc.ssl_channel_credentials(
certificate_chain=cert, private_key=key
)
else:
self._ssl_channel_credentials = SslCredentials().ssl_credentials
else:
if client_cert_source_for_mtls and not ssl_channel_credentials:
cert, key = client_cert_source_for_mtls()
self._ssl_channel_credentials = grpc.ssl_channel_credentials(
certificate_chain=cert, private_key=key
)
# The base transport sets the host, credentials and scopes
super().__init__(
host=host,
credentials=credentials,
credentials_file=credentials_file,
scopes=scopes,
quota_project_id=quota_project_id,
client_info=client_info,
always_use_jwt_access=always_use_jwt_access,
api_audience=api_audience,
)
if not self._grpc_channel:
# initialize with the provided callable or the default channel
channel_init = channel or type(self).create_channel
self._grpc_channel = channel_init(
self._host,
# use the credentials which are saved
credentials=self._credentials,
# Set ``credentials_file`` to ``None`` here as
# the credentials that we saved earlier should be used.
credentials_file=None,
scopes=self._scopes,
ssl_credentials=self._ssl_channel_credentials,
quota_project_id=quota_project_id,
options=[
("grpc.max_send_message_length", -1),
("grpc.max_receive_message_length", -1),
],
)
self._interceptor = _LoggingClientInterceptor()
self._logged_channel = grpc.intercept_channel(
self._grpc_channel, self._interceptor
)
# Wrap messages. This must be done after self._logged_channel exists
self._prep_wrapped_messages(client_info)
@classmethod
def create_channel(
cls,
host: str = "cloudtrace.googleapis.com",
credentials: Optional[ga_credentials.Credentials] = None,
credentials_file: Optional[str] = None,
scopes: Optional[Sequence[str]] = None,
quota_project_id: Optional[str] = None,
**kwargs,
) -> grpc.Channel:
"""Create and return a gRPC channel object.
Args:
host (Optional[str]): The host for the channel to use.
credentials (Optional[~.Credentials]): The
authorization credentials to attach to requests. These
credentials identify this application to the service. If
none are specified, the client will attempt to ascertain
the credentials from the environment.
credentials_file (Optional[str]): A file with credentials that can
be loaded with :func:`google.auth.load_credentials_from_file`.
This argument is mutually exclusive with credentials.
scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
service. These are only used when credentials are not specified and
are passed to :func:`google.auth.default`.
quota_project_id (Optional[str]): An optional project to use for billing
and quota.
kwargs (Optional[dict]): Keyword arguments, which are passed to the
channel creation.
Returns:
grpc.Channel: A gRPC channel object.
Raises:
google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
and ``credentials_file`` are passed.
"""
return grpc_helpers.create_channel(
host,
credentials=credentials,
credentials_file=credentials_file,
quota_project_id=quota_project_id,
default_scopes=cls.AUTH_SCOPES,
scopes=scopes,
default_host=cls.DEFAULT_HOST,
**kwargs,
)
@property
def grpc_channel(self) -> grpc.Channel:
"""Return the channel designed to connect to this service."""
return self._grpc_channel
@property
def list_traces(
self,
) -> Callable[[trace.ListTracesRequest], trace.ListTracesResponse]:
r"""Return a callable for the list traces method over gRPC.
Returns of a list of traces that match the specified
filter conditions.
Returns:
Callable[[~.ListTracesRequest],
~.ListTracesResponse]:
A function that, when called, will call the underlying RPC
on the server.
"""
# Generate a "stub function" on-the-fly which will actually make
# the request.
# gRPC handles serialization and deserialization, so we just need
# to pass in the functions for each.
if "list_traces" not in self._stubs:
self._stubs["list_traces"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v1.TraceService/ListTraces",
request_serializer=trace.ListTracesRequest.serialize,
response_deserializer=trace.ListTracesResponse.deserialize,
)
return self._stubs["list_traces"]
@property
def get_trace(self) -> Callable[[trace.GetTraceRequest], trace.Trace]:
r"""Return a callable for the get trace method over gRPC.
Gets a single trace by its ID.
Returns:
Callable[[~.GetTraceRequest],
~.Trace]:
A function that, when called, will call the underlying RPC
on the server.
"""
# Generate a "stub function" on-the-fly which will actually make
# the request.
# gRPC handles serialization and deserialization, so we just need
# to pass in the functions for each.
if "get_trace" not in self._stubs:
self._stubs["get_trace"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v1.TraceService/GetTrace",
request_serializer=trace.GetTraceRequest.serialize,
response_deserializer=trace.Trace.deserialize,
)
return self._stubs["get_trace"]
@property
def patch_traces(self) -> Callable[[trace.PatchTracesRequest], empty_pb2.Empty]:
r"""Return a callable for the patch traces method over gRPC.
Sends new traces to Stackdriver Trace or updates
existing traces. If the ID of a trace that you send
matches that of an existing trace, any fields in the
existing trace and its spans are overwritten by the
provided values, and any new fields provided are merged
with the existing trace data. If the ID does not match,
a new trace is created.
Returns:
Callable[[~.PatchTracesRequest],
~.Empty]:
A function that, when called, will call the underlying RPC
on the server.
"""
# Generate a "stub function" on-the-fly which will actually make
# the request.
# gRPC handles serialization and deserialization, so we just need
# to pass in the functions for each.
if "patch_traces" not in self._stubs:
self._stubs["patch_traces"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v1.TraceService/PatchTraces",
request_serializer=trace.PatchTracesRequest.serialize,
response_deserializer=empty_pb2.Empty.FromString,
)
return self._stubs["patch_traces"]
def close(self):
self._logged_channel.close()
@property
def kind(self) -> str:
return "grpc"
__all__ = ("TraceServiceGrpcTransport",)

View File

@@ -0,0 +1,482 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import inspect
import json
import logging as std_logging
import pickle
from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union
import warnings
from google.api_core import exceptions as core_exceptions
from google.api_core import gapic_v1, grpc_helpers_async
from google.api_core import retry_async as retries
from google.auth import credentials as ga_credentials # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore
from google.protobuf import empty_pb2 # type: ignore
from google.protobuf.json_format import MessageToJson
import google.protobuf.message
import grpc # type: ignore
from grpc.experimental import aio # type: ignore
import proto # type: ignore
from google.cloud.trace_v1.types import trace
from .base import DEFAULT_CLIENT_INFO, TraceServiceTransport
from .grpc import TraceServiceGrpcTransport
try:
from google.api_core import client_logging # type: ignore
CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
except ImportError: # pragma: NO COVER
CLIENT_LOGGING_SUPPORTED = False
_LOGGER = std_logging.getLogger(__name__)
class _LoggingClientAIOInterceptor(
grpc.aio.UnaryUnaryClientInterceptor
): # pragma: NO COVER
async def intercept_unary_unary(self, continuation, client_call_details, request):
logging_enabled = CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
std_logging.DEBUG
)
if logging_enabled: # pragma: NO COVER
request_metadata = client_call_details.metadata
if isinstance(request, proto.Message):
request_payload = type(request).to_json(request)
elif isinstance(request, google.protobuf.message.Message):
request_payload = MessageToJson(request)
else:
request_payload = f"{type(request).__name__}: {pickle.dumps(request)}"
request_metadata = {
key: value.decode("utf-8") if isinstance(value, bytes) else value
for key, value in request_metadata
}
grpc_request = {
"payload": request_payload,
"requestMethod": "grpc",
"metadata": dict(request_metadata),
}
_LOGGER.debug(
f"Sending request for {client_call_details.method}",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"rpcName": str(client_call_details.method),
"request": grpc_request,
"metadata": grpc_request["metadata"],
},
)
response = await continuation(client_call_details, request)
if logging_enabled: # pragma: NO COVER
response_metadata = await response.trailing_metadata()
# Convert gRPC metadata `<class 'grpc.aio._metadata.Metadata'>` to list of tuples
metadata = (
dict([(k, str(v)) for k, v in response_metadata])
if response_metadata
else None
)
result = await response
if isinstance(result, proto.Message):
response_payload = type(result).to_json(result)
elif isinstance(result, google.protobuf.message.Message):
response_payload = MessageToJson(result)
else:
response_payload = f"{type(result).__name__}: {pickle.dumps(result)}"
grpc_response = {
"payload": response_payload,
"metadata": metadata,
"status": "OK",
}
_LOGGER.debug(
f"Received response to rpc {client_call_details.method}.",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"rpcName": str(client_call_details.method),
"response": grpc_response,
"metadata": grpc_response["metadata"],
},
)
return response
class TraceServiceGrpcAsyncIOTransport(TraceServiceTransport):
"""gRPC AsyncIO backend transport for TraceService.
This file describes an API for collecting and viewing traces
and spans within a trace. A Trace is a collection of spans
corresponding to a single operation or set of operations for an
application. A span is an individual timed event which forms a
node of the trace tree. Spans for a single trace may span
multiple services.
This class defines the same methods as the primary client, so the
primary client can load the underlying transport implementation
and call it.
It sends protocol buffers over the wire using gRPC (which is built on
top of HTTP/2); the ``grpcio`` package must be installed.
"""
_grpc_channel: aio.Channel
_stubs: Dict[str, Callable] = {}
@classmethod
def create_channel(
cls,
host: str = "cloudtrace.googleapis.com",
credentials: Optional[ga_credentials.Credentials] = None,
credentials_file: Optional[str] = None,
scopes: Optional[Sequence[str]] = None,
quota_project_id: Optional[str] = None,
**kwargs,
) -> aio.Channel:
"""Create and return a gRPC AsyncIO channel object.
Args:
host (Optional[str]): The host for the channel to use.
credentials (Optional[~.Credentials]): The
authorization credentials to attach to requests. These
credentials identify this application to the service. If
none are specified, the client will attempt to ascertain
the credentials from the environment.
credentials_file (Optional[str]): A file with credentials that can
be loaded with :func:`google.auth.load_credentials_from_file`.
scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
service. These are only used when credentials are not specified and
are passed to :func:`google.auth.default`.
quota_project_id (Optional[str]): An optional project to use for billing
and quota.
kwargs (Optional[dict]): Keyword arguments, which are passed to the
channel creation.
Returns:
aio.Channel: A gRPC AsyncIO channel object.
"""
return grpc_helpers_async.create_channel(
host,
credentials=credentials,
credentials_file=credentials_file,
quota_project_id=quota_project_id,
default_scopes=cls.AUTH_SCOPES,
scopes=scopes,
default_host=cls.DEFAULT_HOST,
**kwargs,
)
def __init__(
self,
*,
host: str = "cloudtrace.googleapis.com",
credentials: Optional[ga_credentials.Credentials] = None,
credentials_file: Optional[str] = None,
scopes: Optional[Sequence[str]] = None,
channel: Optional[Union[aio.Channel, Callable[..., aio.Channel]]] = None,
api_mtls_endpoint: Optional[str] = None,
client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None,
client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
quota_project_id: Optional[str] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
always_use_jwt_access: Optional[bool] = False,
api_audience: Optional[str] = None,
) -> None:
"""Instantiate the transport.
Args:
host (Optional[str]):
The hostname to connect to (default: 'cloudtrace.googleapis.com').
credentials (Optional[google.auth.credentials.Credentials]): The
authorization credentials to attach to requests. These
credentials identify the application to the service; if none
are specified, the client will attempt to ascertain the
credentials from the environment.
This argument is ignored if a ``channel`` instance is provided.
credentials_file (Optional[str]): A file with credentials that can
be loaded with :func:`google.auth.load_credentials_from_file`.
This argument is ignored if a ``channel`` instance is provided.
scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
service. These are only used when credentials are not specified and
are passed to :func:`google.auth.default`.
channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]):
A ``Channel`` instance through which to make calls, or a Callable
that constructs and returns one. If set to None, ``self.create_channel``
is used to create the channel. If a Callable is given, it will be called
with the same arguments as used in ``self.create_channel``.
api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
If provided, it overrides the ``host`` argument and tries to create
a mutual TLS channel with client SSL credentials from
``client_cert_source`` or application default SSL credentials.
client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
Deprecated. A callback to provide client SSL certificate bytes and
private key bytes, both in PEM format. It is ignored if
``api_mtls_endpoint`` is None.
ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
for the grpc channel. It is ignored if a ``channel`` instance is provided.
client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]):
A callback to provide client certificate bytes and private key bytes,
both in PEM format. It is used to configure a mutual TLS channel. It is
ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided.
quota_project_id (Optional[str]): An optional project to use for billing
and quota.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
The client info used to send a user-agent string along with
API requests. If ``None``, then default info will be used.
Generally, you only need to set this if you're developing
your own client library.
always_use_jwt_access (Optional[bool]): Whether self signed JWT should
be used for service account credentials.
Raises:
google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
creation failed for any reason.
google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
and ``credentials_file`` are passed.
"""
self._grpc_channel = None
self._ssl_channel_credentials = ssl_channel_credentials
self._stubs: Dict[str, Callable] = {}
if api_mtls_endpoint:
warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning)
if client_cert_source:
warnings.warn("client_cert_source is deprecated", DeprecationWarning)
if isinstance(channel, aio.Channel):
# Ignore credentials if a channel was passed.
credentials = None
self._ignore_credentials = True
# If a channel was explicitly provided, set it.
self._grpc_channel = channel
self._ssl_channel_credentials = None
else:
if api_mtls_endpoint:
host = api_mtls_endpoint
# Create SSL credentials with client_cert_source or application
# default SSL credentials.
if client_cert_source:
cert, key = client_cert_source()
self._ssl_channel_credentials = grpc.ssl_channel_credentials(
certificate_chain=cert, private_key=key
)
else:
self._ssl_channel_credentials = SslCredentials().ssl_credentials
else:
if client_cert_source_for_mtls and not ssl_channel_credentials:
cert, key = client_cert_source_for_mtls()
self._ssl_channel_credentials = grpc.ssl_channel_credentials(
certificate_chain=cert, private_key=key
)
# The base transport sets the host, credentials and scopes
super().__init__(
host=host,
credentials=credentials,
credentials_file=credentials_file,
scopes=scopes,
quota_project_id=quota_project_id,
client_info=client_info,
always_use_jwt_access=always_use_jwt_access,
api_audience=api_audience,
)
if not self._grpc_channel:
# initialize with the provided callable or the default channel
channel_init = channel or type(self).create_channel
self._grpc_channel = channel_init(
self._host,
# use the credentials which are saved
credentials=self._credentials,
# Set ``credentials_file`` to ``None`` here as
# the credentials that we saved earlier should be used.
credentials_file=None,
scopes=self._scopes,
ssl_credentials=self._ssl_channel_credentials,
quota_project_id=quota_project_id,
options=[
("grpc.max_send_message_length", -1),
("grpc.max_receive_message_length", -1),
],
)
self._interceptor = _LoggingClientAIOInterceptor()
self._grpc_channel._unary_unary_interceptors.append(self._interceptor)
self._logged_channel = self._grpc_channel
self._wrap_with_kind = (
"kind" in inspect.signature(gapic_v1.method_async.wrap_method).parameters
)
# Wrap messages. This must be done after self._logged_channel exists
self._prep_wrapped_messages(client_info)
@property
def grpc_channel(self) -> aio.Channel:
"""Create the channel designed to connect to this service.
This property caches on the instance; repeated calls return
the same channel.
"""
# Return the channel from cache.
return self._grpc_channel
@property
def list_traces(
self,
) -> Callable[[trace.ListTracesRequest], Awaitable[trace.ListTracesResponse]]:
r"""Return a callable for the list traces method over gRPC.
Returns of a list of traces that match the specified
filter conditions.
Returns:
Callable[[~.ListTracesRequest],
Awaitable[~.ListTracesResponse]]:
A function that, when called, will call the underlying RPC
on the server.
"""
# Generate a "stub function" on-the-fly which will actually make
# the request.
# gRPC handles serialization and deserialization, so we just need
# to pass in the functions for each.
if "list_traces" not in self._stubs:
self._stubs["list_traces"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v1.TraceService/ListTraces",
request_serializer=trace.ListTracesRequest.serialize,
response_deserializer=trace.ListTracesResponse.deserialize,
)
return self._stubs["list_traces"]
@property
def get_trace(self) -> Callable[[trace.GetTraceRequest], Awaitable[trace.Trace]]:
r"""Return a callable for the get trace method over gRPC.
Gets a single trace by its ID.
Returns:
Callable[[~.GetTraceRequest],
Awaitable[~.Trace]]:
A function that, when called, will call the underlying RPC
on the server.
"""
# Generate a "stub function" on-the-fly which will actually make
# the request.
# gRPC handles serialization and deserialization, so we just need
# to pass in the functions for each.
if "get_trace" not in self._stubs:
self._stubs["get_trace"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v1.TraceService/GetTrace",
request_serializer=trace.GetTraceRequest.serialize,
response_deserializer=trace.Trace.deserialize,
)
return self._stubs["get_trace"]
@property
def patch_traces(
self,
) -> Callable[[trace.PatchTracesRequest], Awaitable[empty_pb2.Empty]]:
r"""Return a callable for the patch traces method over gRPC.
Sends new traces to Stackdriver Trace or updates
existing traces. If the ID of a trace that you send
matches that of an existing trace, any fields in the
existing trace and its spans are overwritten by the
provided values, and any new fields provided are merged
with the existing trace data. If the ID does not match,
a new trace is created.
Returns:
Callable[[~.PatchTracesRequest],
Awaitable[~.Empty]]:
A function that, when called, will call the underlying RPC
on the server.
"""
# Generate a "stub function" on-the-fly which will actually make
# the request.
# gRPC handles serialization and deserialization, so we just need
# to pass in the functions for each.
if "patch_traces" not in self._stubs:
self._stubs["patch_traces"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v1.TraceService/PatchTraces",
request_serializer=trace.PatchTracesRequest.serialize,
response_deserializer=empty_pb2.Empty.FromString,
)
return self._stubs["patch_traces"]
def _prep_wrapped_messages(self, client_info):
"""Precompute the wrapped methods, overriding the base class method to use async wrappers."""
self._wrapped_methods = {
self.list_traces: self._wrap_method(
self.list_traces,
default_retry=retries.AsyncRetry(
initial=0.1,
maximum=1.0,
multiplier=1.2,
predicate=retries.if_exception_type(
core_exceptions.DeadlineExceeded,
core_exceptions.ServiceUnavailable,
),
deadline=45.0,
),
default_timeout=45.0,
client_info=client_info,
),
self.get_trace: self._wrap_method(
self.get_trace,
default_retry=retries.AsyncRetry(
initial=0.1,
maximum=1.0,
multiplier=1.2,
predicate=retries.if_exception_type(
core_exceptions.DeadlineExceeded,
core_exceptions.ServiceUnavailable,
),
deadline=45.0,
),
default_timeout=45.0,
client_info=client_info,
),
self.patch_traces: self._wrap_method(
self.patch_traces,
default_retry=retries.AsyncRetry(
initial=0.1,
maximum=1.0,
multiplier=1.2,
predicate=retries.if_exception_type(
core_exceptions.DeadlineExceeded,
core_exceptions.ServiceUnavailable,
),
deadline=45.0,
),
default_timeout=45.0,
client_info=client_info,
),
}
def _wrap_method(self, func, *args, **kwargs):
if self._wrap_with_kind: # pragma: NO COVER
kwargs["kind"] = self.kind
return gapic_v1.method_async.wrap_method(func, *args, **kwargs)
def close(self):
return self._logged_channel.close()
@property
def kind(self) -> str:
return "grpc_asyncio"
__all__ = ("TraceServiceGrpcAsyncIOTransport",)

View File

@@ -0,0 +1,736 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import dataclasses
import json # type: ignore
import logging
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
import warnings
from google.api_core import exceptions as core_exceptions
from google.api_core import gapic_v1, rest_helpers, rest_streaming
from google.api_core import retry as retries
from google.auth import credentials as ga_credentials # type: ignore
from google.auth.transport.requests import AuthorizedSession # type: ignore
from google.protobuf import empty_pb2 # type: ignore
from google.protobuf import json_format
from requests import __version__ as requests_version
from google.cloud.trace_v1.types import trace
from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO
from .rest_base import _BaseTraceServiceRestTransport
try:
OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None]
except AttributeError: # pragma: NO COVER
OptionalRetry = Union[retries.Retry, object, None] # type: ignore
try:
from google.api_core import client_logging # type: ignore
CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
except ImportError: # pragma: NO COVER
CLIENT_LOGGING_SUPPORTED = False
_LOGGER = logging.getLogger(__name__)
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version,
grpc_version=None,
rest_version=f"requests@{requests_version}",
)
class TraceServiceRestInterceptor:
"""Interceptor for TraceService.
Interceptors are used to manipulate requests, request metadata, and responses
in arbitrary ways.
Example use cases include:
* Logging
* Verifying requests according to service or custom semantics
* Stripping extraneous information from responses
These use cases and more can be enabled by injecting an
instance of a custom subclass when constructing the TraceServiceRestTransport.
.. code-block:: python
class MyCustomTraceServiceInterceptor(TraceServiceRestInterceptor):
def pre_get_trace(self, request, metadata):
logging.log(f"Received request: {request}")
return request, metadata
def post_get_trace(self, response):
logging.log(f"Received response: {response}")
return response
def pre_list_traces(self, request, metadata):
logging.log(f"Received request: {request}")
return request, metadata
def post_list_traces(self, response):
logging.log(f"Received response: {response}")
return response
def pre_patch_traces(self, request, metadata):
logging.log(f"Received request: {request}")
return request, metadata
transport = TraceServiceRestTransport(interceptor=MyCustomTraceServiceInterceptor())
client = TraceServiceClient(transport=transport)
"""
def pre_get_trace(
self,
request: trace.GetTraceRequest,
metadata: Sequence[Tuple[str, Union[str, bytes]]],
) -> Tuple[trace.GetTraceRequest, Sequence[Tuple[str, Union[str, bytes]]]]:
"""Pre-rpc interceptor for get_trace
Override in a subclass to manipulate the request or metadata
before they are sent to the TraceService server.
"""
return request, metadata
def post_get_trace(self, response: trace.Trace) -> trace.Trace:
"""Post-rpc interceptor for get_trace
DEPRECATED. Please use the `post_get_trace_with_metadata`
interceptor instead.
Override in a subclass to read or manipulate the response
after it is returned by the TraceService server but before
it is returned to user code. This `post_get_trace` interceptor runs
before the `post_get_trace_with_metadata` interceptor.
"""
return response
def post_get_trace_with_metadata(
self, response: trace.Trace, metadata: Sequence[Tuple[str, Union[str, bytes]]]
) -> Tuple[trace.Trace, Sequence[Tuple[str, Union[str, bytes]]]]:
"""Post-rpc interceptor for get_trace
Override in a subclass to read or manipulate the response or metadata after it
is returned by the TraceService server but before it is returned to user code.
We recommend only using this `post_get_trace_with_metadata`
interceptor in new development instead of the `post_get_trace` interceptor.
When both interceptors are used, this `post_get_trace_with_metadata` interceptor runs after the
`post_get_trace` interceptor. The (possibly modified) response returned by
`post_get_trace` will be passed to
`post_get_trace_with_metadata`.
"""
return response, metadata
def pre_list_traces(
self,
request: trace.ListTracesRequest,
metadata: Sequence[Tuple[str, Union[str, bytes]]],
) -> Tuple[trace.ListTracesRequest, Sequence[Tuple[str, Union[str, bytes]]]]:
"""Pre-rpc interceptor for list_traces
Override in a subclass to manipulate the request or metadata
before they are sent to the TraceService server.
"""
return request, metadata
def post_list_traces(
self, response: trace.ListTracesResponse
) -> trace.ListTracesResponse:
"""Post-rpc interceptor for list_traces
DEPRECATED. Please use the `post_list_traces_with_metadata`
interceptor instead.
Override in a subclass to read or manipulate the response
after it is returned by the TraceService server but before
it is returned to user code. This `post_list_traces` interceptor runs
before the `post_list_traces_with_metadata` interceptor.
"""
return response
def post_list_traces_with_metadata(
self,
response: trace.ListTracesResponse,
metadata: Sequence[Tuple[str, Union[str, bytes]]],
) -> Tuple[trace.ListTracesResponse, Sequence[Tuple[str, Union[str, bytes]]]]:
"""Post-rpc interceptor for list_traces
Override in a subclass to read or manipulate the response or metadata after it
is returned by the TraceService server but before it is returned to user code.
We recommend only using this `post_list_traces_with_metadata`
interceptor in new development instead of the `post_list_traces` interceptor.
When both interceptors are used, this `post_list_traces_with_metadata` interceptor runs after the
`post_list_traces` interceptor. The (possibly modified) response returned by
`post_list_traces` will be passed to
`post_list_traces_with_metadata`.
"""
return response, metadata
def pre_patch_traces(
self,
request: trace.PatchTracesRequest,
metadata: Sequence[Tuple[str, Union[str, bytes]]],
) -> Tuple[trace.PatchTracesRequest, Sequence[Tuple[str, Union[str, bytes]]]]:
"""Pre-rpc interceptor for patch_traces
Override in a subclass to manipulate the request or metadata
before they are sent to the TraceService server.
"""
return request, metadata
@dataclasses.dataclass
class TraceServiceRestStub:
_session: AuthorizedSession
_host: str
_interceptor: TraceServiceRestInterceptor
class TraceServiceRestTransport(_BaseTraceServiceRestTransport):
"""REST backend synchronous transport for TraceService.
This file describes an API for collecting and viewing traces
and spans within a trace. A Trace is a collection of spans
corresponding to a single operation or set of operations for an
application. A span is an individual timed event which forms a
node of the trace tree. Spans for a single trace may span
multiple services.
This class defines the same methods as the primary client, so the
primary client can load the underlying transport implementation
and call it.
It sends JSON representations of protocol buffers over HTTP/1.1
"""
def __init__(
self,
*,
host: str = "cloudtrace.googleapis.com",
credentials: Optional[ga_credentials.Credentials] = None,
credentials_file: Optional[str] = None,
scopes: Optional[Sequence[str]] = None,
client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
quota_project_id: Optional[str] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
always_use_jwt_access: Optional[bool] = False,
url_scheme: str = "https",
interceptor: Optional[TraceServiceRestInterceptor] = None,
api_audience: Optional[str] = None,
) -> None:
"""Instantiate the transport.
Args:
host (Optional[str]):
The hostname to connect to (default: 'cloudtrace.googleapis.com').
credentials (Optional[google.auth.credentials.Credentials]): The
authorization credentials to attach to requests. These
credentials identify the application to the service; if none
are specified, the client will attempt to ascertain the
credentials from the environment.
credentials_file (Optional[str]): A file with credentials that can
be loaded with :func:`google.auth.load_credentials_from_file`.
This argument is ignored if ``channel`` is provided.
scopes (Optional(Sequence[str])): A list of scopes. This argument is
ignored if ``channel`` is provided.
client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client
certificate to configure mutual TLS HTTP channel. It is ignored
if ``channel`` is provided.
quota_project_id (Optional[str]): An optional project to use for billing
and quota.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
The client info used to send a user-agent string along with
API requests. If ``None``, then default info will be used.
Generally, you only need to set this if you are developing
your own client library.
always_use_jwt_access (Optional[bool]): Whether self signed JWT should
be used for service account credentials.
url_scheme: the protocol scheme for the API endpoint. Normally
"https", but for testing or local servers,
"http" can be specified.
"""
# Run the base constructor
# TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc.
# TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the
# credentials object
super().__init__(
host=host,
credentials=credentials,
client_info=client_info,
always_use_jwt_access=always_use_jwt_access,
url_scheme=url_scheme,
api_audience=api_audience,
)
self._session = AuthorizedSession(
self._credentials, default_host=self.DEFAULT_HOST
)
if client_cert_source_for_mtls:
self._session.configure_mtls_channel(client_cert_source_for_mtls)
self._interceptor = interceptor or TraceServiceRestInterceptor()
self._prep_wrapped_messages(client_info)
class _GetTrace(_BaseTraceServiceRestTransport._BaseGetTrace, TraceServiceRestStub):
def __hash__(self):
return hash("TraceServiceRestTransport.GetTrace")
@staticmethod
def _get_response(
host,
metadata,
query_params,
session,
timeout,
transcoded_request,
body=None,
):
uri = transcoded_request["uri"]
method = transcoded_request["method"]
headers = dict(metadata)
headers["Content-Type"] = "application/json"
response = getattr(session, method)(
"{host}{uri}".format(host=host, uri=uri),
timeout=timeout,
headers=headers,
params=rest_helpers.flatten_query_params(query_params, strict=True),
)
return response
def __call__(
self,
request: trace.GetTraceRequest,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Optional[float] = None,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> trace.Trace:
r"""Call the get trace method over HTTP.
Args:
request (~.trace.GetTraceRequest):
The request object. The request message for the ``GetTrace`` method.
retry (google.api_core.retry.Retry): Designation of what errors, if any,
should be retried.
timeout (float): The timeout for this request.
metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
sent along with the request as metadata. Normally, each value must be of type `str`,
but for metadata keys ending with the suffix `-bin`, the corresponding values must
be of type `bytes`.
Returns:
~.trace.Trace:
A trace describes how long it takes
for an application to perform an
operation. It consists of a set of
spans, each of which represent a single
timed event within the operation.
"""
http_options = (
_BaseTraceServiceRestTransport._BaseGetTrace._get_http_options()
)
request, metadata = self._interceptor.pre_get_trace(request, metadata)
transcoded_request = (
_BaseTraceServiceRestTransport._BaseGetTrace._get_transcoded_request(
http_options, request
)
)
# Jsonify the query params
query_params = (
_BaseTraceServiceRestTransport._BaseGetTrace._get_query_params_json(
transcoded_request
)
)
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
logging.DEBUG
): # pragma: NO COVER
request_url = "{host}{uri}".format(
host=self._host, uri=transcoded_request["uri"]
)
method = transcoded_request["method"]
try:
request_payload = type(request).to_json(request)
except:
request_payload = None
http_request = {
"payload": request_payload,
"requestMethod": method,
"requestUrl": request_url,
"headers": dict(metadata),
}
_LOGGER.debug(
f"Sending request for google.devtools.cloudtrace_v1.TraceServiceClient.GetTrace",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"rpcName": "GetTrace",
"httpRequest": http_request,
"metadata": http_request["headers"],
},
)
# Send the request
response = TraceServiceRestTransport._GetTrace._get_response(
self._host,
metadata,
query_params,
self._session,
timeout,
transcoded_request,
)
# In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
# subclass.
if response.status_code >= 400:
raise core_exceptions.from_http_response(response)
# Return the response
resp = trace.Trace()
pb_resp = trace.Trace.pb(resp)
json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
resp = self._interceptor.post_get_trace(resp)
response_metadata = [(k, str(v)) for k, v in response.headers.items()]
resp, _ = self._interceptor.post_get_trace_with_metadata(
resp, response_metadata
)
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
logging.DEBUG
): # pragma: NO COVER
try:
response_payload = trace.Trace.to_json(response)
except:
response_payload = None
http_response = {
"payload": response_payload,
"headers": dict(response.headers),
"status": response.status_code,
}
_LOGGER.debug(
"Received response for google.devtools.cloudtrace_v1.TraceServiceClient.get_trace",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"rpcName": "GetTrace",
"metadata": http_response["headers"],
"httpResponse": http_response,
},
)
return resp
class _ListTraces(
_BaseTraceServiceRestTransport._BaseListTraces, TraceServiceRestStub
):
def __hash__(self):
return hash("TraceServiceRestTransport.ListTraces")
@staticmethod
def _get_response(
host,
metadata,
query_params,
session,
timeout,
transcoded_request,
body=None,
):
uri = transcoded_request["uri"]
method = transcoded_request["method"]
headers = dict(metadata)
headers["Content-Type"] = "application/json"
response = getattr(session, method)(
"{host}{uri}".format(host=host, uri=uri),
timeout=timeout,
headers=headers,
params=rest_helpers.flatten_query_params(query_params, strict=True),
)
return response
def __call__(
self,
request: trace.ListTracesRequest,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Optional[float] = None,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> trace.ListTracesResponse:
r"""Call the list traces method over HTTP.
Args:
request (~.trace.ListTracesRequest):
The request object. The request message for the ``ListTraces`` method. All
fields are required unless specified.
retry (google.api_core.retry.Retry): Designation of what errors, if any,
should be retried.
timeout (float): The timeout for this request.
metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
sent along with the request as metadata. Normally, each value must be of type `str`,
but for metadata keys ending with the suffix `-bin`, the corresponding values must
be of type `bytes`.
Returns:
~.trace.ListTracesResponse:
The response message for the ``ListTraces`` method.
"""
http_options = (
_BaseTraceServiceRestTransport._BaseListTraces._get_http_options()
)
request, metadata = self._interceptor.pre_list_traces(request, metadata)
transcoded_request = (
_BaseTraceServiceRestTransport._BaseListTraces._get_transcoded_request(
http_options, request
)
)
# Jsonify the query params
query_params = (
_BaseTraceServiceRestTransport._BaseListTraces._get_query_params_json(
transcoded_request
)
)
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
logging.DEBUG
): # pragma: NO COVER
request_url = "{host}{uri}".format(
host=self._host, uri=transcoded_request["uri"]
)
method = transcoded_request["method"]
try:
request_payload = type(request).to_json(request)
except:
request_payload = None
http_request = {
"payload": request_payload,
"requestMethod": method,
"requestUrl": request_url,
"headers": dict(metadata),
}
_LOGGER.debug(
f"Sending request for google.devtools.cloudtrace_v1.TraceServiceClient.ListTraces",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"rpcName": "ListTraces",
"httpRequest": http_request,
"metadata": http_request["headers"],
},
)
# Send the request
response = TraceServiceRestTransport._ListTraces._get_response(
self._host,
metadata,
query_params,
self._session,
timeout,
transcoded_request,
)
# In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
# subclass.
if response.status_code >= 400:
raise core_exceptions.from_http_response(response)
# Return the response
resp = trace.ListTracesResponse()
pb_resp = trace.ListTracesResponse.pb(resp)
json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
resp = self._interceptor.post_list_traces(resp)
response_metadata = [(k, str(v)) for k, v in response.headers.items()]
resp, _ = self._interceptor.post_list_traces_with_metadata(
resp, response_metadata
)
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
logging.DEBUG
): # pragma: NO COVER
try:
response_payload = trace.ListTracesResponse.to_json(response)
except:
response_payload = None
http_response = {
"payload": response_payload,
"headers": dict(response.headers),
"status": response.status_code,
}
_LOGGER.debug(
"Received response for google.devtools.cloudtrace_v1.TraceServiceClient.list_traces",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"rpcName": "ListTraces",
"metadata": http_response["headers"],
"httpResponse": http_response,
},
)
return resp
class _PatchTraces(
_BaseTraceServiceRestTransport._BasePatchTraces, TraceServiceRestStub
):
def __hash__(self):
return hash("TraceServiceRestTransport.PatchTraces")
@staticmethod
def _get_response(
host,
metadata,
query_params,
session,
timeout,
transcoded_request,
body=None,
):
uri = transcoded_request["uri"]
method = transcoded_request["method"]
headers = dict(metadata)
headers["Content-Type"] = "application/json"
response = getattr(session, method)(
"{host}{uri}".format(host=host, uri=uri),
timeout=timeout,
headers=headers,
params=rest_helpers.flatten_query_params(query_params, strict=True),
data=body,
)
return response
def __call__(
self,
request: trace.PatchTracesRequest,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Optional[float] = None,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
):
r"""Call the patch traces method over HTTP.
Args:
request (~.trace.PatchTracesRequest):
The request object. The request message for the ``PatchTraces`` method.
retry (google.api_core.retry.Retry): Designation of what errors, if any,
should be retried.
timeout (float): The timeout for this request.
metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
sent along with the request as metadata. Normally, each value must be of type `str`,
but for metadata keys ending with the suffix `-bin`, the corresponding values must
be of type `bytes`.
"""
http_options = (
_BaseTraceServiceRestTransport._BasePatchTraces._get_http_options()
)
request, metadata = self._interceptor.pre_patch_traces(request, metadata)
transcoded_request = (
_BaseTraceServiceRestTransport._BasePatchTraces._get_transcoded_request(
http_options, request
)
)
body = (
_BaseTraceServiceRestTransport._BasePatchTraces._get_request_body_json(
transcoded_request
)
)
# Jsonify the query params
query_params = (
_BaseTraceServiceRestTransport._BasePatchTraces._get_query_params_json(
transcoded_request
)
)
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
logging.DEBUG
): # pragma: NO COVER
request_url = "{host}{uri}".format(
host=self._host, uri=transcoded_request["uri"]
)
method = transcoded_request["method"]
try:
request_payload = json_format.MessageToJson(request)
except:
request_payload = None
http_request = {
"payload": request_payload,
"requestMethod": method,
"requestUrl": request_url,
"headers": dict(metadata),
}
_LOGGER.debug(
f"Sending request for google.devtools.cloudtrace_v1.TraceServiceClient.PatchTraces",
extra={
"serviceName": "google.devtools.cloudtrace.v1.TraceService",
"rpcName": "PatchTraces",
"httpRequest": http_request,
"metadata": http_request["headers"],
},
)
# Send the request
response = TraceServiceRestTransport._PatchTraces._get_response(
self._host,
metadata,
query_params,
self._session,
timeout,
transcoded_request,
body,
)
# In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
# subclass.
if response.status_code >= 400:
raise core_exceptions.from_http_response(response)
@property
def get_trace(self) -> Callable[[trace.GetTraceRequest], trace.Trace]:
# The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
# In C++ this would require a dynamic_cast
return self._GetTrace(self._session, self._host, self._interceptor) # type: ignore
@property
def list_traces(
self,
) -> Callable[[trace.ListTracesRequest], trace.ListTracesResponse]:
# The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
# In C++ this would require a dynamic_cast
return self._ListTraces(self._session, self._host, self._interceptor) # type: ignore
@property
def patch_traces(self) -> Callable[[trace.PatchTracesRequest], empty_pb2.Empty]:
# The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
# In C++ this would require a dynamic_cast
return self._PatchTraces(self._session, self._host, self._interceptor) # type: ignore
@property
def kind(self) -> str:
return "rest"
def close(self):
self._session.close()
__all__ = ("TraceServiceRestTransport",)

View File

@@ -0,0 +1,243 @@
# -*- coding: utf-8 -*-
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json # type: ignore
import re
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
from google.api_core import gapic_v1, path_template
from google.protobuf import empty_pb2 # type: ignore
from google.protobuf import json_format
from google.cloud.trace_v1.types import trace
from .base import DEFAULT_CLIENT_INFO, TraceServiceTransport
class _BaseTraceServiceRestTransport(TraceServiceTransport):
"""Base REST backend transport for TraceService.
Note: This class is not meant to be used directly. Use its sync and
async sub-classes instead.
This class defines the same methods as the primary client, so the
primary client can load the underlying transport implementation
and call it.
It sends JSON representations of protocol buffers over HTTP/1.1
"""
def __init__(
self,
*,
host: str = "cloudtrace.googleapis.com",
credentials: Optional[Any] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
always_use_jwt_access: Optional[bool] = False,
url_scheme: str = "https",
api_audience: Optional[str] = None,
) -> None:
"""Instantiate the transport.
Args:
host (Optional[str]):
The hostname to connect to (default: 'cloudtrace.googleapis.com').
credentials (Optional[Any]): The
authorization credentials to attach to requests. These
credentials identify the application to the service; if none
are specified, the client will attempt to ascertain the
credentials from the environment.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
The client info used to send a user-agent string along with
API requests. If ``None``, then default info will be used.
Generally, you only need to set this if you are developing
your own client library.
always_use_jwt_access (Optional[bool]): Whether self signed JWT should
be used for service account credentials.
url_scheme: the protocol scheme for the API endpoint. Normally
"https", but for testing or local servers,
"http" can be specified.
"""
# Run the base constructor
maybe_url_match = re.match("^(?P<scheme>http(?:s)?://)?(?P<host>.*)$", host)
if maybe_url_match is None:
raise ValueError(
f"Unexpected hostname structure: {host}"
) # pragma: NO COVER
url_match_items = maybe_url_match.groupdict()
host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host
super().__init__(
host=host,
credentials=credentials,
client_info=client_info,
always_use_jwt_access=always_use_jwt_access,
api_audience=api_audience,
)
class _BaseGetTrace:
def __hash__(self): # pragma: NO COVER
return NotImplementedError("__hash__ must be implemented.")
__REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
@classmethod
def _get_unset_required_fields(cls, message_dict):
return {
k: v
for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
if k not in message_dict
}
@staticmethod
def _get_http_options():
http_options: List[Dict[str, str]] = [
{
"method": "get",
"uri": "/v1/projects/{project_id}/traces/{trace_id}",
},
]
return http_options
@staticmethod
def _get_transcoded_request(http_options, request):
pb_request = trace.GetTraceRequest.pb(request)
transcoded_request = path_template.transcode(http_options, pb_request)
return transcoded_request
@staticmethod
def _get_query_params_json(transcoded_request):
query_params = json.loads(
json_format.MessageToJson(
transcoded_request["query_params"],
use_integers_for_enums=True,
)
)
query_params.update(
_BaseTraceServiceRestTransport._BaseGetTrace._get_unset_required_fields(
query_params
)
)
query_params["$alt"] = "json;enum-encoding=int"
return query_params
class _BaseListTraces:
def __hash__(self): # pragma: NO COVER
return NotImplementedError("__hash__ must be implemented.")
__REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
@classmethod
def _get_unset_required_fields(cls, message_dict):
return {
k: v
for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
if k not in message_dict
}
@staticmethod
def _get_http_options():
http_options: List[Dict[str, str]] = [
{
"method": "get",
"uri": "/v1/projects/{project_id}/traces",
},
]
return http_options
@staticmethod
def _get_transcoded_request(http_options, request):
pb_request = trace.ListTracesRequest.pb(request)
transcoded_request = path_template.transcode(http_options, pb_request)
return transcoded_request
@staticmethod
def _get_query_params_json(transcoded_request):
query_params = json.loads(
json_format.MessageToJson(
transcoded_request["query_params"],
use_integers_for_enums=True,
)
)
query_params.update(
_BaseTraceServiceRestTransport._BaseListTraces._get_unset_required_fields(
query_params
)
)
query_params["$alt"] = "json;enum-encoding=int"
return query_params
class _BasePatchTraces:
def __hash__(self): # pragma: NO COVER
return NotImplementedError("__hash__ must be implemented.")
__REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
@classmethod
def _get_unset_required_fields(cls, message_dict):
return {
k: v
for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
if k not in message_dict
}
@staticmethod
def _get_http_options():
http_options: List[Dict[str, str]] = [
{
"method": "patch",
"uri": "/v1/projects/{project_id}/traces",
"body": "traces",
},
]
return http_options
@staticmethod
def _get_transcoded_request(http_options, request):
pb_request = trace.PatchTracesRequest.pb(request)
transcoded_request = path_template.transcode(http_options, pb_request)
return transcoded_request
@staticmethod
def _get_request_body_json(transcoded_request):
# Jsonify the request body
body = json_format.MessageToJson(
transcoded_request["body"], use_integers_for_enums=True
)
return body
@staticmethod
def _get_query_params_json(transcoded_request):
query_params = json.loads(
json_format.MessageToJson(
transcoded_request["query_params"],
use_integers_for_enums=True,
)
)
query_params.update(
_BaseTraceServiceRestTransport._BasePatchTraces._get_unset_required_fields(
query_params
)
)
query_params["$alt"] = "json;enum-encoding=int"
return query_params
__all__ = ("_BaseTraceServiceRestTransport",)