Emit configuration span after logfire.configure()#1904
Conversation
Adds a "Logfire configured" log span at the end of `LogfireConfig._initialize` containing the SDK version, installed package versions, and the active configuration (with `token` and `api_key` redacted). Useful for diagnosing "why is my data not showing up" issues from a single span in the UI.
Deploying logfire-docs with
|
| Latest commit: |
3ea2771
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://5c2a85db.logfire-docs.pages.dev |
| Branch Preview URL: | https://emit-configuration-span.logfire-docs.pages.dev |
|
I believe it is useful to query this data for a variety of reasons — debugging logfire configuration, knowing when services were started, etc. Obviously better if you could be confident it was never sampled out but I'd prefer to have these spans and have it "misbehave" (i.e., just sometimes be missing these spans) if you have sampling enabled. Not sure why it would be incompatible with other backends if it uses otel; obviously sending data out-of-band using another API is incompatible with other backends. I feel like making it opt-out of this behavior (rather than opt-in) is reasonable, but making other out-of-band telemetry opt-out rather than opt-in seems harder to justify.
We have the
Presumably plays poorly but I feel like it's better to have than not. We could make it possible to opt out but I'd suggest we have it opt-in by default. |
|
If we go forward with this please lets cherry pick information from |
Add `AdvancedOptions.emit_configuration_span` flag (default `False`) and replace the dynamic config-dict serialization with an explicit allowlist of non-sensitive flags. Identity and secrets - token, api_key, service_name, service_version, environment, base_url - are never sent.
…N` env var Adds an `emit_configuration_span` ConfigParam so the flag can be set via env var or pyproject.toml without passing an explicit `advanced=` argument - useful for enabling on demo apps without touching the configure() call.
Promote the flag from `AdvancedOptions` to a first-class `configure()` keyword argument plus a `_LogfireConfigData` field, matching the pattern used by `distributed_tracing`. The `LOGFIRE_EMIT_CONFIGURATION_SPAN` env var now drives the field directly instead of going through `AdvancedOptions`.
Summary
Logfire configuredlog span emitted at the end ofLogfireConfig._initialize, after providers/exporters are wired up but outside thesuppress_instrumentation()block so it actually gets exported.logfire_version,package_versions(fromcollect_package_info()), andlogfire_config(a shallow dict of_LogfireConfigDatafields).tokenandapi_keyare redacted to[REDACTED]; the scrubber catches anything else by default.collect_package_infowas defined and tested but never actually emitted anywhere (a commented-out resource attribute inconfig.pyhints at an earlier abandoned design).Implementation notes
dataclasses.asdict(self)because the latterdeepcopys nested values, andadditional_span_processors/log_record_processorscarry_thread.lockobjects that fail to pickle._disable_configured_spanfixture replaces_emit_configuration_spanwith a no-op so existing snapshot tests aren't disturbed and trace/span IDs fromIncrementalIdGeneratordon't shift. Areal_emit_configuration_spanfixture exposes the original for the dedicatedtest_configuration_span_emittedtest.Test plan
make lint typecheckcleantest_configuration_span_emittedcovers attributes and token redactiontest_exit_open_spans_exports_suspended_generator_span_before_shutdownto expect the new spantest_configure.py/test_cli.pycaused by a stale local credentials file, unrelated to this change)AI Disclaimer
This PR was developed with the assistance of either Claude or Codex. I've reviewed and verified the changes.