Files
2026-07-13 13:22:34 +08:00

161 lines
5.3 KiB
Python

from pathlib import Path
from unittest.mock import Mock, patch
import pytest
import mlflow.telemetry.utils
from mlflow.telemetry.constant import (
CONFIG_STAGING_URL,
CONFIG_URL,
FALLBACK_UI_CONFIG,
UI_CONFIG_STAGING_URL,
UI_CONFIG_URL,
)
from mlflow.telemetry.schemas import Environment
from mlflow.telemetry.utils import (
_detect_environment,
_get_config_url,
fetch_ui_telemetry_config,
is_telemetry_disabled,
)
@pytest.mark.parametrize(
("env_var", "expected"),
[
("KAGGLE_KERNEL_RUN_TYPE", Environment.KAGGLE.value),
("COLAB_RELEASE_TAG", Environment.COLAB.value),
("AZUREML_FRAMEWORK", Environment.AZURE_ML.value),
("SAGEMAKER_APP_TYPE", Environment.SAGEMAKER_STUDIO.value),
],
)
def test_detect_environment_from_env_var(monkeypatch, env_var, expected):
monkeypatch.setenv(env_var, "some_value")
assert _detect_environment() == expected
@pytest.mark.parametrize(
("value", "expected"),
[
("demo", Environment.DEMO.value),
("staging", None),
],
)
def test_detect_environment_deployment_env(monkeypatch, value, expected):
monkeypatch.setenv("MLFLOW_DEPLOYMENT_ENV", value)
assert _detect_environment() == expected
def test_detect_environment_sagemaker_notebook(tmp_path, monkeypatch):
metadata_file = tmp_path / "resource-metadata.json"
metadata_file.write_text("{}")
with patch("mlflow.telemetry.utils.Path") as mock_path:
def path_side_effect(p):
if p == "/opt/ml/metadata/resource-metadata.json":
return metadata_file
return Path(p)
mock_path.side_effect = path_side_effect
assert _detect_environment() == Environment.SAGEMAKER_NOTEBOOK
def test_detect_environment_docker(tmp_path, monkeypatch):
dockerenv = tmp_path / ".dockerenv"
dockerenv.touch()
with patch("mlflow.telemetry.utils.Path") as mock_path:
def path_side_effect(p):
if p == "/.dockerenv":
return dockerenv
return Path(p)
mock_path.side_effect = path_side_effect
assert _detect_environment() == Environment.DOCKER
def test_detect_environment_none():
assert _detect_environment() is None
def test_is_telemetry_disabled(monkeypatch, bypass_env_check):
assert is_telemetry_disabled() is False
with monkeypatch.context() as m:
m.setenv("MLFLOW_DISABLE_TELEMETRY", "true")
assert is_telemetry_disabled() is True
assert is_telemetry_disabled() is False
with monkeypatch.context() as m:
m.setenv("DO_NOT_TRACK", "true")
assert is_telemetry_disabled() is True
def test_is_telemetry_disabled_does_not_disable_in_databricks(monkeypatch, bypass_env_check):
# Running inside DBR / model serving must not disable telemetry — events
# are routed to the workspace via _forward_to_databricks. The OSS branch
# is independently gated inside TelemetryClient._process_records.
monkeypatch.setattr(mlflow.telemetry.utils, "_IS_IN_DATABRICKS", True)
assert is_telemetry_disabled() is False
def test_get_config_url(bypass_env_check):
assert _get_config_url("1.0.0") == f"{CONFIG_URL}/1.0.0.json"
assert _get_config_url("1.0.0.rc0") == f"{CONFIG_URL}/1.0.0.rc0.json"
assert _get_config_url("1.0.0.dev0") == f"{CONFIG_STAGING_URL}/1.0.0.dev0.json"
assert _get_config_url("1.0.0+abc") is None
assert _get_config_url("1.0.0", is_ui=True) == f"{UI_CONFIG_URL}/1.0.0.json"
assert _get_config_url("1.0.0.rc0", is_ui=True) == f"{UI_CONFIG_URL}/1.0.0.rc0.json"
assert _get_config_url("1.0.0.dev0", is_ui=True) == f"{UI_CONFIG_STAGING_URL}/1.0.0.dev0.json"
assert _get_config_url("1.0.0+abc", is_ui=True) is None
def test_fetch_ui_telemetry_config_fetch_success(bypass_env_check):
mock_config = {
"mlflow_version": "3.7.1.dev0",
"disable_telemetry": False,
"rollout_percentage": 100,
"ingestion_url": "https://api.mlflow-telemetry.io/staging/log",
"disable_sdks": [],
"disable_os": [],
"disable_events": [],
"disable_ui_telemetry": False,
"disable_ui_events": ["test_event"],
"ui_rollout_percentage": 100,
}
with patch("requests.get") as mock_get:
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = mock_config
mock_get.return_value = mock_response
result = fetch_ui_telemetry_config()
assert result["disable_ui_telemetry"] is False
assert result["disable_ui_events"] == ["test_event"]
assert result["ui_rollout_percentage"] == 100
def test_fetch_ui_telemetry_config_fetch_error_fallback(bypass_env_check):
with patch("requests.get") as mock_get:
mock_response = Mock()
mock_response.status_code = 404
mock_get.return_value = mock_response
result = fetch_ui_telemetry_config()
assert result == FALLBACK_UI_CONFIG
assert result["disable_ui_telemetry"] is True
with patch("requests.get") as mock_get:
mock_get.side_effect = Exception("Network error")
result = fetch_ui_telemetry_config()
assert result == FALLBACK_UI_CONFIG
assert result["disable_ui_telemetry"] is True
assert result["disable_ui_events"] == []
assert result["ui_rollout_percentage"] == 0