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,34 @@
# -*- 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 google.cloud.trace_v2 import gapic_version as package_version
__version__ = package_version.__version__
from .services.trace_service import TraceServiceAsyncClient, TraceServiceClient
from .types.trace import AttributeValue, Module, Span, StackTrace, TruncatableString
from .types.tracing import BatchWriteSpansRequest
__all__ = (
"TraceServiceAsyncClient",
"AttributeValue",
"BatchWriteSpansRequest",
"Module",
"Span",
"StackTrace",
"TraceServiceClient",
"TruncatableString",
)

View File

@@ -0,0 +1,58 @@
{
"comment": "This file maps proto services/RPCs to the corresponding library clients/methods",
"language": "python",
"libraryPackage": "google.cloud.trace_v2",
"protoPackage": "google.devtools.cloudtrace.v2",
"schema": "1.0",
"services": {
"TraceService": {
"clients": {
"grpc": {
"libraryClient": "TraceServiceClient",
"rpcs": {
"BatchWriteSpans": {
"methods": [
"batch_write_spans"
]
},
"CreateSpan": {
"methods": [
"create_span"
]
}
}
},
"grpc-async": {
"libraryClient": "TraceServiceAsyncClient",
"rpcs": {
"BatchWriteSpans": {
"methods": [
"batch_write_spans"
]
},
"CreateSpan": {
"methods": [
"create_span"
]
}
}
},
"rest": {
"libraryClient": "TraceServiceClient",
"rpcs": {
"BatchWriteSpans": {
"methods": [
"batch_write_spans"
]
},
"CreateSpan": {
"methods": [
"create_span"
]
}
}
}
}
}
}
}

View File

@@ -0,0 +1,16 @@
# -*- 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.
#
__version__ = "1.16.1" # {x-release-please-version}

View File

@@ -0,0 +1,2 @@
# Marker file for PEP 561.
# The google-cloud-trace package uses inline types.

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,529 @@
# -*- 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_v2 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.protobuf import timestamp_pb2 # type: ignore
from google.protobuf import wrappers_pb2 # type: ignore
from google.rpc import status_pb2 # type: ignore
from google.cloud.trace_v2.types import trace, tracing
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:
"""Service for collecting and viewing traces and spans within a
trace.
A trace is a collection of spans corresponding to a single
operation or a set of operations in an application.
A span is an individual timed event which forms a node of the
trace tree. A single trace can contain spans from 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
span_path = staticmethod(TraceServiceClient.span_path)
parse_span_path = staticmethod(TraceServiceClient.parse_span_path)
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_v2.TraceServiceAsyncClient`.",
extra={
"serviceName": "google.devtools.cloudtrace.v2.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.v2.TraceService",
"credentialsType": None,
},
)
async def batch_write_spans(
self,
request: Optional[Union[tracing.BatchWriteSpansRequest, dict]] = None,
*,
name: Optional[str] = None,
spans: Optional[MutableSequence[trace.Span]] = None,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> None:
r"""Batch writes new spans to new or existing traces. You
cannot update existing spans.
.. 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_v2
async def sample_batch_write_spans():
# Create a client
client = trace_v2.TraceServiceAsyncClient()
# Initialize request argument(s)
spans = trace_v2.Span()
spans.name = "name_value"
spans.span_id = "span_id_value"
request = trace_v2.BatchWriteSpansRequest(
name="name_value",
spans=spans,
)
# Make the request
await client.batch_write_spans(request=request)
Args:
request (Optional[Union[google.cloud.trace_v2.types.BatchWriteSpansRequest, dict]]):
The request object. The request message for the ``BatchWriteSpans`` method.
name (:class:`str`):
Required. The name of the project where the spans
belong. The format is ``projects/[PROJECT_ID]``.
This corresponds to the ``name`` field
on the ``request`` instance; if ``request`` is provided, this
should not be set.
spans (:class:`MutableSequence[google.cloud.trace_v2.types.Span]`):
Required. A list of new spans. The
span names must not match existing
spans, otherwise the results are
undefined.
This corresponds to the ``spans`` 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 = [name, spans]
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, tracing.BatchWriteSpansRequest):
request = tracing.BatchWriteSpansRequest(request)
# If we have keyword arguments corresponding to fields on the
# request, apply these.
if name is not None:
request.name = name
if spans:
request.spans.extend(spans)
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
rpc = self._client._transport._wrapped_methods[
self._client._transport.batch_write_spans
]
# Certain fields should be provided within the metadata header;
# add these here.
metadata = tuple(metadata) + (
gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
)
# Validate the universe domain.
self._client._validate_universe_domain()
# Send the request.
await rpc(
request,
retry=retry,
timeout=timeout,
metadata=metadata,
)
async def create_span(
self,
request: Optional[Union[trace.Span, dict]] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> trace.Span:
r"""Creates a new span.
.. 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_v2
async def sample_create_span():
# Create a client
client = trace_v2.TraceServiceAsyncClient()
# Initialize request argument(s)
request = trace_v2.Span(
name="name_value",
span_id="span_id_value",
)
# Make the request
response = await client.create_span(request=request)
# Handle the response
print(response)
Args:
request (Optional[Union[google.cloud.trace_v2.types.Span, dict]]):
The request object. A span represents a single operation
within a trace. Spans can be nested to
form a trace tree. Often, a trace
contains a root span that describes the
end-to-end latency, and one or more
subspans for its sub-operations.
A trace can also contain multiple root
spans, or none at all. Spans do not need
to be contiguous. There might be gaps or
overlaps between spans in a trace.
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_v2.types.Span:
A span represents a single operation
within a trace. Spans can be nested to
form a trace tree. Often, a trace
contains a root span that describes the
end-to-end latency, and one or more
subspans for its sub-operations.
A trace can also contain multiple root
spans, or none at all. Spans do not need
to be contiguous. There might be gaps or
overlaps between spans in a trace.
"""
# Create or coerce a protobuf request object.
# - 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.Span):
request = trace.Span(request)
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
rpc = self._client._transport._wrapped_methods[
self._client._transport.create_span
]
# Certain fields should be provided within the metadata header;
# add these here.
metadata = tuple(metadata) + (
gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
)
# 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 __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,953 @@
# -*- 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 http import HTTPStatus
import json
import logging as std_logging
import os
import re
from typing import (
Callable,
Dict,
Mapping,
MutableMapping,
MutableSequence,
Optional,
Sequence,
Tuple,
Type,
Union,
cast,
)
import warnings
from google.api_core import client_options as client_options_lib
from google.api_core import exceptions as core_exceptions
from google.api_core import gapic_v1
from google.api_core import retry as retries
from google.auth import credentials as ga_credentials # type: ignore
from google.auth.exceptions import MutualTLSChannelError # type: ignore
from google.auth.transport import mtls # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore
from google.oauth2 import service_account # type: ignore
from google.cloud.trace_v2 import gapic_version as package_version
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 = std_logging.getLogger(__name__)
from google.protobuf import timestamp_pb2 # type: ignore
from google.protobuf import wrappers_pb2 # type: ignore
from google.rpc import status_pb2 # type: ignore
from google.cloud.trace_v2.types import trace, tracing
from .transports.base import DEFAULT_CLIENT_INFO, TraceServiceTransport
from .transports.grpc import TraceServiceGrpcTransport
from .transports.grpc_asyncio import TraceServiceGrpcAsyncIOTransport
from .transports.rest import TraceServiceRestTransport
class TraceServiceClientMeta(type):
"""Metaclass for the TraceService client.
This provides class-level methods for building and retrieving
support objects (e.g. transport) without polluting the client instance
objects.
"""
_transport_registry = OrderedDict() # type: Dict[str, Type[TraceServiceTransport]]
_transport_registry["grpc"] = TraceServiceGrpcTransport
_transport_registry["grpc_asyncio"] = TraceServiceGrpcAsyncIOTransport
_transport_registry["rest"] = TraceServiceRestTransport
def get_transport_class(
cls,
label: Optional[str] = None,
) -> Type[TraceServiceTransport]:
"""Returns an appropriate transport class.
Args:
label: The name of the desired transport. If none is
provided, then the first transport in the registry is used.
Returns:
The transport class to use.
"""
# If a specific transport is requested, return that one.
if label:
return cls._transport_registry[label]
# No transport is requested; return the default (that is, the first one
# in the dictionary).
return next(iter(cls._transport_registry.values()))
class TraceServiceClient(metaclass=TraceServiceClientMeta):
"""Service for collecting and viewing traces and spans within a
trace.
A trace is a collection of spans corresponding to a single
operation or a set of operations in an application.
A span is an individual timed event which forms a node of the
trace tree. A single trace can contain spans from multiple
services.
"""
@staticmethod
def _get_default_mtls_endpoint(api_endpoint):
"""Converts api endpoint to mTLS endpoint.
Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
"*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
Args:
api_endpoint (Optional[str]): the api endpoint to convert.
Returns:
str: converted mTLS api endpoint.
"""
if not api_endpoint:
return api_endpoint
mtls_endpoint_re = re.compile(
r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
)
m = mtls_endpoint_re.match(api_endpoint)
name, mtls, sandbox, googledomain = m.groups()
if mtls or not googledomain:
return api_endpoint
if sandbox:
return api_endpoint.replace(
"sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
)
return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")
# Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead.
DEFAULT_ENDPOINT = "cloudtrace.googleapis.com"
DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore
DEFAULT_ENDPOINT
)
_DEFAULT_ENDPOINT_TEMPLATE = "cloudtrace.{UNIVERSE_DOMAIN}"
_DEFAULT_UNIVERSE = "googleapis.com"
@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:
TraceServiceClient: The constructed client.
"""
credentials = service_account.Credentials.from_service_account_info(info)
kwargs["credentials"] = credentials
return cls(*args, **kwargs)
@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:
TraceServiceClient: The constructed client.
"""
credentials = service_account.Credentials.from_service_account_file(filename)
kwargs["credentials"] = credentials
return cls(*args, **kwargs)
from_service_account_json = from_service_account_file
@property
def transport(self) -> TraceServiceTransport:
"""Returns the transport used by the client instance.
Returns:
TraceServiceTransport: The transport used by the client
instance.
"""
return self._transport
@staticmethod
def span_path(
project: str,
trace: str,
span: str,
) -> str:
"""Returns a fully-qualified span string."""
return "projects/{project}/traces/{trace}/spans/{span}".format(
project=project,
trace=trace,
span=span,
)
@staticmethod
def parse_span_path(path: str) -> Dict[str, str]:
"""Parses a span path into its component segments."""
m = re.match(
r"^projects/(?P<project>.+?)/traces/(?P<trace>.+?)/spans/(?P<span>.+?)$",
path,
)
return m.groupdict() if m else {}
@staticmethod
def common_billing_account_path(
billing_account: str,
) -> str:
"""Returns a fully-qualified billing_account string."""
return "billingAccounts/{billing_account}".format(
billing_account=billing_account,
)
@staticmethod
def parse_common_billing_account_path(path: str) -> Dict[str, str]:
"""Parse a billing_account path into its component segments."""
m = re.match(r"^billingAccounts/(?P<billing_account>.+?)$", path)
return m.groupdict() if m else {}
@staticmethod
def common_folder_path(
folder: str,
) -> str:
"""Returns a fully-qualified folder string."""
return "folders/{folder}".format(
folder=folder,
)
@staticmethod
def parse_common_folder_path(path: str) -> Dict[str, str]:
"""Parse a folder path into its component segments."""
m = re.match(r"^folders/(?P<folder>.+?)$", path)
return m.groupdict() if m else {}
@staticmethod
def common_organization_path(
organization: str,
) -> str:
"""Returns a fully-qualified organization string."""
return "organizations/{organization}".format(
organization=organization,
)
@staticmethod
def parse_common_organization_path(path: str) -> Dict[str, str]:
"""Parse a organization path into its component segments."""
m = re.match(r"^organizations/(?P<organization>.+?)$", path)
return m.groupdict() if m else {}
@staticmethod
def common_project_path(
project: str,
) -> str:
"""Returns a fully-qualified project string."""
return "projects/{project}".format(
project=project,
)
@staticmethod
def parse_common_project_path(path: str) -> Dict[str, str]:
"""Parse a project path into its component segments."""
m = re.match(r"^projects/(?P<project>.+?)$", path)
return m.groupdict() if m else {}
@staticmethod
def common_location_path(
project: str,
location: str,
) -> str:
"""Returns a fully-qualified location string."""
return "projects/{project}/locations/{location}".format(
project=project,
location=location,
)
@staticmethod
def parse_common_location_path(path: str) -> Dict[str, str]:
"""Parse a location path into its component segments."""
m = re.match(r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)$", path)
return m.groupdict() if m else {}
@classmethod
def get_mtls_endpoint_and_cert_source(
cls, client_options: Optional[client_options_lib.ClientOptions] = None
):
"""Deprecated. 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.
"""
warnings.warn(
"get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.",
DeprecationWarning,
)
if client_options is None:
client_options = client_options_lib.ClientOptions()
use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
if use_client_cert not in ("true", "false"):
raise ValueError(
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
)
if use_mtls_endpoint not in ("auto", "never", "always"):
raise MutualTLSChannelError(
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
)
# Figure out the client cert source to use.
client_cert_source = None
if use_client_cert == "true":
if client_options.client_cert_source:
client_cert_source = client_options.client_cert_source
elif mtls.has_default_client_cert_source():
client_cert_source = mtls.default_client_cert_source()
# Figure out which api endpoint to use.
if client_options.api_endpoint is not None:
api_endpoint = client_options.api_endpoint
elif use_mtls_endpoint == "always" or (
use_mtls_endpoint == "auto" and client_cert_source
):
api_endpoint = cls.DEFAULT_MTLS_ENDPOINT
else:
api_endpoint = cls.DEFAULT_ENDPOINT
return api_endpoint, client_cert_source
@staticmethod
def _read_environment_variables():
"""Returns the environment variables used by the client.
Returns:
Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE,
GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables.
Raises:
ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not
any of ["true", "false"].
google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
is not any of ["auto", "never", "always"].
"""
use_client_cert = os.getenv(
"GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
).lower()
use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
if use_client_cert not in ("true", "false"):
raise ValueError(
"Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
)
if use_mtls_endpoint not in ("auto", "never", "always"):
raise MutualTLSChannelError(
"Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
)
return use_client_cert == "true", use_mtls_endpoint, universe_domain_env
@staticmethod
def _get_client_cert_source(provided_cert_source, use_cert_flag):
"""Return the client cert source to be used by the client.
Args:
provided_cert_source (bytes): The client certificate source provided.
use_cert_flag (bool): A flag indicating whether to use the client certificate.
Returns:
bytes or None: The client cert source to be used by the client.
"""
client_cert_source = None
if use_cert_flag:
if provided_cert_source:
client_cert_source = provided_cert_source
elif mtls.has_default_client_cert_source():
client_cert_source = mtls.default_client_cert_source()
return client_cert_source
@staticmethod
def _get_api_endpoint(
api_override, client_cert_source, universe_domain, use_mtls_endpoint
):
"""Return the API endpoint used by the client.
Args:
api_override (str): The API endpoint override. If specified, this is always
the return value of this function and the other arguments are not used.
client_cert_source (bytes): The client certificate source used by the client.
universe_domain (str): The universe domain used by the client.
use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters.
Possible values are "always", "auto", or "never".
Returns:
str: The API endpoint to be used by the client.
"""
if api_override is not None:
api_endpoint = api_override
elif use_mtls_endpoint == "always" or (
use_mtls_endpoint == "auto" and client_cert_source
):
_default_universe = TraceServiceClient._DEFAULT_UNIVERSE
if universe_domain != _default_universe:
raise MutualTLSChannelError(
f"mTLS is not supported in any universe other than {_default_universe}."
)
api_endpoint = TraceServiceClient.DEFAULT_MTLS_ENDPOINT
else:
api_endpoint = TraceServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format(
UNIVERSE_DOMAIN=universe_domain
)
return api_endpoint
@staticmethod
def _get_universe_domain(
client_universe_domain: Optional[str], universe_domain_env: Optional[str]
) -> str:
"""Return the universe domain used by the client.
Args:
client_universe_domain (Optional[str]): The universe domain configured via the client options.
universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable.
Returns:
str: The universe domain to be used by the client.
Raises:
ValueError: If the universe domain is an empty string.
"""
universe_domain = TraceServiceClient._DEFAULT_UNIVERSE
if client_universe_domain is not None:
universe_domain = client_universe_domain
elif universe_domain_env is not None:
universe_domain = universe_domain_env
if len(universe_domain.strip()) == 0:
raise ValueError("Universe Domain cannot be an empty string.")
return universe_domain
def _validate_universe_domain(self):
"""Validates client's and credentials' universe domains are consistent.
Returns:
bool: True iff the configured universe domain is valid.
Raises:
ValueError: If the configured universe domain is not valid.
"""
# NOTE (b/349488459): universe validation is disabled until further notice.
return True
def _add_cred_info_for_auth_errors(
self, error: core_exceptions.GoogleAPICallError
) -> None:
"""Adds credential info string to error details for 401/403/404 errors.
Args:
error (google.api_core.exceptions.GoogleAPICallError): The error to add the cred info.
"""
if error.code not in [
HTTPStatus.UNAUTHORIZED,
HTTPStatus.FORBIDDEN,
HTTPStatus.NOT_FOUND,
]:
return
cred = self._transport._credentials
# get_cred_info is only available in google-auth>=2.35.0
if not hasattr(cred, "get_cred_info"):
return
# ignore the type check since pypy test fails when get_cred_info
# is not available
cred_info = cred.get_cred_info() # type: ignore
if cred_info and hasattr(error._details, "append"):
error._details.append(json.dumps(cred_info))
@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._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._universe_domain
def __init__(
self,
*,
credentials: Optional[ga_credentials.Credentials] = None,
transport: Optional[
Union[str, TraceServiceTransport, Callable[..., TraceServiceTransport]]
] = None,
client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
) -> None:
"""Instantiates the trace service 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.
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 the ``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_options = client_options
if isinstance(self._client_options, dict):
self._client_options = client_options_lib.from_dict(self._client_options)
if self._client_options is None:
self._client_options = client_options_lib.ClientOptions()
self._client_options = cast(
client_options_lib.ClientOptions, self._client_options
)
universe_domain_opt = getattr(self._client_options, "universe_domain", None)
(
self._use_client_cert,
self._use_mtls_endpoint,
self._universe_domain_env,
) = TraceServiceClient._read_environment_variables()
self._client_cert_source = TraceServiceClient._get_client_cert_source(
self._client_options.client_cert_source, self._use_client_cert
)
self._universe_domain = TraceServiceClient._get_universe_domain(
universe_domain_opt, self._universe_domain_env
)
self._api_endpoint = None # updated below, depending on `transport`
# Initialize the universe domain validation.
self._is_universe_domain_valid = False
if CLIENT_LOGGING_SUPPORTED: # pragma: NO COVER
# Setup logging.
client_logging.initialize_logging()
api_key_value = getattr(self._client_options, "api_key", None)
if api_key_value and credentials:
raise ValueError(
"client_options.api_key and credentials are mutually exclusive"
)
# Save or instantiate the transport.
# Ordinarily, we provide the transport, but allowing a custom transport
# instance provides an extensibility point for unusual situations.
transport_provided = isinstance(transport, TraceServiceTransport)
if transport_provided:
# transport is a TraceServiceTransport instance.
if credentials or self._client_options.credentials_file or api_key_value:
raise ValueError(
"When providing a transport instance, "
"provide its credentials directly."
)
if self._client_options.scopes:
raise ValueError(
"When providing a transport instance, provide its scopes "
"directly."
)
self._transport = cast(TraceServiceTransport, transport)
self._api_endpoint = self._transport.host
self._api_endpoint = self._api_endpoint or TraceServiceClient._get_api_endpoint(
self._client_options.api_endpoint,
self._client_cert_source,
self._universe_domain,
self._use_mtls_endpoint,
)
if not transport_provided:
import google.auth._default # type: ignore
if api_key_value and hasattr(
google.auth._default, "get_api_key_credentials"
):
credentials = google.auth._default.get_api_key_credentials(
api_key_value
)
transport_init: Union[
Type[TraceServiceTransport], Callable[..., TraceServiceTransport]
] = (
TraceServiceClient.get_transport_class(transport)
if isinstance(transport, str) or transport is None
else cast(Callable[..., TraceServiceTransport], transport)
)
# initialize with the provided callable or the passed in class
self._transport = transport_init(
credentials=credentials,
credentials_file=self._client_options.credentials_file,
host=self._api_endpoint,
scopes=self._client_options.scopes,
client_cert_source_for_mtls=self._client_cert_source,
quota_project_id=self._client_options.quota_project_id,
client_info=client_info,
always_use_jwt_access=True,
api_audience=self._client_options.api_audience,
)
if "async" not in str(self._transport):
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
std_logging.DEBUG
): # pragma: NO COVER
_LOGGER.debug(
"Created client `google.devtools.cloudtrace_v2.TraceServiceClient`.",
extra={
"serviceName": "google.devtools.cloudtrace.v2.TraceService",
"universeDomain": getattr(
self._transport._credentials, "universe_domain", ""
),
"credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}",
"credentialsInfo": getattr(
self.transport._credentials, "get_cred_info", lambda: None
)(),
}
if hasattr(self._transport, "_credentials")
else {
"serviceName": "google.devtools.cloudtrace.v2.TraceService",
"credentialsType": None,
},
)
def batch_write_spans(
self,
request: Optional[Union[tracing.BatchWriteSpansRequest, dict]] = None,
*,
name: Optional[str] = None,
spans: Optional[MutableSequence[trace.Span]] = None,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> None:
r"""Batch writes new spans to new or existing traces. You
cannot update existing spans.
.. 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_v2
def sample_batch_write_spans():
# Create a client
client = trace_v2.TraceServiceClient()
# Initialize request argument(s)
spans = trace_v2.Span()
spans.name = "name_value"
spans.span_id = "span_id_value"
request = trace_v2.BatchWriteSpansRequest(
name="name_value",
spans=spans,
)
# Make the request
client.batch_write_spans(request=request)
Args:
request (Union[google.cloud.trace_v2.types.BatchWriteSpansRequest, dict]):
The request object. The request message for the ``BatchWriteSpans`` method.
name (str):
Required. The name of the project where the spans
belong. The format is ``projects/[PROJECT_ID]``.
This corresponds to the ``name`` field
on the ``request`` instance; if ``request`` is provided, this
should not be set.
spans (MutableSequence[google.cloud.trace_v2.types.Span]):
Required. A list of new spans. The
span names must not match existing
spans, otherwise the results are
undefined.
This corresponds to the ``spans`` field
on the ``request`` instance; if ``request`` is provided, this
should not be set.
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`.
"""
# 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 = [name, spans]
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, tracing.BatchWriteSpansRequest):
request = tracing.BatchWriteSpansRequest(request)
# If we have keyword arguments corresponding to fields on the
# request, apply these.
if name is not None:
request.name = name
if spans is not None:
request.spans = spans
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
rpc = self._transport._wrapped_methods[self._transport.batch_write_spans]
# Certain fields should be provided within the metadata header;
# add these here.
metadata = tuple(metadata) + (
gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
)
# Validate the universe domain.
self._validate_universe_domain()
# Send the request.
rpc(
request,
retry=retry,
timeout=timeout,
metadata=metadata,
)
def create_span(
self,
request: Optional[Union[trace.Span, dict]] = None,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> trace.Span:
r"""Creates a new span.
.. 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_v2
def sample_create_span():
# Create a client
client = trace_v2.TraceServiceClient()
# Initialize request argument(s)
request = trace_v2.Span(
name="name_value",
span_id="span_id_value",
)
# Make the request
response = client.create_span(request=request)
# Handle the response
print(response)
Args:
request (Union[google.cloud.trace_v2.types.Span, dict]):
The request object. A span represents a single operation
within a trace. Spans can be nested to
form a trace tree. Often, a trace
contains a root span that describes the
end-to-end latency, and one or more
subspans for its sub-operations.
A trace can also contain multiple root
spans, or none at all. Spans do not need
to be contiguous. There might be gaps or
overlaps between spans in a trace.
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:
google.cloud.trace_v2.types.Span:
A span represents a single operation
within a trace. Spans can be nested to
form a trace tree. Often, a trace
contains a root span that describes the
end-to-end latency, and one or more
subspans for its sub-operations.
A trace can also contain multiple root
spans, or none at all. Spans do not need
to be contiguous. There might be gaps or
overlaps between spans in a trace.
"""
# Create or coerce a protobuf request object.
# - 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.Span):
request = trace.Span(request)
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
rpc = self._transport._wrapped_methods[self._transport.create_span]
# Certain fields should be provided within the metadata header;
# add these here.
metadata = tuple(metadata) + (
gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
)
# Validate the universe domain.
self._validate_universe_domain()
# Send the request.
response = rpc(
request,
retry=retry,
timeout=timeout,
metadata=metadata,
)
# Done; return the response.
return response
def __enter__(self) -> "TraceServiceClient":
return self
def __exit__(self, type, value, traceback):
"""Releases underlying transport's resources.
.. warning::
ONLY use as a context manager if the transport is NOT shared
with other clients! Exiting the with block will CLOSE the transport
and may cause errors in other clients!
"""
self.transport.close()
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
gapic_version=package_version.__version__
)
__all__ = ("TraceServiceClient",)

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,196 @@
# -*- 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_v2 import gapic_version as package_version
from google.cloud.trace_v2.types import trace, tracing
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",
)
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.batch_write_spans: gapic_v1.method.wrap_method(
self.batch_write_spans,
default_retry=retries.Retry(
initial=0.1,
maximum=30.0,
multiplier=2,
predicate=retries.if_exception_type(
core_exceptions.DeadlineExceeded,
core_exceptions.ServiceUnavailable,
),
deadline=120.0,
),
default_timeout=120.0,
client_info=client_info,
),
self.create_span: gapic_v1.method.wrap_method(
self.create_span,
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=120.0,
),
default_timeout=120.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 batch_write_spans(
self,
) -> Callable[
[tracing.BatchWriteSpansRequest],
Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]],
]:
raise NotImplementedError()
@property
def create_span(
self,
) -> Callable[[trace.Span], Union[trace.Span, Awaitable[trace.Span]]]:
raise NotImplementedError()
@property
def kind(self) -> str:
raise NotImplementedError()
__all__ = ("TraceServiceTransport",)

View File

@@ -0,0 +1,390 @@
# -*- 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_v2.types import trace, tracing
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.v2.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.v2.TraceService",
"rpcName": client_call_details.method,
"response": grpc_response,
"metadata": grpc_response["metadata"],
},
)
return response
class TraceServiceGrpcTransport(TraceServiceTransport):
"""gRPC backend transport for TraceService.
Service for collecting and viewing traces and spans within a
trace.
A trace is a collection of spans corresponding to a single
operation or a set of operations in an application.
A span is an individual timed event which forms a node of the
trace tree. A single trace can contain spans from 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 batch_write_spans(
self,
) -> Callable[[tracing.BatchWriteSpansRequest], empty_pb2.Empty]:
r"""Return a callable for the batch write spans method over gRPC.
Batch writes new spans to new or existing traces. You
cannot update existing spans.
Returns:
Callable[[~.BatchWriteSpansRequest],
~.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 "batch_write_spans" not in self._stubs:
self._stubs["batch_write_spans"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v2.TraceService/BatchWriteSpans",
request_serializer=tracing.BatchWriteSpansRequest.serialize,
response_deserializer=empty_pb2.Empty.FromString,
)
return self._stubs["batch_write_spans"]
@property
def create_span(self) -> Callable[[trace.Span], trace.Span]:
r"""Return a callable for the create span method over gRPC.
Creates a new span.
Returns:
Callable[[~.Span],
~.Span]:
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 "create_span" not in self._stubs:
self._stubs["create_span"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v2.TraceService/CreateSpan",
request_serializer=trace.Span.serialize,
response_deserializer=trace.Span.deserialize,
)
return self._stubs["create_span"]
def close(self):
self._logged_channel.close()
@property
def kind(self) -> str:
return "grpc"
__all__ = ("TraceServiceGrpcTransport",)

View File

@@ -0,0 +1,437 @@
# -*- 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_v2.types import trace, tracing
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.v2.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.v2.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.
Service for collecting and viewing traces and spans within a
trace.
A trace is a collection of spans corresponding to a single
operation or a set of operations in an application.
A span is an individual timed event which forms a node of the
trace tree. A single trace can contain spans from 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 batch_write_spans(
self,
) -> Callable[[tracing.BatchWriteSpansRequest], Awaitable[empty_pb2.Empty]]:
r"""Return a callable for the batch write spans method over gRPC.
Batch writes new spans to new or existing traces. You
cannot update existing spans.
Returns:
Callable[[~.BatchWriteSpansRequest],
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 "batch_write_spans" not in self._stubs:
self._stubs["batch_write_spans"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v2.TraceService/BatchWriteSpans",
request_serializer=tracing.BatchWriteSpansRequest.serialize,
response_deserializer=empty_pb2.Empty.FromString,
)
return self._stubs["batch_write_spans"]
@property
def create_span(self) -> Callable[[trace.Span], Awaitable[trace.Span]]:
r"""Return a callable for the create span method over gRPC.
Creates a new span.
Returns:
Callable[[~.Span],
Awaitable[~.Span]]:
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 "create_span" not in self._stubs:
self._stubs["create_span"] = self._logged_channel.unary_unary(
"/google.devtools.cloudtrace.v2.TraceService/CreateSpan",
request_serializer=trace.Span.serialize,
response_deserializer=trace.Span.deserialize,
)
return self._stubs["create_span"]
def _prep_wrapped_messages(self, client_info):
"""Precompute the wrapped methods, overriding the base class method to use async wrappers."""
self._wrapped_methods = {
self.batch_write_spans: self._wrap_method(
self.batch_write_spans,
default_retry=retries.AsyncRetry(
initial=0.1,
maximum=30.0,
multiplier=2,
predicate=retries.if_exception_type(
core_exceptions.DeadlineExceeded,
core_exceptions.ServiceUnavailable,
),
deadline=120.0,
),
default_timeout=120.0,
client_info=client_info,
),
self.create_span: self._wrap_method(
self.create_span,
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=120.0,
),
default_timeout=120.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,549 @@
# -*- 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_v2.types import trace, tracing
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_batch_write_spans(self, request, metadata):
logging.log(f"Received request: {request}")
return request, metadata
def pre_create_span(self, request, metadata):
logging.log(f"Received request: {request}")
return request, metadata
def post_create_span(self, response):
logging.log(f"Received response: {response}")
return response
transport = TraceServiceRestTransport(interceptor=MyCustomTraceServiceInterceptor())
client = TraceServiceClient(transport=transport)
"""
def pre_batch_write_spans(
self,
request: tracing.BatchWriteSpansRequest,
metadata: Sequence[Tuple[str, Union[str, bytes]]],
) -> Tuple[tracing.BatchWriteSpansRequest, Sequence[Tuple[str, Union[str, bytes]]]]:
"""Pre-rpc interceptor for batch_write_spans
Override in a subclass to manipulate the request or metadata
before they are sent to the TraceService server.
"""
return request, metadata
def pre_create_span(
self, request: trace.Span, metadata: Sequence[Tuple[str, Union[str, bytes]]]
) -> Tuple[trace.Span, Sequence[Tuple[str, Union[str, bytes]]]]:
"""Pre-rpc interceptor for create_span
Override in a subclass to manipulate the request or metadata
before they are sent to the TraceService server.
"""
return request, metadata
def post_create_span(self, response: trace.Span) -> trace.Span:
"""Post-rpc interceptor for create_span
DEPRECATED. Please use the `post_create_span_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_create_span` interceptor runs
before the `post_create_span_with_metadata` interceptor.
"""
return response
def post_create_span_with_metadata(
self, response: trace.Span, metadata: Sequence[Tuple[str, Union[str, bytes]]]
) -> Tuple[trace.Span, Sequence[Tuple[str, Union[str, bytes]]]]:
"""Post-rpc interceptor for create_span
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_create_span_with_metadata`
interceptor in new development instead of the `post_create_span` interceptor.
When both interceptors are used, this `post_create_span_with_metadata` interceptor runs after the
`post_create_span` interceptor. The (possibly modified) response returned by
`post_create_span` will be passed to
`post_create_span_with_metadata`.
"""
return response, metadata
@dataclasses.dataclass
class TraceServiceRestStub:
_session: AuthorizedSession
_host: str
_interceptor: TraceServiceRestInterceptor
class TraceServiceRestTransport(_BaseTraceServiceRestTransport):
"""REST backend synchronous transport for TraceService.
Service for collecting and viewing traces and spans within a
trace.
A trace is a collection of spans corresponding to a single
operation or a set of operations in an application.
A span is an individual timed event which forms a node of the
trace tree. A single trace can contain spans from 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 _BatchWriteSpans(
_BaseTraceServiceRestTransport._BaseBatchWriteSpans, TraceServiceRestStub
):
def __hash__(self):
return hash("TraceServiceRestTransport.BatchWriteSpans")
@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: tracing.BatchWriteSpansRequest,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Optional[float] = None,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
):
r"""Call the batch write spans method over HTTP.
Args:
request (~.tracing.BatchWriteSpansRequest):
The request object. The request message for the ``BatchWriteSpans`` 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._BaseBatchWriteSpans._get_http_options()
)
request, metadata = self._interceptor.pre_batch_write_spans(
request, metadata
)
transcoded_request = _BaseTraceServiceRestTransport._BaseBatchWriteSpans._get_transcoded_request(
http_options, request
)
body = _BaseTraceServiceRestTransport._BaseBatchWriteSpans._get_request_body_json(
transcoded_request
)
# Jsonify the query params
query_params = _BaseTraceServiceRestTransport._BaseBatchWriteSpans._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_v2.TraceServiceClient.BatchWriteSpans",
extra={
"serviceName": "google.devtools.cloudtrace.v2.TraceService",
"rpcName": "BatchWriteSpans",
"httpRequest": http_request,
"metadata": http_request["headers"],
},
)
# Send the request
response = TraceServiceRestTransport._BatchWriteSpans._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)
class _CreateSpan(
_BaseTraceServiceRestTransport._BaseCreateSpan, TraceServiceRestStub
):
def __hash__(self):
return hash("TraceServiceRestTransport.CreateSpan")
@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.Span,
*,
retry: OptionalRetry = gapic_v1.method.DEFAULT,
timeout: Optional[float] = None,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
) -> trace.Span:
r"""Call the create span method over HTTP.
Args:
request (~.trace.Span):
The request object. A span represents a single operation
within a trace. Spans can be nested to
form a trace tree. Often, a trace
contains a root span that describes the
end-to-end latency, and one or more
subspans for its sub-operations.
A trace can also contain multiple root
spans, or none at all. Spans do not need
to be contiguous. There might be gaps or
overlaps between spans in a trace.
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.Span:
A span represents a single operation
within a trace. Spans can be nested to
form a trace tree. Often, a trace
contains a root span that describes the
end-to-end latency, and one or more
subspans for its sub-operations.
A trace can also contain multiple root
spans, or none at all. Spans do not need
to be contiguous. There might be gaps or
overlaps between spans in a trace.
"""
http_options = (
_BaseTraceServiceRestTransport._BaseCreateSpan._get_http_options()
)
request, metadata = self._interceptor.pre_create_span(request, metadata)
transcoded_request = (
_BaseTraceServiceRestTransport._BaseCreateSpan._get_transcoded_request(
http_options, request
)
)
body = (
_BaseTraceServiceRestTransport._BaseCreateSpan._get_request_body_json(
transcoded_request
)
)
# Jsonify the query params
query_params = (
_BaseTraceServiceRestTransport._BaseCreateSpan._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_v2.TraceServiceClient.CreateSpan",
extra={
"serviceName": "google.devtools.cloudtrace.v2.TraceService",
"rpcName": "CreateSpan",
"httpRequest": http_request,
"metadata": http_request["headers"],
},
)
# Send the request
response = TraceServiceRestTransport._CreateSpan._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)
# Return the response
resp = trace.Span()
pb_resp = trace.Span.pb(resp)
json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
resp = self._interceptor.post_create_span(resp)
response_metadata = [(k, str(v)) for k, v in response.headers.items()]
resp, _ = self._interceptor.post_create_span_with_metadata(
resp, response_metadata
)
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
logging.DEBUG
): # pragma: NO COVER
try:
response_payload = trace.Span.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_v2.TraceServiceClient.create_span",
extra={
"serviceName": "google.devtools.cloudtrace.v2.TraceService",
"rpcName": "CreateSpan",
"metadata": http_response["headers"],
"httpResponse": http_response,
},
)
return resp
@property
def batch_write_spans(
self,
) -> Callable[[tracing.BatchWriteSpansRequest], 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._BatchWriteSpans(self._session, self._host, self._interceptor) # type: ignore
@property
def create_span(self) -> Callable[[trace.Span], trace.Span]:
# 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._CreateSpan(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,206 @@
# -*- 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_v2.types import trace, tracing
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 _BaseBatchWriteSpans:
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": "post",
"uri": "/v2/{name=projects/*}/traces:batchWrite",
"body": "*",
},
]
return http_options
@staticmethod
def _get_transcoded_request(http_options, request):
pb_request = tracing.BatchWriteSpansRequest.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._BaseBatchWriteSpans._get_unset_required_fields(
query_params
)
)
query_params["$alt"] = "json;enum-encoding=int"
return query_params
class _BaseCreateSpan:
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": "post",
"uri": "/v2/{name=projects/*/traces/*/spans/*}",
"body": "*",
},
]
return http_options
@staticmethod
def _get_transcoded_request(http_options, request):
pb_request = trace.Span.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._BaseCreateSpan._get_unset_required_fields(
query_params
)
)
query_params["$alt"] = "json;enum-encoding=int"
return query_params
__all__ = ("_BaseTraceServiceRestTransport",)

View File

@@ -0,0 +1,26 @@
# -*- 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 .trace import AttributeValue, Module, Span, StackTrace, TruncatableString
from .tracing import BatchWriteSpansRequest
__all__ = (
"AttributeValue",
"Module",
"Span",
"StackTrace",
"TruncatableString",
"BatchWriteSpansRequest",
)

View File

@@ -0,0 +1,715 @@
# -*- 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 __future__ import annotations
from typing import MutableMapping, MutableSequence
from google.protobuf import timestamp_pb2 # type: ignore
from google.protobuf import wrappers_pb2 # type: ignore
from google.rpc import status_pb2 # type: ignore
import proto # type: ignore
__protobuf__ = proto.module(
package="google.devtools.cloudtrace.v2",
manifest={
"Span",
"AttributeValue",
"StackTrace",
"Module",
"TruncatableString",
},
)
class Span(proto.Message):
r"""A span represents a single operation within a trace. Spans
can be nested to form a trace tree. Often, a trace contains a
root span that describes the end-to-end latency, and one or more
subspans for its sub-operations.
A trace can also contain multiple root spans, or none at all.
Spans do not need to be contiguous. There might be
gaps or overlaps between spans in a trace.
Attributes:
name (str):
Required. The resource name of the span in the following
format:
- ``projects/[PROJECT_ID]/traces/[TRACE_ID]/spans/[SPAN_ID]``
``[TRACE_ID]`` is a unique identifier for a trace within a
project; it is a 32-character hexadecimal encoding of a
16-byte array. It should not be zero.
``[SPAN_ID]`` is a unique identifier for a span within a
trace; it is a 16-character hexadecimal encoding of an
8-byte array. It should not be zero. .
span_id (str):
Required. The ``[SPAN_ID]`` portion of the span's resource
name.
parent_span_id (str):
The ``[SPAN_ID]`` of this span's parent span. If this is a
root span, then this field must be empty.
display_name (google.cloud.trace_v2.types.TruncatableString):
Required. A description of the span's
operation (up to 128 bytes). Cloud Trace
displays the description in the Cloud console.
For example, the display name can be a qualified
method name or a file name and a line number
where the operation is called. A best practice
is to use the same display name within an
application and at the same call point. This
makes it easier to correlate spans in different
traces.
start_time (google.protobuf.timestamp_pb2.Timestamp):
Required. The start time of the span. On the
client side, this is the time kept by the local
machine where the span execution starts. On the
server side, this is the time when the server's
application handler starts running.
end_time (google.protobuf.timestamp_pb2.Timestamp):
Required. The end time of the span. On the
client side, this is the time kept by the local
machine where the span execution ends. On the
server side, this is the time when the server
application handler stops running.
attributes (google.cloud.trace_v2.types.Span.Attributes):
A set of attributes on the span. You can have
up to 32 attributes per span.
stack_trace (google.cloud.trace_v2.types.StackTrace):
Stack trace captured at the start of the
span.
time_events (google.cloud.trace_v2.types.Span.TimeEvents):
A set of time events. You can have up to 32
annotations and 128 message events per span.
links (google.cloud.trace_v2.types.Span.Links):
Links associated with the span. You can have
up to 128 links per Span.
status (google.rpc.status_pb2.Status):
Optional. The final status for this span.
same_process_as_parent_span (google.protobuf.wrappers_pb2.BoolValue):
Optional. Set this parameter to indicate
whether this span is in the same process as its
parent. If you do not set this parameter, Trace
is unable to take advantage of this helpful
information.
child_span_count (google.protobuf.wrappers_pb2.Int32Value):
Optional. The number of child spans that were
generated while this span was active. If set,
allows implementation to detect missing child
spans.
span_kind (google.cloud.trace_v2.types.Span.SpanKind):
Optional. Distinguishes between spans generated in a
particular context. For example, two spans with the same
name may be distinguished using ``CLIENT`` (caller) and
``SERVER`` (callee) to identify an RPC call.
"""
class SpanKind(proto.Enum):
r"""Type of span. Can be used to specify additional relationships
between spans in addition to a parent/child relationship.
Values:
SPAN_KIND_UNSPECIFIED (0):
Unspecified. Do NOT use as default.
Implementations MAY assume SpanKind.INTERNAL to
be default.
INTERNAL (1):
Indicates that the span is used internally.
Default value.
SERVER (2):
Indicates that the span covers server-side
handling of an RPC or other remote network
request.
CLIENT (3):
Indicates that the span covers the
client-side wrapper around an RPC or other
remote request.
PRODUCER (4):
Indicates that the span describes producer
sending a message to a broker. Unlike client and
server, there is no direct critical path latency
relationship between producer and consumer spans
(e.g. publishing a message to a pubsub service).
CONSUMER (5):
Indicates that the span describes consumer
receiving a message from a broker. Unlike client
and server, there is no direct critical path
latency relationship between producer and
consumer spans (e.g. receiving a message from a
pubsub service subscription).
"""
SPAN_KIND_UNSPECIFIED = 0
INTERNAL = 1
SERVER = 2
CLIENT = 3
PRODUCER = 4
CONSUMER = 5
class Attributes(proto.Message):
r"""A set of attributes as key-value pairs.
Attributes:
attribute_map (MutableMapping[str, google.cloud.trace_v2.types.AttributeValue]):
A set of attributes. Each attribute's key can be up to 128
bytes long. The value can be a string up to 256 bytes, a
signed 64-bit integer, or the boolean values ``true`` or
``false``. For example:
::
"/instance_id": { "string_value": { "value": "my-instance" } }
"/http/request_bytes": { "int_value": 300 }
"abc.com/myattribute": { "bool_value": false }
dropped_attributes_count (int):
The number of attributes that were discarded.
Attributes can be discarded because their keys
are too long or because there are too many
attributes. If this value is 0 then all
attributes are valid.
"""
attribute_map: MutableMapping[str, "AttributeValue"] = proto.MapField(
proto.STRING,
proto.MESSAGE,
number=1,
message="AttributeValue",
)
dropped_attributes_count: int = proto.Field(
proto.INT32,
number=2,
)
class TimeEvent(proto.Message):
r"""A time-stamped annotation or message event in the Span.
This message has `oneof`_ fields (mutually exclusive fields).
For each oneof, at most one member field can be set at the same time.
Setting any member of the oneof automatically clears all other
members.
.. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields
Attributes:
time (google.protobuf.timestamp_pb2.Timestamp):
The timestamp indicating the time the event
occurred.
annotation (google.cloud.trace_v2.types.Span.TimeEvent.Annotation):
Text annotation with a set of attributes.
This field is a member of `oneof`_ ``value``.
message_event (google.cloud.trace_v2.types.Span.TimeEvent.MessageEvent):
An event describing a message sent/received
between Spans.
This field is a member of `oneof`_ ``value``.
"""
class Annotation(proto.Message):
r"""Text annotation with a set of attributes.
Attributes:
description (google.cloud.trace_v2.types.TruncatableString):
A user-supplied message describing the event.
The maximum length for the description is 256
bytes.
attributes (google.cloud.trace_v2.types.Span.Attributes):
A set of attributes on the annotation. You
can have up to 4 attributes per Annotation.
"""
description: "TruncatableString" = proto.Field(
proto.MESSAGE,
number=1,
message="TruncatableString",
)
attributes: "Span.Attributes" = proto.Field(
proto.MESSAGE,
number=2,
message="Span.Attributes",
)
class MessageEvent(proto.Message):
r"""An event describing a message sent/received between Spans.
Attributes:
type (google.cloud.trace_v2.types.Span.TimeEvent.MessageEvent.Type):
Type of MessageEvent. Indicates whether the
message was sent or received.
id (int):
An identifier for the MessageEvent's message that can be
used to match ``SENT`` and ``RECEIVED`` MessageEvents.
uncompressed_size_bytes (int):
The number of uncompressed bytes sent or
received.
compressed_size_bytes (int):
The number of compressed bytes sent or
received. If missing, the compressed size is
assumed to be the same size as the uncompressed
size.
"""
class Type(proto.Enum):
r"""Indicates whether the message was sent or received.
Values:
TYPE_UNSPECIFIED (0):
Unknown event type.
SENT (1):
Indicates a sent message.
RECEIVED (2):
Indicates a received message.
"""
TYPE_UNSPECIFIED = 0
SENT = 1
RECEIVED = 2
type: "Span.TimeEvent.MessageEvent.Type" = proto.Field(
proto.ENUM,
number=1,
enum="Span.TimeEvent.MessageEvent.Type",
)
id: int = proto.Field(
proto.INT64,
number=2,
)
uncompressed_size_bytes: int = proto.Field(
proto.INT64,
number=3,
)
compressed_size_bytes: int = proto.Field(
proto.INT64,
number=4,
)
time: timestamp_pb2.Timestamp = proto.Field(
proto.MESSAGE,
number=1,
message=timestamp_pb2.Timestamp,
)
annotation: "Span.TimeEvent.Annotation" = proto.Field(
proto.MESSAGE,
number=2,
oneof="value",
message="Span.TimeEvent.Annotation",
)
message_event: "Span.TimeEvent.MessageEvent" = proto.Field(
proto.MESSAGE,
number=3,
oneof="value",
message="Span.TimeEvent.MessageEvent",
)
class TimeEvents(proto.Message):
r"""A collection of ``TimeEvent``\ s. A ``TimeEvent`` is a time-stamped
annotation on the span, consisting of either user-supplied key:value
pairs, or details of a message sent/received between Spans.
Attributes:
time_event (MutableSequence[google.cloud.trace_v2.types.Span.TimeEvent]):
A collection of ``TimeEvent``\ s.
dropped_annotations_count (int):
The number of dropped annotations in all the
included time events. If the value is 0, then no
annotations were dropped.
dropped_message_events_count (int):
The number of dropped message events in all
the included time events. If the value is 0,
then no message events were dropped.
"""
time_event: MutableSequence["Span.TimeEvent"] = proto.RepeatedField(
proto.MESSAGE,
number=1,
message="Span.TimeEvent",
)
dropped_annotations_count: int = proto.Field(
proto.INT32,
number=2,
)
dropped_message_events_count: int = proto.Field(
proto.INT32,
number=3,
)
class Link(proto.Message):
r"""A pointer from the current span to another span in the same
trace or in a different trace. For example, this can be used in
batching operations, where a single batch handler processes
multiple requests from different traces or when the handler
receives a request from a different project.
Attributes:
trace_id (str):
The ``[TRACE_ID]`` for a trace within a project.
span_id (str):
The ``[SPAN_ID]`` for a span within a trace.
type (google.cloud.trace_v2.types.Span.Link.Type):
The relationship of the current span relative
to the linked span.
attributes (google.cloud.trace_v2.types.Span.Attributes):
A set of attributes on the link. Up to 32
attributes can be specified per link.
"""
class Type(proto.Enum):
r"""The relationship of the current span relative to the linked
span: child, parent, or unspecified.
Values:
TYPE_UNSPECIFIED (0):
The relationship of the two spans is unknown.
CHILD_LINKED_SPAN (1):
The linked span is a child of the current
span.
PARENT_LINKED_SPAN (2):
The linked span is a parent of the current
span.
"""
TYPE_UNSPECIFIED = 0
CHILD_LINKED_SPAN = 1
PARENT_LINKED_SPAN = 2
trace_id: str = proto.Field(
proto.STRING,
number=1,
)
span_id: str = proto.Field(
proto.STRING,
number=2,
)
type: "Span.Link.Type" = proto.Field(
proto.ENUM,
number=3,
enum="Span.Link.Type",
)
attributes: "Span.Attributes" = proto.Field(
proto.MESSAGE,
number=4,
message="Span.Attributes",
)
class Links(proto.Message):
r"""A collection of links, which are references from this span to
a span in the same or different trace.
Attributes:
link (MutableSequence[google.cloud.trace_v2.types.Span.Link]):
A collection of links.
dropped_links_count (int):
The number of dropped links after the maximum
size was enforced. If this value is 0, then no
links were dropped.
"""
link: MutableSequence["Span.Link"] = proto.RepeatedField(
proto.MESSAGE,
number=1,
message="Span.Link",
)
dropped_links_count: int = proto.Field(
proto.INT32,
number=2,
)
name: str = proto.Field(
proto.STRING,
number=1,
)
span_id: str = proto.Field(
proto.STRING,
number=2,
)
parent_span_id: str = proto.Field(
proto.STRING,
number=3,
)
display_name: "TruncatableString" = proto.Field(
proto.MESSAGE,
number=4,
message="TruncatableString",
)
start_time: timestamp_pb2.Timestamp = proto.Field(
proto.MESSAGE,
number=5,
message=timestamp_pb2.Timestamp,
)
end_time: timestamp_pb2.Timestamp = proto.Field(
proto.MESSAGE,
number=6,
message=timestamp_pb2.Timestamp,
)
attributes: Attributes = proto.Field(
proto.MESSAGE,
number=7,
message=Attributes,
)
stack_trace: "StackTrace" = proto.Field(
proto.MESSAGE,
number=8,
message="StackTrace",
)
time_events: TimeEvents = proto.Field(
proto.MESSAGE,
number=9,
message=TimeEvents,
)
links: Links = proto.Field(
proto.MESSAGE,
number=10,
message=Links,
)
status: status_pb2.Status = proto.Field(
proto.MESSAGE,
number=11,
message=status_pb2.Status,
)
same_process_as_parent_span: wrappers_pb2.BoolValue = proto.Field(
proto.MESSAGE,
number=12,
message=wrappers_pb2.BoolValue,
)
child_span_count: wrappers_pb2.Int32Value = proto.Field(
proto.MESSAGE,
number=13,
message=wrappers_pb2.Int32Value,
)
span_kind: SpanKind = proto.Field(
proto.ENUM,
number=14,
enum=SpanKind,
)
class AttributeValue(proto.Message):
r"""The allowed types for ``[VALUE]`` in a ``[KEY]:[VALUE]`` attribute.
This message has `oneof`_ fields (mutually exclusive fields).
For each oneof, at most one member field can be set at the same time.
Setting any member of the oneof automatically clears all other
members.
.. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields
Attributes:
string_value (google.cloud.trace_v2.types.TruncatableString):
A string up to 256 bytes long.
This field is a member of `oneof`_ ``value``.
int_value (int):
A 64-bit signed integer.
This field is a member of `oneof`_ ``value``.
bool_value (bool):
A Boolean value represented by ``true`` or ``false``.
This field is a member of `oneof`_ ``value``.
"""
string_value: "TruncatableString" = proto.Field(
proto.MESSAGE,
number=1,
oneof="value",
message="TruncatableString",
)
int_value: int = proto.Field(
proto.INT64,
number=2,
oneof="value",
)
bool_value: bool = proto.Field(
proto.BOOL,
number=3,
oneof="value",
)
class StackTrace(proto.Message):
r"""A call stack appearing in a trace.
Attributes:
stack_frames (google.cloud.trace_v2.types.StackTrace.StackFrames):
Stack frames in this stack trace. A maximum
of 128 frames are allowed.
stack_trace_hash_id (int):
The hash ID is used to conserve network bandwidth for
duplicate stack traces within a single trace.
Often multiple spans will have identical stack traces. The
first occurrence of a stack trace should contain both the
``stackFrame`` content and a value in ``stackTraceHashId``.
Subsequent spans within the same request can refer to that
stack trace by only setting ``stackTraceHashId``.
"""
class StackFrame(proto.Message):
r"""Represents a single stack frame in a stack trace.
Attributes:
function_name (google.cloud.trace_v2.types.TruncatableString):
The fully-qualified name that uniquely
identifies the function or method that is active
in this frame (up to 1024 bytes).
original_function_name (google.cloud.trace_v2.types.TruncatableString):
An un-mangled function name, if ``function_name`` is
mangled. To get information about name mangling, run `this
search <https://www.google.com/search?q=cxx+name+mangling>`__.
The name can be fully-qualified (up to 1024 bytes).
file_name (google.cloud.trace_v2.types.TruncatableString):
The name of the source file where the
function call appears (up to 256 bytes).
line_number (int):
The line number in ``file_name`` where the function call
appears.
column_number (int):
The column number where the function call
appears, if available. This is important in
JavaScript because of its anonymous functions.
load_module (google.cloud.trace_v2.types.Module):
The binary module from where the code was
loaded.
source_version (google.cloud.trace_v2.types.TruncatableString):
The version of the deployed source code (up
to 128 bytes).
"""
function_name: "TruncatableString" = proto.Field(
proto.MESSAGE,
number=1,
message="TruncatableString",
)
original_function_name: "TruncatableString" = proto.Field(
proto.MESSAGE,
number=2,
message="TruncatableString",
)
file_name: "TruncatableString" = proto.Field(
proto.MESSAGE,
number=3,
message="TruncatableString",
)
line_number: int = proto.Field(
proto.INT64,
number=4,
)
column_number: int = proto.Field(
proto.INT64,
number=5,
)
load_module: "Module" = proto.Field(
proto.MESSAGE,
number=6,
message="Module",
)
source_version: "TruncatableString" = proto.Field(
proto.MESSAGE,
number=7,
message="TruncatableString",
)
class StackFrames(proto.Message):
r"""A collection of stack frames, which can be truncated.
Attributes:
frame (MutableSequence[google.cloud.trace_v2.types.StackTrace.StackFrame]):
Stack frames in this call stack.
dropped_frames_count (int):
The number of stack frames that were dropped
because there were too many stack frames.
If this value is 0, then no stack frames were
dropped.
"""
frame: MutableSequence["StackTrace.StackFrame"] = proto.RepeatedField(
proto.MESSAGE,
number=1,
message="StackTrace.StackFrame",
)
dropped_frames_count: int = proto.Field(
proto.INT32,
number=2,
)
stack_frames: StackFrames = proto.Field(
proto.MESSAGE,
number=1,
message=StackFrames,
)
stack_trace_hash_id: int = proto.Field(
proto.INT64,
number=2,
)
class Module(proto.Message):
r"""Binary module.
Attributes:
module (google.cloud.trace_v2.types.TruncatableString):
For example: main binary, kernel modules, and
dynamic libraries such as libc.so, sharedlib.so
(up to 256 bytes).
build_id (google.cloud.trace_v2.types.TruncatableString):
A unique identifier for the module, usually a
hash of its contents (up to 128 bytes).
"""
module: "TruncatableString" = proto.Field(
proto.MESSAGE,
number=1,
message="TruncatableString",
)
build_id: "TruncatableString" = proto.Field(
proto.MESSAGE,
number=2,
message="TruncatableString",
)
class TruncatableString(proto.Message):
r"""Represents a string that might be shortened to a specified
length.
Attributes:
value (str):
The shortened string. For example, if the original string is
500 bytes long and the limit of the string is 128 bytes,
then ``value`` contains the first 128 bytes of the 500-byte
string.
Truncation always happens on a UTF8 character boundary. If
there are multi-byte characters in the string, then the
length of the shortened string might be less than the size
limit.
truncated_byte_count (int):
The number of bytes removed from the original
string. If this value is 0, then the string was
not shortened.
"""
value: str = proto.Field(
proto.STRING,
number=1,
)
truncated_byte_count: int = proto.Field(
proto.INT32,
number=2,
)
__all__ = tuple(sorted(__protobuf__.manifest))

View File

@@ -0,0 +1,56 @@
# -*- 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 __future__ import annotations
from typing import MutableMapping, MutableSequence
import proto # type: ignore
from google.cloud.trace_v2.types import trace
__protobuf__ = proto.module(
package="google.devtools.cloudtrace.v2",
manifest={
"BatchWriteSpansRequest",
},
)
class BatchWriteSpansRequest(proto.Message):
r"""The request message for the ``BatchWriteSpans`` method.
Attributes:
name (str):
Required. The name of the project where the spans belong.
The format is ``projects/[PROJECT_ID]``.
spans (MutableSequence[google.cloud.trace_v2.types.Span]):
Required. A list of new spans. The span names
must not match existing spans, otherwise the
results are undefined.
"""
name: str = proto.Field(
proto.STRING,
number=1,
)
spans: MutableSequence[trace.Span] = proto.RepeatedField(
proto.MESSAGE,
number=2,
message=trace.Span,
)
__all__ = tuple(sorted(__protobuf__.manifest))