Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add debug logs for rest streaming
  • Loading branch information
parthea committed Mar 19, 2025
commit 826c79b533d4a595ac7c8dae9fc9925d11474fb7
26 changes: 24 additions & 2 deletions google/api_core/_rest_streaming_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""Helpers for server-side streaming in REST."""

from collections import deque
import logging
import string
from typing import Deque, Union
import types
Expand All @@ -23,6 +24,8 @@
import google.protobuf.message
from google.protobuf.json_format import Parse

_LOGGER = logging.getLogger(__name__)


class BaseResponseIterator:
"""Base Iterator over REST API responses. This class should not be used directly.
Expand Down Expand Up @@ -97,19 +100,38 @@ def _process_chunk(self, chunk: str):
self._obj += char
self._escape_next = not self._escape_next if char == "\\" else False

def _log_response_payload(self, response_payload: str):
rest_response = {
"payload": response_payload,
"status": "OK",
}
_LOGGER.debug(
"Received response via REST stream",
extra={
"response": rest_response,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we be using httpResponse here instead for structured logs?

Comment on lines +104 to +111
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should be using/reference any sort of HTTP response here at all. This helper is being called from grab, and grab simply passes already received messages reconstituted from chunks. So what we should log in grab is something like passing next message to stream: <message>.

We should log http responses where we actually receive the HTTP chunks.

},
)

def _create_grab(self):
logging_enabled = _LOGGER.isEnabledFor(logging.DEBUG)
if issubclass(self._response_message_cls, proto.Message):

def grab(this):
result = this._ready_objs.popleft()
if logging_enabled: # pragma: NO COVER
self._log_result(result)
return this._response_message_cls.from_json(
this._ready_objs.popleft(), ignore_unknown_fields=True
result, ignore_unknown_fields=True
)

return grab
elif issubclass(self._response_message_cls, google.protobuf.message.Message):

def grab(this):
return Parse(this._ready_objs.popleft(), this._response_message_cls())
result = this._ready_objs.popleft()
if logging_enabled: # pragma: NO COVER
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add coverage for this?

self._log_result(result)
return Parse(result, this._response_message_cls())

return grab
else:
Expand Down