Skip to content

fix: own capture connection retries and redact hook error logs - #1125

Open
eli-r-ph wants to merge 2 commits into
v1from
v1-pre-release-fixes
Open

eli-r-ph wants to merge 2 commits into
v1from
v1-pre-release-fixes

Conversation

@eli-r-ph

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

Capture corrects clock skew from each request's PostHog-Request-Timestamp, so every physical send needs a fresh stamp.
The capture session's HTTP adapter retried a failed connection up to twice inside one SDK attempt, reusing the stamped headers.
After slow connection failures, capture saw a stale timestamp and shifted every event in that request later by the time spent connecting.

A raising before_send hook was logged with its exception message, which can hold the data the hook was removing.
The migration guide also listed three of the four legacy option properties.

Changes

  • Capture uses its own session whose adapter never retries, so each connection try is an SDK attempt with its own attempt number and timestamp. It is rebuilt after fork and when socket options change, like the other sessions.
    • The adapter's read retries never applied to capture: urllib3 does not retry a read error on a POST. Only connection retries change.
    • Other requests (remote config, flag definitions, metrics, tracing) keep the existing session.
  • A raising before_send logs one error line with the event name and exception type, and the traceback at debug level, in Client and AsyncPosthog.
  • A before_send that returns something other than a dict or None logs its type and drops the event.
  • The migration guide adds $product_tour_id, the one-connection-try-per-attempt change, and the new hook log.

💚 How did you test it?

  • New test: a refused connection is tried exactly once per SDK attempt through the real session stack (it failed with 9 tries for 3 attempts before this change).
  • Hook tests assert the exact error line, no traceback on it, and one debug traceback, for both clients.
  • Session tests cover no adapter retries, socket options and the fork rebuild for the capture session.
  • ruff format --check, ruff check, mypy with the baseline, and the full test suite pass.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran sampo add to generate a changeset file

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Written with Claude Code (Claude Opus 5.5, claude-opus-5-5) under the direction of the assignee.
The capture session reuses the flags session's no-retry builder rather than changing the general session, so non-capture requests keep their behavior.

🤖 Generated with Claude Code

Capture uses a session whose adapter never retries, so each connection
try is an SDK attempt with its own attempt number and request timestamp.
The hidden adapter retries reused a stale timestamp, which capture reads
as clock skew.

A raising before_send logs the event name and exception type, never the
exception message; the traceback goes to debug. A non-dict return logs
its type and drops the event. The migration guide lists all four legacy
option properties.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@eli-r-ph
eli-r-ph requested a review from a team as a code owner October 25, 2026 03:26
@eli-r-ph eli-r-ph self-assigned this Oct 25, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant