feat: surface X-Logfire-Warning header#1906
Merged
Merged
Conversation
Deploying logfire-docs with
|
| Latest commit: |
ee581a9
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a713b4fc.logfire-docs.pages.dev |
| Branch Preview URL: | https://add-server-response-headers.logfire-docs.pages.dev |
adriangb
added a commit
that referenced
this pull request
May 5, 2026
Per review (#1905#discussion_r3189043209), the X-Logfire-Warning / X-Logfire-Error response-hook handling is logically independent from the X-Logfire-Telemetry request header — they just happened to be introduced together. Moved that code (plus its exceptions, install calls, and tests) to a separate PR (#1906) so each can be reviewed and landed on its own. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
alexmojaki
reviewed
May 6, 2026
Contributor
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="logfire/_internal/config.py">
<violation number="1" location="logfire/_internal/config.py:1333">
P2: `_lazy_init_variable_provider` (line 1462) creates a `LogfireRemoteVariableProvider` without passing `transport_response_hook`, so lazily-initialized providers won't surface server warning/error headers. Add `transport_response_hook=self.advanced.transport_response_hook` there as well.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Contributor
There was a problem hiding this comment.
2 issues found across 6 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="logfire/_internal/config.py">
<violation number="1" location="logfire/_internal/config.py:222">
P3: The new callback example uses an undefined variable (`response`) instead of the `helper` parameter.</violation>
</file>
<file name="logfire/_internal/server_response.py">
<violation number="1" location="logfire/_internal/server_response.py:42">
P2: Use an explicit `None` check for `hook`; truthiness can skip valid custom callbacks and unexpectedly run the default hook.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Contributor
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="logfire/types.py">
<violation number="1" location="logfire/types.py:291">
P1: `default_hook()` no longer processes `X-Logfire-Error`, so server-signaled hard failures are ignored.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Adds a `requests` response hook that the SDK installs on every Logfire-bound HTTP session (OTLP exporters, token validation, CRUD client, variables provider, CLI). The hook reads two custom headers the server attaches to responses: * `X-Logfire-Warning` -> `warnings.warn(..., LogfireServerWarning)`. Python's default filter dedupes identical messages within a process, so a chatty server only warns once. * `X-Logfire-Error` -> raises `LogfireServerError`. OTLP/variables paths already swallow exceptions from their HTTP calls; CRUD/CLI propagate the error to the user. This gives the backend an out-of-band channel to deprecate endpoints or signal hard failures without piggy-backing on response bodies. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lets users intercept every Logfire API response (OTLP exports, credential init, variables provider). Default keeps the existing X-Logfire-Warning / X-Logfire-Error handling; pass `lambda response: None` to opt out, or compose around `process_logfire_response_headers`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The example references `logfire`/`my_metric` without imports, which test_docs runs through pytest-examples and trips on. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`_lazy_init_variable_provider` was constructing `LogfireRemoteVariableProvider` without the configured hook, so providers spun up via the lazy path bypassed the user-supplied response handling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop LogfireServerError and X-Logfire-Error handling; default hook now only emits LogfireServerWarning from X-Logfire-Warning. Also fixes cubic review comments: explicit None check on the hook callback, and fix the docstring example to use helper.response.status_code. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
adriangb
added a commit
that referenced
this pull request
May 13, 2026
Per review (#1905#discussion_r3189043209), the X-Logfire-Warning / X-Logfire-Error response-hook handling is logically independent from the X-Logfire-Telemetry request header — they just happened to be introduced together. Moved that code (plus its exceptions, install calls, and tests) to a separate PR (#1906) so each can be reviewed and landed on its own. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80334c4 to
ee581a9
Compare
adriangb
added a commit
that referenced
this pull request
May 13, 2026
Adds an `X-Logfire-Telemetry: key=val,...` header to every request the SDK sends (OTLP exports, token validation, CRUD calls, variable provider, CLI), carrying the SDK version and a curated set of non-sensitive `_LogfireConfigData` fields so the backend can drive product analytics and deprecation decisions. Tokens, API keys, service name, environment, etc. are explicitly excluded. Also installs a response hook on every Logfire SDK session that surfaces `X-Logfire-Warning` headers via `warnings.warn` (deduplicated by Python's default filter) and raises `LogfireServerError` on `X-Logfire-Error` headers, so the server can deprecate endpoints or signal hard failures out-of-band. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> trim telemetry pairs, add service.instance.id, document rationale per field * Limit `_LogfireConfigData`-derived pairs to `code_source_set`, `variables_set`, and `token_count` — the only ones with a concrete product question they answer. Each remaining field now has an inline comment explaining why we send it. * Carry the resolved `service.instance.id` (UUID generated inside `_initialize`, shared with OTLP resource attributes) so the backend can correlate the header on non-OTLP requests with the spans this SDK instance exports. * Drop the `None` branch of `_format_value` and the idempotency guard in `install_logfire_response_hook` — both were unreachable, which was tripping the coverage gate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> move service_instance_id into _config_telemetry_pairs It only ships when a LogfireConfig is available, so it belongs in the config-derived group rather than the always-sent base group. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Revert "Add user agent to query client (#1875)" This reverts commit ff5c802. With X-Logfire-Telemetry now carrying SDK version, Python version, implementation and OS, the custom User-Agent on the query client is duplicate plumbing for the same product analytics question. Letting httpx send its default UA again, and the next commit adds the telemetry header here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> address review: JSON header value, implementation field, cache base pairs, query client - Encode the X-Logfire-Telemetry value as compact JSON instead of a comma-separated key=val list. Removes a silent footgun if any value ever contains "," or "=", and lets us send native bool/int instead of formatting them as strings. - Rename the `runtime` field to `implementation` to match Python's own wording for `sys.implementation.name`. - Cache `_base_telemetry_pairs()` with `functools.cache` since the value is constant per-process. - Wire the same telemetry header into the experimental query client now that the previous custom User-Agent has been reverted. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> split out response-header handling into its own PR Per review (#1905#discussion_r3189043209), the X-Logfire-Warning / X-Logfire-Error response-hook handling is logically independent from the X-Logfire-Telemetry request header — they just happened to be introduced together. Moved that code (plus its exceptions, install calls, and tests) to a separate PR (#1906) so each can be reviewed and landed on its own. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gives the Logfire backend an out-of-band channel — independent of response bodies — to deprecate endpoints or signal hard failures to any client running this SDK.
A new
logfire/_internal/server_response.pymodule installs arequestsresponse hook on every Logfire-bound HTTP session (OTLP exporters, token validation, CRUD client, variables provider, CLI). Each Logfire response is checked for the custom headersX-Logfire-Warning: <message>which callswarnings.warn(message, LogfireServerWarning). Python's default filter dedupes identical messages within a process, so a chatty server only warns once.