Repository navigation
fix(ai): capture an error event when a streaming call fails to connect #1146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7aaa93c
29325a4
9798de2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| pypi/posthog: patch | ||
| --- | ||
|
|
||
| Capture an `$ai_generation` error event when `create(stream=True)` fails before the stream starts (bad key, rate limit, invalid model) in the OpenAI chat, OpenAI Responses, Anthropic and Gemini wrappers, sync and async. Previously only errors raised mid-stream were captured. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -256,11 +256,31 @@ def _generate_content_streaming( | |
| ): | ||
| start_time = time.time() | ||
| usage_stats: TokenUsage = TokenUsage() | ||
| accumulated_content = [] | ||
| accumulated_content: list[Any] = [] | ||
| stop_reason: Optional[str] = None | ||
|
|
||
| kwargs_without_stream = {"model": model, "contents": contents, **kwargs} | ||
| response = self._client.models.generate_content_stream(**kwargs_without_stream) | ||
| try: | ||
| response = self._client.models.generate_content_stream( | ||
| **kwargs_without_stream | ||
| ) | ||
| except Exception as exc: | ||
| self._capture_streaming_event( | ||
| model, | ||
| contents, | ||
| distinct_id, | ||
| trace_id, | ||
| properties, | ||
| privacy_mode, | ||
| groups, | ||
| kwargs, | ||
| usage_stats, | ||
| time.time() - start_time, | ||
| accumulated_content, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blocking: Keep the new Gemini handlers compatible with Mypy — Passing the initially empty, unannotated |
||
| stop_reason=stop_reason, | ||
| error=exc, | ||
| ) | ||
| raise | ||
|
|
||
| def generator(): | ||
| nonlocal usage_stats | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blocking: Preserve the provider exception when error telemetry cannot format rejected input — When Anthropic rejects malformed input such as
messages=[None]with HTTP 400, the newly added capture call formats that same rejected input before reaching the bareraise.format_anthropic_inputcallsmsg.get(...), raisingAttributeErrorand replacing the originalanthropic.BadRequestError; the async handler atposthog/ai/anthropic/anthropic_async.py:169behaves identically. Previously callers received the actionable provider error and could handleBadRequestErrornormally. Ensure failures in this telemetry path cannot replace the original exception. Reproduction: reproduced —python -m pytest -p no:cacheprovider posthog/test/ai/test_review_connect.py -k invalid_anthropic --timeout=30 -vvfails both sync/async assertions on the reviewed head withAttributeError: 'NoneType' object has no attribute 'get', while both pass unchanged at the recorded merge base.