Skip to content

[DRAFT] feat: added client side metric instrumentation to read_rows and mutate_rows#16758

Draft
daniel-sanche wants to merge 5 commits intobigtable_csm_1_basic_instrumentationfrom
bigtable_csm_2_instrumentation_advanced
Draft

[DRAFT] feat: added client side metric instrumentation to read_rows and mutate_rows#16758
daniel-sanche wants to merge 5 commits intobigtable_csm_1_basic_instrumentationfrom
bigtable_csm_2_instrumentation_advanced

Conversation

@daniel-sanche
Copy link
Copy Markdown
Contributor

Migration of googleapis/python-bigtable#1256 to the monorepo

Builds off of #16712 to add instrumentation to read_rows and mutate_rows, along with the mutation batcher

@daniel-sanche daniel-sanche changed the title Bigtable csm 2 instrumentation advanced [DRAFT] feat: added client side metric instrumentation to read_rows and mutate_rows Apr 21, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request integrates client-side metrics tracking into Bigtable data operations, including ReadRows and MutateRows, for both asynchronous and synchronous implementations. It introduces tracked_retry to capture operation metrics and refactors read_row to utilize operation classes directly, supported by extensive new system and unit tests. Feedback identifies opportunities to improve the efficiency of read_row by using next() or __anext__ on generators instead of converting them to lists, and suggests adding a type ignore comment in the synchronous code for consistency.

Comment on lines +1246 to 1250
try:
results = [a async for a in results_generator]
return results[0]
except IndexError:
return None
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This implementation consumes the entire generator into a list just to get the first element. A more efficient and idiomatic way to get the first item from an async generator is to use anext.

Suggested change
try:
results = [a async for a in results_generator]
return results[0]
except IndexError:
return None
try:
return await results_generator.__anext__()
except StopAsyncIteration:
return None

Comment on lines +275 to +277
self._operation_metric.active_attempt.application_blocking_time_ns += (
time.monotonic_ns() - block_time
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The corresponding async version of this code includes a # type: ignore comment here. To maintain consistency and prevent potential mypy errors, it would be good to add it here as well.

Suggested change
self._operation_metric.active_attempt.application_blocking_time_ns += (
time.monotonic_ns() - block_time
)
self._operation_metric.active_attempt.application_blocking_time_ns += (
time.monotonic_ns() - block_time
) # type: ignore
References
  1. Using type: ignore is an acceptable trade-off to satisfy mypy when precise type hints are not cost-effective or to maintain consistency with other parts of the codebase.

Comment on lines +1013 to 1017
try:
results = [a for a in results_generator]
return results[0]
except IndexError:
return None
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This implementation consumes the entire generator into a list just to get the first element. A more efficient and idiomatic way to get the first item from a generator is to use next().

Suggested change
try:
results = [a for a in results_generator]
return results[0]
except IndexError:
return None
try:
return next(results_generator)
except StopIteration:
return None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant