From cd9b6596d1adfed86b34e83e12fe8cab0d526d22 Mon Sep 17 00:00:00 2001 From: Marcelo Trylesinski Date: Wed, 8 May 2024 13:01:12 +0200 Subject: [PATCH] Set `send_to_logfire` to `False` when running under Pytest (#154) --- logfire/_internal/config_params.py | 19 +++++++++++++++++-- tests/test_configure.py | 22 ++++++++++++++++------ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/logfire/_internal/config_params.py b/logfire/_internal/config_params.py index d687b03bc..da3604c01 100644 --- a/logfire/_internal/config_params.py +++ b/logfire/_internal/config_params.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from functools import cached_property, lru_cache from pathlib import Path -from typing import Any, Literal, Set, TypeVar +from typing import Any, Callable, Literal, Set, TypeVar from opentelemetry.sdk.environment_variables import OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_SERVICE_NAME from typing_extensions import get_args, get_origin @@ -47,10 +47,23 @@ class ConfigParam: """Type of the parameter.""" +@dataclass +class _DefaultCallback: + """A default value that is computed at runtime. + + A good example is when we want to check if we are running under pytest and set a default value based on that. + """ + + callback: Callable[[], Any] + + +_send_to_logfire_default = _DefaultCallback(lambda: 'PYTEST_CURRENT_TEST' not in os.environ) +"""When running under pytest, don't send spans to Logfire by default.""" + # fmt: off BASE_URL = ConfigParam(env_vars=['LOGFIRE_BASE_URL', OTEL_EXPORTER_OTLP_ENDPOINT], allow_file_config=True, default=LOGFIRE_BASE_URL) """Use to set the base URL of the Logfire backend.""" -SEND_TO_LOGFIRE = ConfigParam(env_vars=['LOGFIRE_SEND_TO_LOGFIRE'], allow_file_config=True, default=True, tp=bool) +SEND_TO_LOGFIRE = ConfigParam(env_vars=['LOGFIRE_SEND_TO_LOGFIRE'], allow_file_config=True, default=_send_to_logfire_default, tp=bool) """Whether to send spans to Logfire.""" TOKEN = ConfigParam(env_vars=['LOGFIRE_TOKEN']) """Token for the Logfire API.""" @@ -161,6 +174,8 @@ def load_param(self, name: str, runtime: Any = None) -> Any: if value is not None: return self._cast(value, name, param.tp) + if isinstance(param.default, _DefaultCallback): + return self._cast(param.default.callback(), name, param.tp) return self._cast(param.default, name, param.tp) @cached_property diff --git a/tests/test_configure.py b/tests/test_configure.py index 10689a343..8cbcc73cd 100644 --- a/tests/test_configure.py +++ b/tests/test_configure.py @@ -530,6 +530,7 @@ def default_span_processor(exporter: SpanExporter) -> SimpleSpanProcessor: with request_mocker: data_dir = Path(tmp_path) / 'logfire_data' logfire.configure( + send_to_logfire=True, data_dir=data_dir, token='abc', default_span_processor=default_span_processor, @@ -836,7 +837,7 @@ def test_initialize_project_use_existing_project_no_projects(tmp_dir_cwd: Path, } request_mocker.post('https://logfire-api.pydantic.dev/v1/projects/fake_org', [create_project_response]) - logfire.configure() + logfire.configure(send_to_logfire=True) assert confirm_mock.mock_calls == [ call('The project will be created in the organization "fake_org". Continue?', default=True), @@ -871,7 +872,7 @@ def test_initialize_project_use_existing_project(tmp_dir_cwd: Path, tmp_path: Pa [create_project_response], ) - logfire.configure() + logfire.configure(send_to_logfire=True) assert confirm_mock.mock_calls == [ call('Do you want to use one of your existing projects? ', default=True), @@ -928,7 +929,7 @@ def test_initialize_project_not_using_existing_project( [create_project_response], ) - logfire.configure() + logfire.configure(send_to_logfire=True) assert confirm_mock.mock_calls == [ call('Do you want to use one of your existing projects? ', default=True), @@ -968,7 +969,7 @@ def test_initialize_project_not_confirming_organization(tmp_path: Path) -> None: ) with pytest.raises(SystemExit): - logfire.configure(data_dir=tmp_path) + logfire.configure(data_dir=tmp_path, send_to_logfire=True) assert confirm_mock.mock_calls == [ call('Do you want to use one of your existing projects? ', default=True), @@ -1045,7 +1046,7 @@ def test_initialize_project_create_project(tmp_dir_cwd: Path, tmp_path: Path, ca ], ) - logfire.configure() + logfire.configure(send_to_logfire=True) for request in request_mocker.request_history: assert request.headers['Authorization'] == 'fake_user_token' @@ -1128,7 +1129,7 @@ def test_initialize_project_create_project_default_organization(tmp_dir_cwd: Pat [create_project_response], ) - logfire.configure() + logfire.configure(send_to_logfire=True) assert prompt_mock.mock_calls == [ call( @@ -1278,3 +1279,12 @@ def test_initialize_credentials_from_token_unhealthy(): def test_configure_twice_no_warning(caplog: LogCaptureFixture): logfire.configure(send_to_logfire=False) assert not caplog.messages + + +def test_send_to_logfire_under_pytest(): + """ + Test that the `send_to_logfire` parameter is set to False when running under pytest. + """ + assert 'PYTEST_CURRENT_TEST' in os.environ + logfire.configure() + assert GLOBAL_CONFIG.send_to_logfire is False