Visitar URL original
feat(storage): add StorageMetricsContext for operation metrics state by nidhiii-27 · Pull Request #14728 · googleapis/google-cloud-java · GitHub
Skip to content

feat(storage): add StorageMetricsContext for operation metrics state - #14728

Merged
nidhiii-27 merged 56 commits into
mainfrom
feat/storage-metrics-context
Nov 11, 2026
Merged

nidhiii-27 merged 56 commits into
mainfrom
feat/storage-metrics-context

Conversation

@nidhiii-27

Copy link
Copy Markdown
Contributor

Introduces StorageMetricsContext for tracking per-operation and per-attempt OpenTelemetry metrics state.

  • Adds StorageMetricsContext to manage operation attributes, attempt counters, and durations.
  • Adds StorageMetricsContextTest unit tests.

Stacked on #14694.

…nfiguration

- Add configuration options to StorageOptions, GrpcStorageOptions, and HttpStorageOptions (enableOtelMetrics, enableOtelDebugMetrics, meterProvider, metricInterval).
- Add development gate checking system properties and environment variables in StorageMetricsConfig.
- Implement package-private instrument registry in StorageClientMetrics.
- Update OpenTelemetryBootstrappingUtils to register client views with custom histogram boundaries and create client meter provider.
- Add comprehensive unit tests in StorageOptionsTest, StorageClientMetricsTest, and OpenTelemetryBootstrappingUtilsTest.
Apply spotify fmt-maven-plugin formatting to StorageMetricsConfig, StorageClientMetrics, StorageOptionsTest, and StorageClientMetricsTest.

[Generated-by: AI]
Use simple class name Duration instead of fully qualified java.time.Duration in GrpcStorageOptions and OpenTelemetryBootstrappingUtils.

[Generated-by: AI]
…trappingUtils

Apply spotify fmt-maven-plugin formatting to OpenTelemetryBootstrappingUtils.

[Generated-by: AI]
… metrics

Refactor addClientHistogramView in OpenTelemetryBootstrappingUtils to remove unit selector and custom view description, preserving instrument default descriptions.

Remove deferred Phase 2 connection metrics (dnsLookupDuration, tcpConnectDuration, tlsHandshakeDuration) from StorageClientMetrics, CLIENT_LATENCY_HISTOGRAMS, and StorageClientMetricsTest.

Ensure clean Duration imports.

[Generated-by: AI]
…rProvider

Default api parameter to "grpc" instead of "storage" in createClientMeterProvider, allow specifying "json" / "http" transport protocols for Cloud Monitoring monitored resource storage.googleapis.com/Client, and add unit test coverage in OpenTelemetryBootstrappingUtilsTest.

[Generated-by: AI]
Update createClientMeterProvider to use prefix custom.googleapis.com with default monitored resource mapping.
Add KEY_URL_TEMPLATE attribute key constant in StorageClientMetrics.

[Generated-by: AI]
… options

- In GrpcStorageOptions and HttpStorageOptions:
  - Add null check in getMetricInterval() defaulting to 60 seconds
  - Use getMetricInterval() in equals() and hashCode()
  - Update Javadoc for setMeterProvider to document nullable/default behavior
- In StorageOptions:
  - Update Javadoc for setMeterProvider on Builder
- In StorageMetricsConfig:
  - Make sysPropResolver and envResolver volatile for thread safety
- In StorageOptionsTest:
  - Add unit test verifying deserialization with null metricInterval defaults to 60s and equals/hashCode match
  - Verify explicit client options take precedence over env vars and sysprops

[Generated-by: AI]
Format StorageOptions, GrpcStorageOptions, HttpStorageOptions, and StorageOptionsTest using com.spotify.fmt:fmt-maven-plugin:2.25:format under JDK 17 to resolve CI lint check failure.

[Generated-by: AI]
…iew comments

Clamp metric export interval to at least 60 seconds when meterProvider is null and no custom OpenTelemetry is configured, preventing invalid sub-60s intervals during deserialization when falling back to default Cloud Monitoring exporter.

[Generated-by: AI]
…ig and tests

Deduplicate flag resolution in StorageMetricsConfig by extracting resolveFlag helper, separate multi-behavior tests per go/tott/726, and add input diagnostic messages in looped assertions.

[Generated-by: AI]
@nidhiii-27
nidhiii-27 requested review from a team as code owners October 22, 2026 05:39
… tests

- Walk the class hierarchy in isAuthException to support anonymous and custom subclasses, and remove redundant simpleName check.
- Extract mapSpecificClientCause and mapKnownCause helpers and check specific client causes on HttpResponseException.
- Guard against null StatusCode on ApiException.
- Restrict single-use HTTP mapping status constants to private visibility, use Ascii.toLowerCase, add boolean parameter comments, and move private constructor to bottom of class.
- Split multi-behavior tests in StorageErrorTypeMapperTest, deduplicate test exception classes and CRC32C fixtures, and import SigningException.

[Generated-by: AI]
- Consolidate CONNECTION_REFUSED, CONNECTION_RESET, and CONNECTIVITY into CONNECTION_ERROR.
- Keep DEADLINE_EXCEEDED for server/RPC status codes and HTTP 408/504, reserving TIMEOUT for client timeouts.
- Map HTTP 409 to ABORTED.
- Include IOException in hasSpecificClientCause so wrapped IOExceptions map to CONNECTION_ERROR.
- Match server-side CRC32C and MD5 checksum mismatch messages in isChecksumMismatch.

[Generated-by: AI]
Explicitly declare com.google.api:gax-httpjson in java-storage/google-cloud-storage/pom.xml to satisfy Maven dependency:analyze.

[Generated-by: AI]

@cpriti-os cpriti-os left a comment

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.

Left a few small comments on attribute filtering and status code fallbacks.

- Check status.getCause() and server checksum mismatch descriptions on INVALID_ARGUMENT and DATA_LOSS in mapGrpcStatus
- Simplify StorageException cause handling in mapThrowable by calling mapKnownCause directly
- Restrict (crc32c || md5) && match server checksum error pattern to HTTP 400 and gRPC INVALID_ARGUMENT / DATA_LOSS
- Add unit tests for mapGrpcStatus causes/descriptions and negative 404/412 checksum message cases

[Generated-by: AI]
@nidhiii-27
nidhiii-27 requested a review from cpriti-os November 2, 2026 12:30
- Move self-causation check to the bottom of the while loop in extractRpcStatusCode and extractHttpStatusCode so top-level self-causing exceptions are inspected first
- Add defensive null checks on getStatus() and getCode() for StatusRuntimeException and StatusException in extractRpcStatusCode
- Add unit tests for top-level self-causing exceptions and null status on gRPC status exceptions

[Generated-by: AI]

@cpriti-os cpriti-os left a comment

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.

LGTM! Left a few optional cleanup/idiomatic suggestions that can be addressed here or in a follow-up.

AttributeKey.stringKey("http.request.method");
static final AttributeKey<Long> KEY_HTTP_RESPONSE_STATUS_CODE =
AttributeKey.longKey("http.response.status_code");
static final AttributeKey<String> KEY_HTTP_RESPONSE_STATUS_CODE =

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.

Ref: https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/

In the OTel semantic conventions, http.response.status_code is an int attribute, and it should only be set when a response was actually received. This change makes it a string, and the stack uses "" (gRPC calls) and "0" (no response) as placeholders. I think we should stick to the otel convenetions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated KEY_HTTP_RESPONSE_STATUS_CODE back to AttributeKey (AttributeKey.longKey("http.response.status_code")) with 0L as the fallback when no HTTP response is received or on gRPC attempts (matching the Go SDK's attribute.Int64("http.response.status_code", 0) while still emitting both keys on attempts for Cloud Monitoring MetricDescriptor SEND_ONCE compatibility).

Co-authored by AI Agent

…n StorageErrorTypeMapper

- Reword class Javadoc to remove HLD acronym.
- Delegate StatusRuntimeException and StatusException directly to mapGrpcStatus.
- Cap cause-chain traversal depth (MAX_CAUSE_DEPTH = 20) across mapGrpcStatus and mapThrowable to guard against multi-node cause cycles (A -> B -> A).

[Generated-by: AI]
Base automatically changed from feat/storage-metrics-context-error-mapping to main November 9, 2026 07:28
@nidhiii-27
nidhiii-27 merged commit edea395 into main Nov 11, 2026
204 checks passed
@nidhiii-27
nidhiii-27 deleted the feat/storage-metrics-context branch November 11, 2026 20:00
nidhiii-27 added a commit that referenced this pull request Nov 12, 2026
…Options (#14695)

Wires client-level metrics lifecycle and retrier operation metrics into
StorageOptions and Retrying.

- Initializes `StorageClientMetrics` provider and lifecycle management
in `StorageOptions`.
- Instruments `Retrying` to record operation attempts, durations, and
status attributes.
- Adds comprehensive unit tests (`StorageOptionsTest`,
`StorageClientMetricsTest`, `RetryingMetricsTest`).

Stacked on #14728.

---------

Co-authored-by: Dhriti07 <56169283+Dhriti07@users.noreply.github.com>
whowes pushed a commit that referenced this pull request Nov 13, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>1.97.0</summary>

##
[1.97.0](v1.96.0...v1.97.0)
(2026-11-12)


### ⚠ BREAKING CHANGES

* **shopping-merchant:** remove discontinued Merchant API v1beta
([#14942](#14942))

### Features

* **bigquery-jdbc:** adds BigQuery graph integration to DatabaseMetadata
methods
([#14930](#14930))
([950b81b](950b81b))
* **gax:** implement resumable upload session resumption
([#14677](#14677))
([24728d6](24728d6))
* **grpc-gcp:** add built-in channel_count metric for client library
pools
([#14947](#14947))
([712f043](712f043))
* **grpc-gcp:** add built-in channel_load metric for client library
pools
([#14985](#14985))
([9f87888](9f87888))
* **shopping-merchant:** remove discontinued Merchant API v1beta
([#14942](#14942))
([2947dfd](2947dfd))
* **storage:** add StorageErrorTypeMapper for standard metrics
([#14694](#14694))
([a9ac393](a9ac393))
* **storage:** add StorageMetricsContext for operation metrics state
([#14728](#14728))
([edea395](edea395))
* **storage:** wire logical operation metrics in Retrying and
StorageOptions
([#14695](#14695))
([589c66c](589c66c))
* update API sources and regenerate
([#14958](#14958))
([75944f3](75944f3))


### Bug Fixes

* **auth:** verify public/private key match with retries in mTLS
keystore loading
([#14829](#14829))
([096dbd6](096dbd6))
* **bigquery:** set QueryResultsFormat.ARROW in QueryArrow sample
([#14960](#14960))
([c98e7c3](c98e7c3))
* **bigtable:** avoid triggering per-RPC credential session fallback on
default call context
([#14961](#14961))
([eb06d2c](eb06d2c))
* **bigtable:** copy Metadata per GetClientConfiguration call
([#14950](#14950))
([278fe2f](278fe2f))
* **bigtable:** disable SwitchingChannelPool when
ChannelPoolConfiguration is empty
([#14911](#14911))
([fa24702](fa24702))
* **bigtable:** handle empty SessionPoolConfiguration in SessionPoolImpl
and PoolSizer
([#14912](#14912))
([cc7b235](cc7b235))
* **bigtable:** replace SessionPoolImpl Watchdog with per-session
closeTimeout
([#14977](#14977))
([a15acfb](a15acfb))
* **spanner-jdbc:** report database default isolation level
([#14929](#14929))
([7e7595a](7e7595a))
* **spanner:** fix PG SHOW isolation level statements
([#14904](#14904))
([bc917ed](bc917ed))


### Dependencies

* bump grpc to 1.85.1, opentelemetry to 1.67.0, and guava to 33.7.2-jre
([#14957](#14957))
([1a27a00](1a27a00))
* bump guava to 33.7.1-jre and jspecify to 1.0.1
([#14937](#14937))
([1441527](1441527))


### Documentation

* **spanner:** update CHANGELOG.md for java spanner releases
([#14935](#14935))
([956681e](956681e))
* **storage:** add Rapid Cache samples
([#14886](#14886))
([e714f62](e714f62))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
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.

3 participants