Skip to content

Commit 4cb1fa2

Browse files
partheaohmayrvchudnov-g
authored
feat: add debug log when sending requests via REST (#2270)
Co-authored-by: ohmayr <[email protected]> Co-authored-by: Victor Chudnovsky <[email protected]>
1 parent 8be95a2 commit 4cb1fa2

File tree

16 files changed

+3196
-26
lines changed

16 files changed

+3196
-26
lines changed

gapic/templates/%namespace/%name_%version/%sub/services/%service/_shared_macros.j2

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,15 @@ def _get_http_options():
195195
Args:
196196
body_spec (str): The http options body i.e. method.http_options[0].body
197197
method_name (str): The method name.
198-
service_name (str): The service name.
198+
service: The service.
199199
is_async (bool): Used to determine the code path i.e. whether for sync or async call. #}
200-
{% macro rest_call_method_common(body_spec, method_name, service_name, is_async=False) %}
200+
{% macro rest_call_method_common(body_spec, method_name, service, is_async=False) %}
201+
{% set service_name = service.name %}
201202
{% set await_prefix = "await " if is_async else "" %}
202203
{% set async_class_prefix = "Async" if is_async else "" %}
203204

204205
http_options = _Base{{ service_name }}RestTransport._Base{{method_name}}._get_http_options()
206+
{# TODO(https://github.com/googleapis/gapic-generator-python/issues/2274): Add debug log before intercepting a request #}
205207
request, metadata = {{ await_prefix }}self._interceptor.pre_{{ method_name|snake_case }}(request, metadata)
206208
transcoded_request = _Base{{ service_name }}RestTransport._Base{{method_name}}._get_transcoded_request(http_options, request)
207209

@@ -212,6 +214,24 @@ def _get_http_options():
212214
# Jsonify the query params
213215
query_params = _Base{{ service_name }}RestTransport._Base{{method_name}}._get_query_params_json(transcoded_request)
214216

217+
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(logging.DEBUG): # pragma: NO COVER
218+
request_url = "{host}{uri}".format(host=self._host, uri=transcoded_request['uri'])
219+
method = transcoded_request['method']
220+
http_request = {
221+
"payload": type(request).to_json(request),
222+
"requestMethod": method,
223+
"requestUrl": request_url,
224+
}
225+
_LOGGER.debug(
226+
f"Sending request for {{ service.meta.address.proto_package_versioned }}.{{ service.client_name }}.{{ method_name }}",
227+
extra = {
228+
"serviceName": "{{ service.meta.address.proto }}",
229+
"rpcName": "{{ method_name }}",
230+
"metadata": str(dict(metadata)),
231+
"httpRequest": http_request,
232+
},
233+
)
234+
215235
# Send the request
216236
response = {{ await_prefix }}{{ async_class_prefix }}{{ service_name }}RestTransport._{{method_name}}._get_response(self._host, metadata, query_params, self._session, timeout, transcoded_request{% if body_spec %}, body{% endif %})
217237

@@ -434,7 +454,7 @@ class _{{ name }}(_Base{{ service.name }}RestTransport._Base{{name}}, {{ async_m
434454
{{ sig.response_type }}: Response from {{ name }} method.
435455
{% endif %}
436456
"""
437-
{{ rest_call_method_common(body_spec, name, service.name, is_async)|indent(4) }}
457+
{{ rest_call_method_common(body_spec, name, service, is_async)|indent(4) }}
438458

439459
{% if sig.response_type == "None" %}
440460
return {{ await_prefix }}self._interceptor.post_{{ name|snake_case }}(None)
@@ -447,6 +467,22 @@ class _{{ name }}(_Base{{ service.name }}RestTransport._Base{{name}}, {{ async_m
447467
resp = {{ sig.response_type }}()
448468
resp = json_format.Parse(content, resp)
449469
resp = {{ await_prefix }}self._interceptor.post_{{ name|snake_case }}(resp)
470+
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(logging.DEBUG): # pragma: NO COVER
471+
http_response = {
472+
"payload": json_format.MessageToJson(response),
473+
"headers": dict(response.headers),
474+
"status": response.status_code,
475+
}
476+
_LOGGER.debug(
477+
"Received response for {{ service.meta.address.proto_package_versioned }}.{{ service.async_client_name }}.{{ name }}",
478+
extra = {
479+
"serviceName": "{{ service.meta.address.proto }}",
480+
"rpcName": "{{ name }}",
481+
{# TODO(https://github.com/googleapis/gapic-generator-python/issues/2275): logging `metadata` seems repetitive and may need to be cleaned up #}
482+
"metadata": http_response["headers"],
483+
"httpResponse": http_response,
484+
},
485+
)
450486
return resp
451487
{% endif %}
452488

gapic/templates/%namespace/%name_%version/%sub/services/%service/client.py.j2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -617,8 +617,8 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
617617
extra = {
618618
"serviceName": "{{ service.meta.address.proto }}",
619619
"universeDomain": getattr(self._transport._credentials, "universe_domain", ""),
620-
"credentialType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}",
621-
"credentialInfo": getattr(self.transport._credentials, "get_cred_info", lambda: None)(),
620+
"credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}",
621+
"credentialsInfo": getattr(self.transport._credentials, "get_cred_info", lambda: None)(),
622622
},
623623
)
624624

gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/rest.py.j2

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33

44
{% block content %}
55

6+
import logging
7+
import json # type: ignore
68

79
from google.auth.transport.requests import AuthorizedSession # type: ignore
8-
import json # type: ignore
910
from google.auth import credentials as ga_credentials # type: ignore
1011
from google.api_core import exceptions as core_exceptions
1112
from google.api_core import retry as retries
@@ -40,6 +41,13 @@ try:
4041
except AttributeError: # pragma: NO COVER
4142
OptionalRetry = Union[retries.Retry, object, None] # type: ignore
4243

44+
try: # pragma: NO COVER
45+
from google.api_core import client_logging # type: ignore
46+
CLIENT_LOGGING_SUPPORTED = True
47+
except ImportError:
48+
CLIENT_LOGGING_SUPPORTED = False
49+
50+
_LOGGER = logging.getLogger(__name__)
4351

4452
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
4553
gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version,
@@ -227,7 +235,7 @@ class {{service.name}}RestTransport(_Base{{ service.name }}RestTransport):
227235
{% endif %}
228236
"""
229237

230-
{{ shared_macros.rest_call_method_common(body_spec, method.name, service.name)|indent(8) }}
238+
{{ shared_macros.rest_call_method_common(body_spec, method.name, service)|indent(8) }}
231239

232240
{% if not method.void %}
233241
# Return the response
@@ -246,7 +254,24 @@ class {{service.name}}RestTransport(_Base{{ service.name }}RestTransport):
246254

247255
json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
248256
{% endif %}{# method.lro #}
257+
{#- TODO(https://github.com/googleapis/gapic-generator-python/issues/2274): Add debug log before intercepting a request #}
249258
resp = self._interceptor.post_{{ method.name|snake_case }}(resp)
259+
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(logging.DEBUG): # pragma: NO COVER
260+
http_response = {
261+
"payload": {% if method.output.ident.is_proto_plus_type %}{{ method.output.ident }}.to_json(resp){% else %}json_format.MessageToJson(resp){% endif %},
262+
"headers": dict(response.headers),
263+
"status": response.status_code,
264+
}
265+
_LOGGER.debug(
266+
"Received response for {{ service.meta.address.proto_package_versioned }}.{{ service.client_name }}.{{ method.transport_safe_name|snake_case }}",
267+
extra = {
268+
"serviceName": "{{ service.meta.address.proto }}",
269+
"rpcName": "{{ method.name }}",
270+
{# TODO(https://github.com/googleapis/gapic-generator-python/issues/2275): logging `metadata` seems repetitive and may need to be cleaned up #}
271+
"metadata": http_response["headers"],
272+
"httpResponse": http_response,
273+
},
274+
)
250275
return resp
251276

252277
{% endif %}{# method.void #}

gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/rest_asyncio.py.j2

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,17 @@ from .rest_base import _Base{{ service.name }}RestTransport
5858

5959
from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO
6060

61+
62+
import logging
63+
64+
try: # pragma: NO COVER
65+
from google.api_core import client_logging # type: ignore
66+
CLIENT_LOGGING_SUPPORTED = True
67+
except ImportError:
68+
CLIENT_LOGGING_SUPPORTED = False
69+
70+
_LOGGER = logging.getLogger(__name__)
71+
6172
try:
6273
OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None]
6374
except AttributeError: # pragma: NO COVER
@@ -188,7 +199,7 @@ class Async{{service.name}}RestTransport(_Base{{ service.name }}RestTransport):
188199
{% endif %}
189200
"""
190201

191-
{{ shared_macros.rest_call_method_common(body_spec, method.name, service.name, is_async=True)|indent(8) }}
202+
{{ shared_macros.rest_call_method_common(body_spec, method.name, service, is_async=True)|indent(8) }}
192203

193204
{% if not method.void %}
194205
# Return the response
@@ -206,6 +217,22 @@ class Async{{service.name}}RestTransport(_Base{{ service.name }}RestTransport):
206217
json_format.Parse(content, pb_resp, ignore_unknown_fields=True)
207218
{% endif %}{# if method.server_streaming #}
208219
resp = await self._interceptor.post_{{ method.name|snake_case }}(resp)
220+
if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(logging.DEBUG): # pragma: NO COVER
221+
http_response = {
222+
"payload": {% if method.output.ident.is_proto_plus_type %}{{ method.output.ident }}.to_json(response){% else %}json_format.MessageToJson(response){% endif %},
223+
"headers": str(dict(response.headers)),
224+
"status": "OK", # need to obtain this properly
225+
}
226+
_LOGGER.debug(
227+
"Received response for {{ service.meta.address.proto_package_versioned }}.{{ service.async_client_name }}.{{ method.transport_safe_name|snake_case }}",
228+
extra = {
229+
"serviceName": "{{ service.meta.address.proto }}",
230+
"rpcName": "{{ method.name }}",
231+
"metadata": http_response["headers"],
232+
"httpResponse": http_response,
233+
},
234+
)
235+
209236
return resp
210237

211238
{% endif %}{# method.void #}

tests/integration/goldens/asset/google/cloud/asset_v1/services/asset_service/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,8 +638,8 @@ def __init__(self, *,
638638
extra = {
639639
"serviceName": "google.cloud.asset.v1.AssetService",
640640
"universeDomain": getattr(self._transport._credentials, "universe_domain", ""),
641-
"credentialType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}",
642-
"credentialInfo": getattr(self.transport._credentials, "get_cred_info", lambda: None)(),
641+
"credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}",
642+
"credentialsInfo": getattr(self.transport._credentials, "get_cred_info", lambda: None)(),
643643
},
644644
)
645645

0 commit comments

Comments
 (0)