Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
24 changes: 24 additions & 0 deletions logfire/_internal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,30 @@ def fix_pid(): # pragma: no cover

self._ensure_flush_after_aws_lambda()

self._emit_configuration_span()

def _emit_configuration_span(self) -> None:
"""Emit a span describing the active Logfire configuration and installed packages."""
from logfire._internal.collect_system_info import collect_package_info
from logfire._internal.main import Logfire

with handle_internal_errors:
config_dict: dict[str, Any] = {}
for f in dataclasses.fields(_LogfireConfigData):
value = getattr(self, f.name, None)
if f.name in ('token', 'api_key') and value:
config_dict[f.name] = '[REDACTED]'
elif dataclasses.is_dataclass(value) and not isinstance(value, type):
config_dict[f.name] = {sf.name: getattr(value, sf.name) for sf in dataclasses.fields(value)}
else:
config_dict[f.name] = value
Logfire(config=self).info(
'Logfire configured',
logfire_version=VERSION,
logfire_config=config_dict,
package_versions=collect_package_info(),
)

def force_flush(self, timeout_millis: int = 30_000) -> bool:
"""Force flush all spans and metrics.

Expand Down
32 changes: 31 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,38 @@ def config_kwargs(
)


_original_emit_configuration_span: Any = None


@pytest.fixture(autouse=True)
def _disable_configured_span(monkeypatch: pytest.MonkeyPatch) -> None: # pyright: ignore[reportUnusedFunction]
"""Skip the "Logfire configured" span in tests.

The span is useful in production but adds noise to nearly every snapshot test
and would shift trace/span ids when using `IncrementalIdGenerator`.
A dedicated test in `test_configure.py` exercises the emit path explicitly.
"""
from logfire._internal.config import LogfireConfig

global _original_emit_configuration_span
if _original_emit_configuration_span is None:
_original_emit_configuration_span = LogfireConfig._emit_configuration_span # pyright: ignore[reportPrivateUsage]

def _no_op(self: LogfireConfig) -> None:
pass

monkeypatch.setattr(LogfireConfig, '_emit_configuration_span', _no_op)


@pytest.fixture
def real_emit_configuration_span() -> Any:
"""Return the unpatched `_emit_configuration_span` so a single test can exercise it."""
assert _original_emit_configuration_span is not None
return _original_emit_configuration_span


@pytest.fixture(autouse=True)
def config(config_kwargs: dict[str, Any], metrics_reader: InMemoryMetricReader) -> None:
def config(_disable_configured_span: None, config_kwargs: dict[str, Any], metrics_reader: InMemoryMetricReader) -> None:
logfire.variables_clear()
configure(
**config_kwargs,
Expand Down
25 changes: 24 additions & 1 deletion tests/test_configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,29 @@ def test_configure_twice_no_warning(caplog: LogCaptureFixture):
assert not caplog.messages


def test_configuration_span_emitted(real_emit_configuration_span: Any, exporter: TestExporter):
from logfire._internal.config import GLOBAL_CONFIG

GLOBAL_CONFIG.token = 'pylf_v1_us_FAKE_TOKEN_xyz'
try:
real_emit_configuration_span(GLOBAL_CONFIG)
finally:
GLOBAL_CONFIG.token = None

spans = [
s for s in exporter.exported_spans_as_dict(parse_json_attributes=True) if s['name'] == 'Logfire configured'
]
assert len(spans) == 1
attrs = spans[0]['attributes']
assert attrs['logfire_version']
assert isinstance(attrs['package_versions'], dict)
assert 'logfire' in attrs['package_versions']
cfg = attrs['logfire_config']
assert isinstance(cfg, dict)
assert 'service_name' in cfg
assert cfg['token'] == '[REDACTED]'


def test_exit_open_spans_exports_suspended_generator_span_before_shutdown() -> None:
script_path = Path(__file__).parent / 'import_used_for_tests' / 'open_span_at_shutdown.py'

Expand All @@ -1609,7 +1632,7 @@ def test_exit_open_spans_exports_suspended_generator_span_before_shutdown() -> N
)

assert result.returncode == 0, result.stderr
assert result.stdout == 'open span at shutdown\n'
assert result.stdout == 'Logfire configured\nopen span at shutdown\n'


def test_send_to_logfire_under_pytest():
Expand Down
Loading