Skip to content

Commit

Permalink
Support 'if-token-present' for env var 'LOGFIRE_SEND_TO_LOGFIRE' (#…
Browse files Browse the repository at this point in the history
…488)

Co-authored-by: Alex Hall <[email protected]>
  • Loading branch information
sydney-runkle and alexmojaki authored Oct 11, 2024
1 parent 450298f commit aa65f2d
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 9 deletions.
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
11 changes: 6 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ We'd love anyone interested to contribute to the Logfire SDK and documentation.

1. Fork and clone the repository
2. [Install uv](https://docs.astral.sh/uv/getting-started/installation/)
3. Run `make install` to install dependencies
4. Run `make test` to run unit tests
5. Run `make format` to format code
6. Run `make lint` to lint code
7. run `make docs` to build docs and `make docs-serve` to serve docs locally
3. [Install pre-commit](https://pre-commit.com/#install)
4. Run `make install` to install dependencies
5. Run `make test` to run unit tests
6. Run `make format` to format code
7. Run `make lint` to lint code
8. run `make docs` to build docs and `make docs-serve` to serve docs locally

You're now set up to start contributing!
2 changes: 1 addition & 1 deletion logfire-api/logfire_api/_internal/config.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class _LogfireConfigData:
advanced: AdvancedOptions

class LogfireConfig(_LogfireConfigData):
def __init__(self, send_to_logfire: bool | None = None, token: str | None = None, service_name: str | None = None, service_version: str | None = None, console: ConsoleOptions | Literal[False] | None = None, config_dir: Path | None = None, data_dir: Path | None = None, additional_span_processors: Sequence[SpanProcessor] | None = None, metrics: MetricsOptions | Literal[False] | None = None, scrubbing: ScrubbingOptions | Literal[False] | None = None, inspect_arguments: bool | None = None, sampling: SamplingOptions | None = None, code_source: CodeSource | None = None, advanced: AdvancedOptions | None = None) -> None:
def __init__(self, send_to_logfire: bool | Literal['if-token-present'] | None = None, token: str | None = None, service_name: str | None = None, service_version: str | None = None, console: ConsoleOptions | Literal[False] | None = None, config_dir: Path | None = None, data_dir: Path | None = None, additional_span_processors: Sequence[SpanProcessor] | None = None, metrics: MetricsOptions | Literal[False] | None = None, scrubbing: ScrubbingOptions | Literal[False] | None = None, inspect_arguments: bool | None = None, sampling: SamplingOptions | None = None, code_source: CodeSource | None = None, advanced: AdvancedOptions | None = None) -> None:
"""Create a new LogfireConfig.
Users should never need to call this directly, instead use `logfire.configure`.
Expand Down
2 changes: 1 addition & 1 deletion logfire/_internal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ def _load_configuration(
class LogfireConfig(_LogfireConfigData):
def __init__(
self,
send_to_logfire: bool | None = None,
send_to_logfire: bool | Literal['if-token-present'] | None = None,
token: str | None = None,
service_name: str | None = None,
service_version: str | None = None,
Expand Down
11 changes: 9 additions & 2 deletions logfire/_internal/config_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dataclasses import dataclass
from functools import cached_property
from pathlib import Path
from typing import Any, Callable, Literal, Set, TypeVar
from typing import Any, Callable, Literal, Set, TypeVar, Union

from opentelemetry.sdk.environment_variables import OTEL_SERVICE_NAME
from typing_extensions import get_args, get_origin
Expand Down Expand Up @@ -53,7 +53,7 @@ class _DefaultCallback:
"""When running under pytest, don't send spans to Logfire by default."""

# fmt: off
SEND_TO_LOGFIRE = ConfigParam(env_vars=['LOGFIRE_SEND_TO_LOGFIRE'], allow_file_config=True, default=_send_to_logfire_default, tp=bool)
SEND_TO_LOGFIRE = ConfigParam(env_vars=['LOGFIRE_SEND_TO_LOGFIRE'], allow_file_config=True, default=_send_to_logfire_default, tp=Union[bool, Literal['if-token-present']])
"""Whether to send spans to Logfire."""
TOKEN = ConfigParam(env_vars=['LOGFIRE_TOKEN'])
"""Token for the Logfire API."""
Expand Down Expand Up @@ -183,6 +183,13 @@ def _cast(self, value: Any, name: str, tp: type[T]) -> T | None:
return value
if get_origin(tp) is Literal:
return _check_literal(value, name, tp)
if get_origin(tp) is Union:
for arg in get_args(tp):
try:
return self._cast(value, name, arg)
except LogfireConfigError:
pass
raise LogfireConfigError(f'Expected {name} to be an instance of one of {get_args(tp)}, got {value!r}')
if tp is bool:
return _check_bool(value, name) # type: ignore
if tp is float:
Expand Down
20 changes: 20 additions & 0 deletions tests/test_configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,14 @@ def test_read_config_from_environment_variables() -> None:
):
fresh_pydantic_plugin()

with patch.dict(os.environ, {'LOGFIRE_SEND_TO_LOGFIRE': 'not-valid'}):
with inline_snapshot.extra.raises(
snapshot(
"LogfireConfigError: Expected send_to_logfire to be an instance of one of (<class 'bool'>, typing.Literal['if-token-present']), got 'not-valid'"
)
):
configure()

assert fresh_pydantic_plugin().include == set()
with patch.dict(os.environ, {'LOGFIRE_PYDANTIC_PLUGIN_INCLUDE': 'test'}):
assert fresh_pydantic_plugin().include == {'test'}
Expand Down Expand Up @@ -1254,6 +1262,18 @@ def test_send_to_logfire_if_token_present_empty() -> None:
del os.environ['LOGFIRE_TOKEN']


def test_send_to_logfire_if_token_present_empty_via_env_var() -> None:
with patch.dict(
os.environ,
{'LOGFIRE_TOKEN': '', 'LOGFIRE_SEND_TO_LOGFIRE': 'if-token-present'},
), mock.patch(
'logfire._internal.config.Confirm.ask',
side_effect=RuntimeError,
), requests_mock.Mocker() as requests_mocker:
configure(console=False)
assert len(requests_mocker.request_history) == 0


def wait_for_check_token_thread():
for thread in threading.enumerate():
if thread.name == 'check_logfire_token': # pragma: no cover
Expand Down

0 comments on commit aa65f2d

Please sign in to comment.