Skip to content

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

Merged
eli-r-ph merged 4 commits into
v1from
v1-pre-release-fixes
Oct 27, 2026
Merged

eli-r-ph merged 4 commits into
v1from
v1-pre-release-fixes

Conversation

@eli-r-ph

@eli-r-ph eli-r-ph commented Oct 25, 2026 •

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.

The event encoder copied every event to replace NaN and Infinity with null before encoding, which made each encode 1.5-1.7x slower even when the event had no such value.

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 event encoder encodes strictly first and copies the event only when that fails on a non-finite number. Output is unchanged.
  • The migration guide adds $product_tour_id, the one-connection-try-per-attempt change, and the new hook log.
  • The migration guide adds a reverse proxy checklist: forward both /i/v1 paths, pass Authorization and the PostHog-* headers, and accept 20 MB bodies.

💚 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.
  • Encoder tests check the exact output with allow_nan on and off, and that events without NaN or Infinity skip the copy (fails before this change).
  • 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
eli-r-ph and others added 2 commits October 24, 2026 20:30
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Encode strictly first and replace NaN and Infinity with null only after
that encode fails, so normal events skip the full copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@eli-r-ph
eli-r-ph merged commit cfdb4ec into v1 Oct 27, 2026
41 checks passed
@eli-r-ph
eli-r-ph deleted the v1-pre-release-fixes branch October 27, 2026 02:25
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.

2 participants