-
Notifications
You must be signed in to change notification settings - Fork 1.8k
feat(gapic): add OpenTelemetry channel tracing to generator templates #18342
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
bfb40b0
87ca9b8
451e17b
29de72e
7f6519f
b0de0a4
ac095c5
ef7d77d
aa2bead
894b380
1c1b9af
81b686c
324b866
abeaf04
99a4d3d
4b82c9c
0fb354a
acce308
d337933
13f1218
11ccd0d
a7dad4f
858ff52
b1c66e4
b409ba6
2059f32
66a6f0e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,9 +8,14 @@ import json | |
| import logging as std_logging | ||
| import pickle | ||
| import warnings | ||
| from typing import Callable, Dict, Optional, Sequence, Tuple, Union | ||
| from typing import Callable, Dict, Optional, Sequence, Tuple, Union, TYPE_CHECKING | ||
|
|
||
| import grpc # type: ignore | ||
| from google.api_core import grpc_helpers | ||
|
|
||
| if TYPE_CHECKING: # pragma: NO COVER | ||
| # ClientInterceptor was added in google-api-core 2.36.0+; ignore attribute-defined for older api-core versions during type checking | ||
| from google.api_core.grpc_helpers import ClientInterceptor # type: ignore[attr-defined] | ||
| {% if service.has_lro %} | ||
| from google.api_core import operations_v1 | ||
| {% endif %} | ||
|
|
@@ -21,7 +26,6 @@ from google.auth.transport.grpc import SslCredentials # type: ignore | |
| from google.protobuf.json_format import MessageToJson | ||
| import google.protobuf.message | ||
|
|
||
| import grpc # type: ignore | ||
| import proto # type: ignore | ||
|
|
||
| {% filter sort_lines %} | ||
|
|
@@ -80,7 +84,7 @@ class _LoggingClientInterceptor(grpc.UnaryUnaryClientInterceptor): # pragma: NO | |
| grpc_response = { | ||
| "payload": response_payload, | ||
| "metadata": metadata, | ||
| "status": "OK", | ||
| "status": "OK", | ||
| } | ||
| _LOGGER.debug( | ||
| f"Received response for {client_call_details.method}.", | ||
|
|
@@ -123,6 +127,14 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): | |
| client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, | ||
| always_use_jwt_access: Optional[bool] = False, | ||
| api_audience: Optional[str] = None, | ||
| interceptors: Optional[ | ||
| Sequence[ | ||
| Union[ | ||
| "ClientInterceptor", | ||
| Callable[[grpc.Channel], grpc.Channel], | ||
| ] | ||
| ] | ||
| ] = None, | ||
| ) -> None: | ||
| """Instantiate the transport. | ||
|
|
||
|
|
@@ -143,7 +155,7 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): | |
| 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`` | ||
| 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. | ||
|
|
@@ -173,6 +185,9 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): | |
| to the service that will be set when using certain 3rd party | ||
| authentication flows. Audience is typically a resource identifier. | ||
| If not set, the host value will be used as a default. | ||
| interceptors (Optional[Sequence[Union[ClientInterceptor, Callable[[grpc.Channel], grpc.Channel]]]]): | ||
| Additional interceptors (or callables that apply interceptors) to apply to the | ||
| gRPC channel. | ||
|
|
||
| Raises: | ||
| google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport | ||
|
|
@@ -252,6 +267,13 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): | |
| ], | ||
| ) | ||
|
|
||
| apply_interceptors = getattr( | ||
| grpc_helpers, | ||
| "apply_channel_interceptors", | ||
| lambda channel, interceptors: channel, | ||
| ) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: If you wanted to make sure this is present, you could make use of the _compat file until we get the right version of api_core in place
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not recommendedRegarding |
||
| self._grpc_channel = apply_interceptors(self._grpc_channel, interceptors) | ||
|
|
||
| self._interceptor = _LoggingClientInterceptor() | ||
| self._logged_channel = grpc.intercept_channel(self._grpc_channel, self._interceptor) | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note
For reviewers: this line is updated from what was in the prototype.
New:
Old (from the
secret-managerprototype):There was a concern if we solely checked for "is the object an instance of the given class". If a user subclassed (i.e.
EchoGrpcTransport) the old check would throw an error. We added two small protections here:We check for whether the object
issubclass(...).We avoid a
TypeErrorduring that check by ensuring that we don't pass in a function. These ensure that we only pass interceptors to gRPC transports that are guaranteed to accept the expected parameters.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good change, but looking at this more, I'm thinking we should probably just append the custom interceptors inside the Transport.__init__, instead of trying to build the interceptor list here. I forgot that this same method is shared for sync/async/rest, which all have different interceptor formats. And this logic loses the interceptors if a
Callableis passedWhat do you think?