Skip to content

Commit e4a207d

Browse files
authored
chore(storage): support DISABLE_GCS_PYTHON_CLIENT_OTEL_BUCKET_METADATA environment variable flag (#17248)
This PR introduces the `DISABLE_GCS_PYTHON_CLIENT_OTEL_BUCKET_METADATA` environment flag to dynamically disable injecting Cloud Storage bucket metadata destination attributes (`gcp.resource.destination.id` and `gcp.resource.destination.location`) inside OTel spans.
1 parent 72c7a27 commit e4a207d

5 files changed

Lines changed: 78 additions & 0 deletions

File tree

packages/google-cloud-storage/google/cloud/storage/_helpers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
from google.cloud.storage._opentelemetry_tracing import (
3636
create_trace_span as _base_create_trace_span,
37+
_is_bucket_metadata_disabled,
3738
)
3839
from google.cloud.storage.constants import _DEFAULT_TIMEOUT
3940
from google.cloud.storage.retry import (
@@ -156,6 +157,7 @@ def create_trace_span_helper(client, bucket_name, name, attributes=None, **kwarg
156157
and client
157158
and hasattr(client, "_bucket_metadata_cache")
158159
and client._bucket_metadata_cache
160+
and not _is_bucket_metadata_disabled()
159161
):
160162
try:
161163
if name in (

packages/google-cloud-storage/google/cloud/storage/_http.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
HAS_OPENTELEMETRY,
2828
create_trace_span,
2929
enable_otel_traces,
30+
_is_bucket_metadata_disabled,
3031
)
3132

3233
logger = logging.getLogger(__name__)
@@ -88,6 +89,7 @@ def api_request(self, *args, **kwargs):
8889
and enable_otel_traces
8990
and hasattr(client, "_bucket_metadata_cache")
9091
and client._bucket_metadata_cache
92+
and not _is_bucket_metadata_disabled()
9193
):
9294
path = kwargs.get("path") or ""
9395
match = re.search(r"/b/([^/?#]+)", path)

packages/google-cloud-storage/google/cloud/storage/_opentelemetry_tracing.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
ENABLE_OTEL_TRACES_ENV_VAR = "ENABLE_GCS_PYTHON_CLIENT_OTEL_TRACES"
2929
_DEFAULT_ENABLE_OTEL_TRACES_VALUE = False
30+
DISABLE_BUCKET_MD_ENV_VAR = "DISABLE_GCS_PYTHON_CLIENT_OTEL_BUCKET_METADATA"
3031

3132

3233
def _parse_bool_env(name: str, default: bool = False) -> bool:
@@ -36,11 +37,16 @@ def _parse_bool_env(name: str, default: bool = False) -> bool:
3637
return str(val).strip().lower() in {"1", "true", "yes", "on"}
3738

3839

40+
def _is_bucket_metadata_disabled() -> bool:
41+
return _parse_bool_env(DISABLE_BUCKET_MD_ENV_VAR, False)
42+
43+
3944
enable_otel_traces = _parse_bool_env(
4045
ENABLE_OTEL_TRACES_ENV_VAR, _DEFAULT_ENABLE_OTEL_TRACES_VALUE
4146
)
4247
logger = logging.getLogger(__name__)
4348

49+
4450
try:
4551
from opentelemetry import trace
4652

packages/google-cloud-storage/tests/system/test_aco_observability.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,3 +549,40 @@ def monitored_update(*args, **kwargs):
549549
assert attrs["gcp.resource.destination.location"] == "global"
550550
finally:
551551
storage_client._bucket_metadata_cache.update_cache = original_update
552+
553+
554+
@pytest.mark.parametrize("env_value", ["true", "1", "yes", "on"])
555+
def test_disable_bucket_md_env_flag(
556+
storage_client, exporter, buckets_to_delete, monkeypatch, env_value
557+
):
558+
"""Verifies that setting DISABLE_GCS_PYTHON_CLIENT_OTEL_BUCKET_METADATA to a truthy value disables GCS
559+
destination annotations, even on cache hits."""
560+
# Clear cache and OTel exporter logs
561+
storage_client._bucket_metadata_cache.clear()
562+
exporter.clear()
563+
564+
bucket_name = _helpers.unique_name("aco-disable")
565+
bucket = storage_client.bucket(bucket_name)
566+
storage_client.create_bucket(bucket)
567+
buckets_to_delete.append(bucket)
568+
569+
blob_name = "test_blob.txt"
570+
blob = bucket.blob(blob_name)
571+
blob.upload_from_string("hello")
572+
573+
# Warm cache directly via GCS creation warming (client.create_bucket already primes the cache)
574+
assert storage_client._bucket_metadata_cache.get(bucket_name) is not None
575+
576+
# Enable the DISABLE_GCS_PYTHON_CLIENT_OTEL_BUCKET_METADATA environment variable using monkeypatch
577+
monkeypatch.setenv("DISABLE_GCS_PYTHON_CLIENT_OTEL_BUCKET_METADATA", env_value)
578+
579+
# Download (normally would be a cache hit with GCS annotations)
580+
blob.download_as_bytes()
581+
582+
# Verify that ACO attributes are NOT present in the OTel span!
583+
spans = exporter.get_finished_spans()
584+
dl_spans = [s for s in spans if s.name == "Storage.Blob.downloadAsBytes"]
585+
assert len(dl_spans) == 1
586+
attrs = dl_spans[0].attributes
587+
assert "gcp.resource.destination.id" not in attrs
588+
assert "gcp.resource.destination.location" not in attrs

packages/google-cloud-storage/tests/unit/test__opentelemetry_tracing.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,34 @@ def test__parse_bool_env(monkeypatch, env_value, default, expected):
321321

322322
result = _opentelemetry_tracing._parse_bool_env(env_var_name, default)
323323
assert result is expected
324+
325+
326+
@pytest.mark.parametrize(
327+
"env_value, expected",
328+
[
329+
# Test default (not set)
330+
(None, False),
331+
# Test truthy values
332+
("true", True),
333+
("1", True),
334+
("yes", True),
335+
("on", True),
336+
("TRUE", True),
337+
(" Yes ", True),
338+
# Test falsy values
339+
("false", False),
340+
("0", False),
341+
("no", False),
342+
("off", False),
343+
("any_other_string", False),
344+
("", False),
345+
],
346+
)
347+
def test__is_bucket_metadata_disabled(monkeypatch, env_value, expected):
348+
env_var_name = "DISABLE_GCS_PYTHON_CLIENT_OTEL_BUCKET_METADATA"
349+
if env_value is not None:
350+
monkeypatch.setenv(env_var_name, str(env_value))
351+
else:
352+
monkeypatch.delenv(env_var_name, raising=False)
353+
354+
assert _opentelemetry_tracing._is_bucket_metadata_disabled() is expected

0 commit comments

Comments
 (0)