Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Install otel extras in docker image and remove experimental flag setting #16412

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ COPY --from=ghcr.io/astral-sh/uv:0.5.8 /uv /uvx /bin/
# Install dependencies using a temporary mount for requirements files
RUN --mount=type=bind,source=requirements-client.txt,target=/tmp/requirements-client.txt \
--mount=type=bind,source=requirements.txt,target=/tmp/requirements.txt \
--mount=type=bind,source=requirements-otel.txt,target=/tmp/requirements-otel.txt \
--mount=type=cache,target=/root/.cache/uv \
uv pip install --system -r /tmp/requirements.txt -r /tmp/requirements-client.txt
uv pip install --system -r /tmp/requirements.txt -r /tmp/requirements-client.txt -r /tmp/requirements-otel.txt

# Install prefect from the sdist
COPY --from=python-builder /opt/prefect/dist ./dist
Expand Down
24 changes: 12 additions & 12 deletions docs/v3/develop/settings-ref.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,18 @@ API URL for Prefect Cloud. Used for authentication with Prefect Cloud.
**Supported environment variables**:
`PREFECT_CLOUD_API_URL`

### `enable_orchestration_telemetry`
Whether or not to enable orchestration telemetry.

**Type**: `boolean`

**Default**: `True`

**TOML dotted key path**: `cloud.enable_orchestration_telemetry`

**Supported environment variables**:
`PREFECT_CLOUD_ENABLE_ORCHESTRATION_TELEMETRY`

### `ui_url`
The URL of the Prefect Cloud UI. If not set, the client will attempt to infer it.

Expand Down Expand Up @@ -467,18 +479,6 @@ If `True`, warn on usage of experimental features.
**Supported environment variables**:
`PREFECT_EXPERIMENTS_WARN`, `PREFECT_EXPERIMENTAL_WARN`

### `telemetry_enabled`
Enables sending telemetry to Prefect Cloud.

**Type**: `boolean`

**Default**: `False`

**TOML dotted key path**: `experiments.telemetry_enabled`

**Supported environment variables**:
`PREFECT_EXPERIMENTS_TELEMETRY_ENABLED`

### `lineage_events_enabled`
If `True`, enables emitting lineage events. Set to `False` to disable lineage event emission.

Expand Down
18 changes: 9 additions & 9 deletions schemas/settings.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,15 @@
"title": "Api Url",
"type": "string"
},
"enable_orchestration_telemetry": {
"default": true,
"description": "Whether or not to enable orchestration telemetry.",
"supported_environment_variables": [
"PREFECT_CLOUD_ENABLE_ORCHESTRATION_TELEMETRY"
],
"title": "Enable Orchestration Telemetry",
"type": "boolean"
},
"ui_url": {
"anyOf": [
{
Expand Down Expand Up @@ -337,15 +346,6 @@
"title": "Warn",
"type": "boolean"
},
"telemetry_enabled": {
"default": false,
"description": "Enables sending telemetry to Prefect Cloud.",
"supported_environment_variables": [
"PREFECT_EXPERIMENTS_TELEMETRY_ENABLED"
],
"title": "Telemetry Enabled",
"type": "boolean"
},
"lineage_events_enabled": {
"default": false,
"description": "If `True`, enables emitting lineage events. Set to `False` to disable lineage event emission.",
Expand Down
5 changes: 5 additions & 0 deletions src/prefect/settings/models/cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ class CloudSettings(PrefectBaseSettings):
description="API URL for Prefect Cloud. Used for authentication with Prefect Cloud.",
)

enable_orchestration_telemetry: bool = Field(
default=True,
description="Whether or not to enable orchestration telemetry.",
)

ui_url: Optional[str] = Field(
default=None,
description="The URL of the Prefect Cloud UI. If not set, the client will attempt to infer it.",
Expand Down
5 changes: 0 additions & 5 deletions src/prefect/settings/models/experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ class ExperimentsSettings(PrefectBaseSettings):
),
)

telemetry_enabled: bool = Field(
default=False,
description="Enables sending telemetry to Prefect Cloud.",
)

lineage_events_enabled: bool = Field(
default=False,
description="If `True`, enables emitting lineage events. Set to `False` to disable lineage event emission.",
Expand Down
19 changes: 10 additions & 9 deletions src/prefect/telemetry/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import prefect.settings
from prefect.client.base import ServerType, determine_server_type
from prefect.logging.loggers import get_logger

logger = get_logger(__name__)

if TYPE_CHECKING:
from opentelemetry.sdk._logs import LoggerProvider
Expand All @@ -16,30 +19,28 @@ def setup_telemetry() -> (
]
):
settings = prefect.settings.get_current_settings()
if not settings.experiments.telemetry_enabled:
return None, None, None

server_type = determine_server_type()
if server_type != ServerType.CLOUD:
return None, None, None

if not settings.cloud.enable_orchestration_telemetry:
return None, None, None

if not settings.api.key:
raise ValueError(
logger.warning(
"A Prefect Cloud API key is required to enable telemetry. Please set "
"the `PREFECT_API_KEY` environment variable or authenticate with "
"Prefect Cloud via the `prefect cloud login` command."
)
return None, None, None

assert settings.api.url

# This import is here to defer importing of the `opentelemetry` packages.
try:
from .instrumentation import setup_exporters
except ImportError as exc:
raise ValueError(
"Unable to import OpenTelemetry instrumentation libraries. Please "
"ensure you have installed the `otel` extra when installing Prefect: "
"`pip install 'prefect[otel]'`"
) from exc
except ImportError:
return None, None, None

return setup_exporters(settings.api.url, settings.api.key.get_secret_value())
36 changes: 0 additions & 36 deletions tests/telemetry/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@
reset_trace_globals,
)

from prefect.settings import (
PREFECT_API_KEY,
PREFECT_API_URL,
PREFECT_EXPERIMENTS_TELEMETRY_ENABLED,
temporary_settings,
)

ACCOUNT_ID = UUID("11111111-1111-1111-1111-111111111111")
WORKSPACE_ID = UUID("22222222-2222-2222-2222-222222222222")

Expand All @@ -28,35 +21,6 @@ def telemetry_workspace_id():
return WORKSPACE_ID


@pytest.fixture
def enable_telemetry(telemetry_account_id: UUID, telemetry_workspace_id: UUID):
with temporary_settings(
{
PREFECT_API_URL: f"https://api.prefect.cloud/api/accounts/{telemetry_account_id}/workspaces/{telemetry_workspace_id}",
PREFECT_API_KEY: "my-token",
PREFECT_EXPERIMENTS_TELEMETRY_ENABLED: True,
}
):
yield


@pytest.fixture
def hosted_server_with_telemetry_enabled():
with temporary_settings(
{
PREFECT_EXPERIMENTS_TELEMETRY_ENABLED: True,
PREFECT_API_URL: "https://prefect.example.com/api",
}
):
yield


@pytest.fixture
def disable_telemetry():
with temporary_settings({PREFECT_EXPERIMENTS_TELEMETRY_ENABLED: False}):
yield


@pytest.fixture(autouse=True)
def reset_otel_globals():
yield
Expand Down
52 changes: 30 additions & 22 deletions tests/telemetry/test_instrumentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.sdk.trace import TracerProvider

from prefect.settings import (
PREFECT_API_KEY,
PREFECT_API_URL,
temporary_settings,
)
from prefect.telemetry.bootstrap import setup_telemetry
from prefect.telemetry.instrumentation import (
extract_account_and_workspace_id,
Expand All @@ -29,6 +34,17 @@ def shutdown_telemetry():
provider.shutdown()


@pytest.fixture(autouse=True)
def enable_telemetry(telemetry_account_id: UUID, telemetry_workspace_id: UUID):
with temporary_settings(
{
PREFECT_API_URL: f"https://api.prefect.cloud/api/accounts/{telemetry_account_id}/workspaces/{telemetry_workspace_id}",
PREFECT_API_KEY: "my-token",
}
):
yield


def test_extract_account_and_workspace_id_valid_url(
telemetry_account_id: UUID, telemetry_workspace_id: UUID
):
Expand Down Expand Up @@ -58,25 +74,21 @@ def test_extract_account_and_workspace_id_invalid_urls(url):
extract_account_and_workspace_id(url)


def test_telemetry_disabled(disable_telemetry):
trace_provider, meter_provider, logger_provider = setup_telemetry()

assert trace_provider is None
assert meter_provider is None
assert logger_provider is None


def test_non_cloud_server(hosted_server_with_telemetry_enabled):
trace_provider, meter_provider, logger_provider = setup_telemetry()
def test_non_cloud_server():
with temporary_settings(
{
PREFECT_API_URL: "https://prefect.example.com/api/",
PREFECT_API_KEY: "my-token",
}
):
trace_provider, meter_provider, logger_provider = setup_telemetry()

assert trace_provider is None
assert meter_provider is None
assert logger_provider is None
assert trace_provider is None
assert meter_provider is None
assert logger_provider is None


def test_trace_provider(
enable_telemetry: None, telemetry_account_id: UUID, telemetry_workspace_id: UUID
):
def test_trace_provider(telemetry_account_id: UUID, telemetry_workspace_id: UUID):
trace_provider, _, _ = setup_telemetry()

assert isinstance(trace_provider, TracerProvider)
Expand Down Expand Up @@ -106,9 +118,7 @@ def test_trace_provider(
assert trace.get_tracer_provider() == trace_provider


def test_meter_provider(
enable_telemetry: None, telemetry_account_id: UUID, telemetry_workspace_id: UUID
):
def test_meter_provider(telemetry_account_id: UUID, telemetry_workspace_id: UUID):
_, meter_provider, _ = setup_telemetry()
assert isinstance(meter_provider, MeterProvider)

Expand Down Expand Up @@ -141,9 +151,7 @@ def test_meter_provider(
assert metrics.get_meter_provider() == meter_provider


def test_logger_provider(
enable_telemetry: None, telemetry_account_id: UUID, telemetry_workspace_id: UUID
):
def test_logger_provider(telemetry_account_id: UUID, telemetry_workspace_id: UUID):
_, _, logger_provider = setup_telemetry()

assert isinstance(logger_provider, LoggerProvider)
Expand Down
2 changes: 1 addition & 1 deletion tests/telemetry/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
)


def test_add_telemetry_log_handler_with_handler(enable_telemetry):
def test_add_telemetry_log_handler_with_handler():
logger = logging.getLogger("test")
initial_handlers = list(logger.handlers)

Expand Down
2 changes: 1 addition & 1 deletion tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@
"PREFECT_CLI_PROMPT": {"test_value": True},
"PREFECT_CLI_WRAP_LINES": {"test_value": True},
"PREFECT_CLOUD_API_URL": {"test_value": "https://cloud.prefect.io"},
"PREFECT_CLOUD_ENABLE_ORCHESTRATION_TELEMETRY": {"test_value": True},
"PREFECT_CLOUD_UI_URL": {"test_value": "https://cloud.prefect.io"},
"PREFECT_DEBUG_MODE": {"test_value": True},
"PREFECT_DEFAULT_DOCKER_BUILD_NAMESPACE": {"test_value": "prefect", "legacy": True},
Expand Down Expand Up @@ -230,7 +231,6 @@
},
"PREFECT_EVENTS_WEBSOCKET_BACKFILL_PAGE_SIZE": {"test_value": 10, "legacy": True},
"PREFECT_EXPERIMENTAL_WARN": {"test_value": True, "legacy": True},
"PREFECT_EXPERIMENTS_TELEMETRY_ENABLED": {"test_value": False},
"PREFECT_EXPERIMENTS_WARN": {"test_value": True},
"PREFECT_EXPERIMENTS_LINEAGE_EVENTS_ENABLED": {"test_value": True},
"PREFECT_FLOW_DEFAULT_RETRIES": {"test_value": 10, "legacy": True},
Expand Down
Loading