Skip to content

Commit 7fee252

Browse files
committed
feat(observability): simplify options resolver to tracing-only
1 parent d7994bd commit 7fee252

5 files changed

Lines changed: 63 additions & 82 deletions

File tree

packages/google-api-core/google/api_core/observability/options.py

Lines changed: 25 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
"""Observability environment variable and client options resolution helpers."""
22

33
import os
4-
import warnings
5-
from typing import Any, Dict, List, Optional, Union
4+
from typing import Any, Dict, Optional, Union
65

76
# Allowed truthy and falsy patterns for environment variables
87
_TRUTHY_VALUES = ("y", "yes", "t", "true", "on", "1")
@@ -66,15 +65,30 @@ def _get_env_bool_with_dev_fallback(name: str) -> Optional[bool]:
6665

6766

6867
def is_signal_enabled(
69-
service_name: str,
7068
signal_type: str,
7169
client_options: Optional[Union[Dict[str, Any], Any]] = None,
7270
default: bool = False,
73-
legacy_vars: Optional[List[str]] = None,
7471
) -> bool:
75-
"""Determines if a telemetry signal is enabled."""
76-
service_upper = service_name.upper().replace("-", "_")
77-
signal_upper = signal_type.upper()
72+
"""Determines if a telemetry signal is enabled.
73+
74+
Resolves settings in the following order of precedence:
75+
1. Programmatic overrides in client_options (checks tracer_provider)
76+
2. Language-wide Environment Variable: GOOGLE_CLOUD_PYTHON_TRACING_ENABLED
77+
(natively checks for an EXPERIMENTAL prefix variant first)
78+
3. Default fallback
79+
80+
Args:
81+
signal_type: The signal type: must be 'tracing'.
82+
client_options: A dictionary or object representing client configuration.
83+
default: Fallback boolean if no options or env variables match.
84+
85+
Returns:
86+
bool: True if the signal is resolved to enabled, False otherwise.
87+
"""
88+
if signal_type != "tracing":
89+
raise ValueError(
90+
f"Invalid signal_type: {signal_type!r}. Only 'tracing' is supported."
91+
)
7892

7993
# 1. Resolve Programmatic Options First
8094
if client_options is not None:
@@ -83,51 +97,14 @@ def is_signal_enabled(
8397
if isinstance(client_options, dict)
8498
else getattr(client_options, "__dict__", {})
8599
)
86-
option_key = f"enable_{signal_type.lower()}"
87-
provider_key = f"{signal_type.rstrip('s').lower()}_provider"
88100

89-
if options_dict.get(option_key) is not None:
90-
return bool(options_dict.get(option_key))
91-
if options_dict.get(provider_key) is not None:
101+
if options_dict.get("tracer_provider") is not None:
92102
return True
93103

94-
# 2. Language & Service-specific
95-
val = _get_env_bool_with_dev_fallback(
96-
f"GOOGLE_CLOUD_PYTHON_{service_upper}_{signal_upper}_ENABLED"
97-
)
98-
if val is not None:
99-
return val
100-
101-
# 3. Language-wide Global
102-
val = _get_env_bool_with_dev_fallback(f"GOOGLE_CLOUD_PYTHON_{signal_upper}_ENABLED")
103-
if val is not None:
104-
return val
105-
106-
# 4. Cross-language Service-specific
107-
val = _get_env_bool_with_dev_fallback(
108-
f"GOOGLE_CLOUD_{service_upper}_{signal_upper}_ENABLED"
109-
)
110-
if val is not None:
111-
return val
112-
113-
# 5. Cross-language Global
114-
val = _get_env_bool_with_dev_fallback(f"GOOGLE_CLOUD_{signal_upper}_ENABLED")
104+
# 2. Check Language-Wide Environment Variable
105+
val = _get_env_bool_with_dev_fallback("GOOGLE_CLOUD_PYTHON_TRACING_ENABLED")
115106
if val is not None:
116107
return val
117108

118-
# 6. Legacy Variables
119-
if legacy_vars:
120-
for legacy_var in legacy_vars:
121-
val = _get_env_bool(legacy_var)
122-
if val is not None:
123-
warnings.warn(
124-
f"Environment variable {legacy_var!r} is deprecated and will be removed "
125-
"in a future release. Please migrate to the standardized "
126-
f"GOOGLE_CLOUD_PYTHON_{service_upper}_{signal_upper}_ENABLED instead.",
127-
DeprecationWarning,
128-
stacklevel=2,
129-
)
130-
return val
131-
132-
# 7. Default Fallback
109+
# 3. Default Fallback
133110
return default

packages/google-api-core/pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ dependencies = [
4949
"proto-plus >= 1.25.0, < 2.0.0; python_version >= '3.13'",
5050
"google-auth >= 2.14.1, < 3.0.0",
5151
"requests >= 2.33.0, < 3.0.0",
52-
"opentelemetry-api >= 1.1.0, < 2.0.0",
52+
"opentelemetry-api >= 1.27.0, < 2.0.0",
5353
]
5454
dynamic = ["version"]
5555

@@ -95,4 +95,6 @@ filterwarnings = [
9595
"ignore:.*custom tp_new.*in Python 3.14:DeprecationWarning",
9696
# Remove once https://github.com/grpc/grpc/issues/35086 is fixed (and version newer than 1.60.0 is published)
9797
"ignore:There is no current event loop:DeprecationWarning",
98+
# Ignore external OpenTelemetry/importlib.metadata SelectableGroups warning
99+
"ignore:.*SelectableGroups dict interface is deprecated:DeprecationWarning",
98100
]

packages/google-api-core/testing/constraints-3.10.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ requests==2.33.0
1212
grpcio==1.41.0
1313
grpcio-status==1.41.0
1414
proto-plus==1.24.0
15-
opentelemetry-api==1.1.0
15+
opentelemetry-api==1.27.0

packages/google-api-core/testing/constraints-async-rest-3.10.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ grpcio==1.41.0
1313
grpcio-status==1.41.0
1414
proto-plus==1.24.0
1515
aiohttp==3.13.4
16-
opentelemetry-api==1.1.0
16+
opentelemetry-api==1.27.0

packages/google-api-core/tests/unit/observability/test_options.py

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -70,65 +70,67 @@ def test_get_env_bool(monkeypatch):
7070

7171

7272
@pytest.mark.parametrize(
73-
"env_vars, client_options, default_val, expected",
73+
"signal_type, env_vars, client_options, default_val, expected",
7474
[
7575
# Default fallback tests
76-
({}, None, False, False),
77-
({}, None, True, True),
78-
# Service-specific env var
79-
({"GOOGLE_CLOUD_PYTHON_TRANSLATE_TRACES_ENABLED": True}, None, False, True),
80-
({"GOOGLE_CLOUD_PYTHON_TRANSLATE_TRACES_ENABLED": False}, None, True, False),
76+
("tracing", {}, None, False, False),
77+
("tracing", {}, None, True, True),
78+
# Global env var
79+
("tracing", {"GOOGLE_CLOUD_PYTHON_TRACING_ENABLED": True}, None, False, True),
80+
("tracing", {"GOOGLE_CLOUD_PYTHON_TRACING_ENABLED": False}, None, True, False),
8181
# Experimental fallback
8282
(
83-
{"GOOGLE_CLOUD_EXPERIMENTAL_PYTHON_TRANSLATE_TRACES_ENABLED": True},
83+
"tracing",
84+
{"GOOGLE_CLOUD_EXPERIMENTAL_PYTHON_TRACING_ENABLED": True},
8485
None,
8586
False,
8687
True,
8788
),
88-
# Precedence: Service specific overrides global
8989
(
90-
{
91-
"GOOGLE_CLOUD_PYTHON_TRACES_ENABLED": True,
92-
"GOOGLE_CLOUD_PYTHON_TRANSLATE_TRACES_ENABLED": False,
93-
},
90+
"tracing",
91+
{"GOOGLE_CLOUD_EXPERIMENTAL_PYTHON_TRACING_ENABLED": False},
9492
None,
95-
False,
93+
True,
9694
False,
9795
),
96+
# Implicit opt-in with provider
9897
(
99-
{
100-
"GOOGLE_CLOUD_PYTHON_TRACES_ENABLED": False,
101-
"GOOGLE_CLOUD_PYTHON_TRANSLATE_TRACES_ENABLED": True,
102-
},
103-
None,
98+
"tracing",
99+
{"GOOGLE_CLOUD_PYTHON_TRACING_ENABLED": False},
100+
{"tracer_provider": object()},
104101
False,
105102
True,
106103
),
107-
# Precedence: Client options override env vars
104+
# Programmatic boolean flags are NOT supported (should default/fallback)
108105
(
109-
{"GOOGLE_CLOUD_PYTHON_TRANSLATE_TRACES_ENABLED": False},
106+
"tracing",
107+
{"GOOGLE_CLOUD_PYTHON_TRACING_ENABLED": False},
110108
{"enable_traces": True},
111109
False,
112-
True,
110+
False,
111+
),
112+
(
113+
"tracing",
114+
{"GOOGLE_CLOUD_PYTHON_TRACING_ENABLED": False},
115+
{"enable_tracing": True},
116+
False,
117+
False,
113118
),
114119
],
115120
)
116-
def test_is_signal_enabled(env_vars, client_options, default_val, expected):
121+
def test_is_signal_enabled(
122+
signal_type, env_vars, client_options, default_val, expected
123+
):
117124
# Setup environment variables using our test overrides
118125
for k, v in env_vars.items():
119126
set_test_env_override(k, v)
120127

121128
result = options.is_signal_enabled(
122-
"translate", "traces", client_options=client_options, default=default_val
129+
signal_type, client_options=client_options, default=default_val
123130
)
124131
assert result is expected
125132

126133

127-
def test_legacy_var_with_warning():
128-
set_test_env_override("LEGACY_TRACE_VAR", True)
129-
130-
with pytest.warns(DeprecationWarning, match="LEGACY_TRACE_VAR"):
131-
result = options.is_signal_enabled(
132-
"translate", "traces", legacy_vars=["LEGACY_TRACE_VAR"]
133-
)
134-
assert result is True
134+
def test_is_signal_enabled_invalid_signal():
135+
with pytest.raises(ValueError, match="Only 'tracing' is supported"):
136+
options.is_signal_enabled("traces")

0 commit comments

Comments
 (0)