Skip to content

Commit f34a91a

Browse files
committed
docs: 8.0 migration guide, README and openfeature-provider pin
1 parent 2011a51 commit f34a91a

6 files changed

Lines changed: 145 additions & 4 deletions

File tree

‎.sampo/changesets/capture-v1-major.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
pypi/posthog: major
33
---
44

5-
Capture v1 is the only capture path. Events and AI events send to the capture v1 endpoints, and the legacy v0 capture path is removed. See the migration guide for breaking changes.
5+
Capture v1 is the only capture path. Events and AI events send to the capture v1 endpoints, and the legacy v0 capture path is removed. See the [migration guide](https://github.com/PostHog/posthog-python/blob/main/docs/migration-7.x-to-8.0.md) for breaking changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
pypi/openfeature-provider-posthog: minor
3+
---
4+
5+
Requires posthog 8.0 or later. Upgrade both packages together.

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Follow [Public API changes](./CONTRIBUTING.md#public-api-changes). As an agent,
2323

2424
Before changing capture configuration, serialization, routing, or retries, read the relevant implementation and tests.
2525

26-
Capture v1 is the only capture protocol (`capture` posts to `/i/v1/analytics/events`, `capture_ai` to `/i/v1/ai/events`); strictly typed v1 options and `$set`/`$set_once` relocation; compression (gzip, zlib-wrapped deflate, optional zstd, default none), set per lane by `capture_compression` and `capture_ai_compression`; partial-only per-event retries with stable identity; accumulated drop reporting even on 2xx; terminal v1 `429`; `Retry-After` as a minimum bounded by the shared 30s ceiling; and inline blocking retries with `sync_mode=True`.
26+
Capture v1 is the only capture protocol (`capture` posts to `/i/v1/analytics/events`, `capture_ai` to `/i/v1/ai/events`); per-event `options` sent as given, layered over `super_options` and context options, with legacy `$` option properties hoisted once after `before_send`; `$set`/`$set_once` relocation; compression (gzip, zlib-wrapped deflate, optional zstd, default none), set per lane by `capture_compression` and `capture_ai_compression`; partial-only per-event retries with stable identity; accumulated drop reporting even on 2xx; terminal v1 `429`; `Retry-After` as a minimum bounded by the shared 30s ceiling; and inline blocking retries with `sync_mode=True`.
2727

2828
## Mirror and build safety
2929

‎README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ SDK usage examples and code snippets live in the official documentation so they
1818

1919
| SDK Version | Python Versions Supported | Notes |
2020
| ------------- | ---------------------------- | -------------------------- |
21-
| 7.3.1+ | 3.10, 3.11, 3.12, 3.13, 3.14 | Added Python 3.14 support |
21+
| 8.0.0+ | 3.10, 3.11, 3.12, 3.13, 3.14 | Capture v1 only, see the [migration guide](docs/migration-7.x-to-8.0.md) |
22+
| 7.3.1 - 7.x | 3.10, 3.11, 3.12, 3.13, 3.14 | Added Python 3.14 support |
2223
| 7.0.0 - 7.0.1 | 3.10, 3.11, 3.12, 3.13 | Dropped Python 3.9 support |
2324
| 4.0.1 - 6.x | 3.9, 3.10, 3.11, 3.12, 3.13 | Python 3.9+ required |
2425

2526
## Documentation
2627

2728
- [Python library docs](https://posthog.com/docs/libraries/python)
29+
- [Migrating from 7.x to 8.0](docs/migration-7.x-to-8.0.md)
2830
- [Django framework docs](https://posthog.com/docs/libraries/django)
2931
- [Flask framework docs](https://posthog.com/docs/libraries/flask)
3032
- [OpenFeature provider docs](https://posthog.com/docs/feature-flags/installation/openfeature) — use PostHog flags through the [OpenFeature](https://openfeature.dev) Python SDK

‎docs/migration-7.x-to-8.0.md‎

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Migrating from posthog 7.x to 8.0
2+
3+
posthog 8.0 sends every event through capture v1 and removes the legacy capture path.
4+
Most apps upgrade without code changes.
5+
Read the checklist first, then the sections that apply to you.
6+
7+
## Checklist
8+
9+
You need to change code if your app does any of these:
10+
11+
- passes `Client` or `AsyncPosthog` constructor arguments by position after `host`
12+
- sets `capture_mode`, `POSTHOG_CAPTURE_MODE` or `gzip`
13+
- imports `CaptureV1Error`, `posthog.capture_v1`, `request.batch_post`, `EVENTS_ENDPOINT` or `AI_EVENTS_ENDPOINT`
14+
- sends events to a self-hosted PostHog that does not serve the capture v1 endpoints
15+
- reuses one event `uuid` for more than one event
16+
- sets `$process_person_profile` to turn person processing on for events without a distinct ID
17+
- passes strings such as `"true"` for `$cookieless_mode`, `$ignore_sent_at` or `$process_person_profile`
18+
- expects `super_properties` to override properties passed to a single call
19+
- tests the AI integrations with a mock client and asserts on `capture`
20+
- passes its own client object to the AI integrations
21+
22+
## Endpoints
23+
24+
| Method | Endpoint |
25+
| --- | --- |
26+
| `capture`, `set`, `set_once`, `alias`, `group_identify`, `capture_exception` | `/i/v1/analytics/events` |
27+
| `capture_ai`, `capture_ai_immediate`, and every built-in AI integration | `/i/v1/ai/events` |
28+
29+
If you send events to a self-hosted PostHog, check that it serves both endpoints before you upgrade.
30+
An endpoint that is not served drops every event sent to it.
31+
32+
## Removed options and APIs
33+
34+
| Removed | Use instead |
35+
| --- | --- |
36+
| `capture_mode`, `CaptureMode`, `POSTHOG_CAPTURE_MODE` | Nothing. Capture v1 is the only path. |
37+
| `gzip=True` | `capture_compression=CaptureCompression.GZIP`. The default is no compression. `POSTHOG_CAPTURE_COMPRESSION` still works. |
38+
| `CaptureV1Error` | `CaptureError`. There is no alias. |
39+
| `posthog.capture_v1` | `posthog.capture_event` and `posthog.capture_send` |
40+
| `request.batch_post`, `async_batch_post`, `EVENTS_ENDPOINT`, `AI_EVENTS_ENDPOINT` | Nothing. Send events through a client. |
41+
| The `gzip` parameter of `request.post` and `request.flags` | Nothing. |
42+
| The `backoff` dependency | Add it to your own requirements if your code imports it. |
43+
44+
Constructor arguments after `host` are keyword-only:
45+
46+
```python
47+
# 7.x
48+
Posthog("<api_key>", "https://us.i.posthog.com", True)
49+
50+
# 8.0
51+
Posthog("<api_key>", host="https://us.i.posthog.com", debug=True)
52+
```
53+
54+
## Errors and `on_error`
55+
56+
Capture v1 returns a result for every event, even when the request succeeds.
57+
An event can be dropped, for example by billing limits or quotas, inside a 2xx response.
58+
8.0 reports those events as failures.
59+
60+
- Every capture failure is a `CaptureError`. It has these fields:
61+
- `status`: the HTTP status, or `0` when the request never got a response
62+
- `endpoint`, `request_id` and `attempts`
63+
- `drops` and `retry_exhausted`: the uuids that were dropped or ran out of retries
64+
- `event_results`: a `CaptureEventResult(result, details)` for each uuid, from `posthog.capture_send`
65+
- `verdict_summary()`: counts such as `drop/billing=1, retry/not_persisted=1`
66+
- `on_error(error, batch)` receives every failure, including in `sync_mode` and from `AsyncPosthog.capture_immediate`.
67+
- Without `on_error`, the SDK logs one line per failed batch, for example `2 event(s) not persisted by /i/v1/analytics/events: ...`. The line never contains event content or the server's response text.
68+
- In `sync_mode`, a failed `capture()` calls `on_error` and returns `None`.
69+
- If a capture inside `on_error` fails, the SDK logs the failure and does not call `on_error` again.
70+
- A `429` response is not retried.
71+
- Retries start at 100 ms and double each attempt, up to 30 seconds. The `Consumer` default is 3 retries, down from 10.
72+
73+
## Event uuids
74+
75+
- Each event needs its own uuid. Capture rejects a whole batch that contains the same uuid twice, so the other events in that batch are lost too.
76+
- The SDK accepts a uuid with hyphens, 32 hex digits, `{...}` braces or a `urn:uuid:` prefix, in any case. It sends the lowercase hyphenated form and returns that form from `capture`.
77+
- Any other value is replaced with a generated uuid, and the SDK logs an error. This applies to `AsyncPosthog` too.
78+
- Generated uuids are UUIDv7.
79+
80+
## Event options
81+
82+
Capture v1 sends processing options in an `options` object, next to `properties`.
83+
84+
- `capture`, `capture_ai`, `set`, `set_once`, `alias`, `group_identify` and `capture_exception` take an `options` argument:
85+
86+
```python
87+
posthog.capture("signed_up", distinct_id="user-1", options={"cookieless_mode": True})
88+
```
89+
90+
- `super_options` sets options on every event, like `super_properties`.
91+
- `set_context_option(key, value)` sets an option for the current context, like `tag()`.
92+
- Options are sent as given. PostHog validates them.
93+
- The legacy properties `$cookieless_mode`, `$ignore_sent_at`, `$product_tour_id` and `$process_person_profile` still work. They move into options after `before_send`. Their values are no longer converted, so pass `True` or `False`, not `"true"`.
94+
- An option wins over its legacy property. A `None` option counts as unset.
95+
96+
Values apply in this order, and each layer overrides the ones before it:
97+
98+
1. options the SDK sets, such as turning off person processing for events without a distinct ID
99+
2. `super_options` and `super_properties`
100+
3. context options and tags
101+
4. the `options` and `properties` of the call
102+
5. `before_send`
103+
104+
Two changes follow from this order:
105+
106+
- Properties passed to a call now override `super_properties`. `super_properties` can no longer change `$lib`, `$lib_version` or `$geoip_disable`.
107+
- An event without a distinct ID gets `options.process_person_profile = false`. A `$process_person_profile: true` property no longer turns person processing back on. Set the option instead.
108+
109+
## AI capture
110+
111+
- `capture_ai` and every built-in AI integration send to `/i/v1/ai/events`. The AI endpoint accepts events up to 8 MiB.
112+
- `enable_full_ai_capture` now controls only content: string truncation and media redaction. It no longer chooses the endpoint. `_use_ai_lane` and `_enable_multimodal_capture` still work as aliases.
113+
- The AI integrations call your client's `capture_ai`, and pass `options=`. A client object without `capture_ai` gets `capture` calls instead. A custom client must accept the `options` keyword argument.
114+
- Tests that pass a `Mock` client to an AI integration must assert on `mock.capture_ai`, not `mock.capture`.
115+
- When an AI integration or MCP falls back to a trace, run or session ID, it turns person processing off with a per-event option. A `$process_person_profile: true` property no longer turns it back on. `before_send` can still change it.
116+
- MCP's `PostHogCaptureEvent` has an `options` key.
117+
- New `Client` and `AsyncPosthog` arguments for the AI lane:
118+
- `capture_ai_compression`: default none. `POSTHOG_CAPTURE_COMPRESSION` does not apply to it.
119+
- `capture_ai_max_queue_size`: default 1000
120+
- `capture_ai_timeout`: default 30 seconds
121+
- `capture_ai_max_event_bytes`: default 8 MiB plus 64 KiB. You can only lower it.
122+
- `AsyncPosthog` has `capture_ai` and `capture_ai_immediate`.
123+
124+
## Batching and size limits
125+
126+
- An analytics event over 900 KiB is dropped and logged. This now applies in `sync_mode` too.
127+
- An AI event over `capture_ai_max_event_bytes` is dropped and logged.
128+
- A batch stops before an event that would take it past 5 MiB. A larger event is sent alone.
129+
- `flush()` and `shutdown()` drain the analytics and AI queues at the same time.
130+
131+
## OpenFeature provider
132+
133+
`openfeature-provider-posthog` 0.2.0 requires posthog 8.0 or later.
134+
Upgrade both packages together.

‎openfeature-provider/pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ dependencies = [
2727
# single-call API. Pinned to the posthog major this provider is released and
2828
# tested against (both ship from this repo); bump the upper bound when moving
2929
# the provider to a new posthog major.
30-
"posthog>=7.0.0,<8.0.0",
30+
"posthog>=8.0.0,<9.0.0",
3131
"openfeature-sdk>=0.8.0",
3232
]
3333

0 commit comments

Comments
 (0)