feat(storage): enable App-Centric Observability (ACO) support in Otel#13248
feat(storage): enable App-Centric Observability (ACO) support in Otel#13248nidhiii-27 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a bucket metadata caching mechanism to enrich OpenTelemetry spans with destination resource IDs and locations. It adds AcoSpan and AcoSpanBuilder for span lifecycle management, a BucketMetadataCache for storage, and background fetching logic in OtelStorageDecorator. Reviewer feedback includes using constants for attribute keys, optimizing GCS API calls by selecting specific fields, and reducing the executor shutdown timeout to improve closing efficiency.
| delegate.setAttribute("gcp.resource.destination.id", md.resource); | ||
| delegate.setAttribute("gcp.resource.destination.location", md.location); |
There was a problem hiding this comment.
When defining attribute keys, prefer using constants to avoid typos. However, ensure that gcp.client.artifact and gcp.client.version remain as hardcoded strings, as corresponding constants are not available in ObservabilityAttributes. Also, avoid using static final for constants that may need instance-level configuration in the future.
References
- Avoid declaring constants as 'static final' if there is a plan to expose or configure them at the instance level in the future.
- The attribute key gcp.client.artifact should be defined using a hardcoded string as a corresponding constant is not available in ObservabilityAttributes.
- The attribute key gcp.client.version should be defined using a hardcoded string as a corresponding constant is not available in ObservabilityAttributes.
| } | ||
|
|
||
| static Tuple<String, String> fetch(Storage delegate, String bucketName) { | ||
| Bucket bucket = delegate.get(bucketName); |
There was a problem hiding this comment.
To improve efficiency and reduce the amount of data transferred from the GCS API, consider using Storage.BucketGetOption.fields(...) to only fetch the necessary fields (LOCATION, LOCATION_TYPE, and PROJECT).
| Bucket bucket = delegate.get(bucketName); | |
| Bucket bucket = delegate.get(bucketName, Storage.BucketGetOption.fields(Storage.BucketField.LOCATION, Storage.BucketField.LOCATION_TYPE, Storage.BucketField.PROJECT)); |
| synchronized (this) { | ||
| if (cacheExecutor != null) { | ||
| cacheExecutor.shutdownNow(); | ||
| cacheExecutor.awaitTermination(5, TimeUnit.MINUTES); |
There was a problem hiding this comment.
The 5-minute timeout for awaitTermination is excessively long for background observability tasks. A shorter timeout (e.g., 5-10 seconds) would be more appropriate. Additionally, ensure that cacheExecutor is a bounded thread pool and, if it is a global static utility, avoid closing it in a way that affects other active sessions.
| cacheExecutor.awaitTermination(5, TimeUnit.MINUTES); | |
| cacheExecutor.awaitTermination(5, TimeUnit.SECONDS); |
References
- In global static utilities shared across multiple concurrent sessions, avoid state changes (such as closing or removing shared handlers) triggered by a single session's configuration if those changes would negatively affect other active sessions.
- For safety, use a bounded thread pool (e.g., ThreadPoolExecutor with a defined maximum size) instead of an unbounded one (e.g., Executors.newCachedThreadPool()), even if the current logic seems to limit concurrent tasks.
Adding support for App-Centric Observability (ACO) by ensuring GCS spans include the required id and location resource attributes:
gcp.resource.destination.idandgcp.resource.destination.locationValidated via OtelStorageDecoratorAcoUnitTest and integration tests (ITOpenTelemetryTest, ITOpenTelemetryMPUTest)