You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 933238e
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/migration-7.x-to-8.0.md
+39-12Lines changed: 39 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,7 +34,7 @@ An endpoint that is not served drops every event sent to it.
34
34
35
35
| Removed | Use instead |
36
36
| --- | --- |
37
-
|`capture_mode`, `CaptureMode`, `POSTHOG_CAPTURE_MODE`| Nothing. Capture v1 is the only path. |
37
+
|`capture_mode`, `CaptureMode`, `POSTHOG_CAPTURE_MODE`| Nothing. Capture v1 is the only path. Setting `posthog.capture_mode` on the module has no effect. |
38
38
|`gzip=True`|`capture_compression=CaptureCompression.GZIP`. The default is no compression. `POSTHOG_CAPTURE_COMPRESSION` still works. |
39
39
|`CaptureV1Error` (`from posthog.capture_v1 import CaptureV1Error`) |`CaptureError` (`from posthog import CaptureError`). There is no alias. |
40
40
|`posthog.capture_v1`|`posthog.capture_event` and `posthog.capture_send`|
@@ -61,18 +61,21 @@ An event can be dropped inside a 2xx response, for example when it is over a pro
61
61
8.0 reports those events as failures.
62
62
When the whole request is over the billing limit, capture returns a `402` with no per-event results instead.
63
63
64
-
- Every capture failure is a `CaptureError`. It has these fields:
65
-
-`status`: the HTTP status, or `0` when the request never got a response
64
+
- Every capture failure is a `CaptureError`, a subclass of `APIError`. It has these fields:
65
+
-`status`: the HTTP status, or `0` when the request never got a response. With `0`, `__cause__` holds the network error. In 7.x, `on_error` received the raw `requests` exception.
66
66
-`endpoint`, `request_id` and `attempts`
67
-
-`drops` and `retry_exhausted`: the uuids that were dropped or ran out of retries
68
-
-`event_results`: a `CaptureEventResult(result, details)` for each uuid, from `posthog.capture_send`
67
+
-`drops`: `(uuid, details)` pairs for the events capture dropped in a 2xx response
68
+
-`retry_exhausted`: the uuids still waiting for a retry after the last attempt
69
+
-`event_results`: a `CaptureEventResult(result, details)` for each uuid that got a result in a 2xx response, from `posthog.capture_send`. An event missing from it never got a result.
69
70
-`verdict_summary()`: counts such as `drop/llm_events_over_quota=1, retry/not_persisted=1`
70
71
-`on_error(error, batch)` receives every failure, including in `sync_mode` and from `AsyncPosthog.capture_immediate`.
72
+
- With `on_error` set, the SDK logs nothing for a failed batch.
71
73
- 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.
74
+
- The 7.x lines `error uploading: ...`, `async capture upload failed (...)` and `Immediate async capture failed (...)` are gone. Update any log-based alerts that match them.
72
75
- In `sync_mode`, a failed `capture()` calls `on_error` and returns `None`. With `debug=True` it calls `on_error` and then re-raises the error.
73
76
- If a capture inside `on_error` fails, the SDK logs the failure and does not call `on_error` again.
74
-
-A `429`response is not retried.
75
-
- Retries start at 100 ms and double each attempt, up to 30 seconds. The `Consumer` default is 3 retries, down from 10.
77
+
-The SDK retries `408`, `500`, `502`, `503` and `504` responses and network errors. Other error statuses fail the batch at once, including `429`and the other 5xx codes. 7.x also retried`429` and every 5xx. Capture itself does not return `429`; a proxy in front of it can.
78
+
- Retries start at 100 ms and double each attempt, up to 30 seconds. A `Retry-After` header sets a minimum wait, up to 30 seconds. The `Consumer` default is 3 retries, down from 10.
76
79
77
80
## Event uuids
78
81
@@ -81,6 +84,15 @@ When the whole request is over the billing limit, capture returns a `402` with n
81
84
- Any other value is replaced with a generated uuid, and the SDK logs an error. This applies to `AsyncPosthog` too.
82
85
- Generated uuids are UUIDv7.
83
86
87
+
## Session and window IDs
88
+
89
+
Capture v1 sends `$session_id` and `$window_id` as top-level event fields, not as properties.
90
+
The SDK moves them out of `properties` for you.
91
+
92
+
- A string is sent as given, including `""`.
93
+
-`None` counts as unset and is removed.
94
+
- Any other value is removed and not sent, because capture would reject the whole batch. 7.x sent it as a property.
95
+
84
96
## Event options
85
97
86
98
Capture v1 sends processing options in an `options` object, next to `properties`.
@@ -91,10 +103,20 @@ Capture v1 sends processing options in an `options` object, next to `properties`
-`super_options` sets options on every event, like `super_properties`.
95
-
-`set_context_option(key, value)` sets an option for the current context, like `tag()`.
106
+
-`super_options`, a new `Client`, `AsyncPosthog` and module setting, sets options on every event, like `super_properties`.
107
+
-`set_context_option(key, value)` sets an option for the current context, like `tag()`. `get_context_options()` returns the options of the current context. Both exist on `Client` and as module functions. `AsyncPosthog` has no context methods, like it has no `tag()`, so call the module functions. They apply to every client in the context.
108
+
- Context tags and options reach `capture`, `capture_ai` and `capture_exception`. Context options also reach `set` and `set_once`. Neither reaches `alias` or `group_identify`. `super_properties` and `super_options` reach every method.
96
109
- Options are sent as given. PostHog validates them.
97
-
- The legacy properties `$cookieless_mode`, `$ignore_sent_at`, `$product_tour_id` and `$process_person_profile` still work. They fill the matching option only when it is unset, and the SDK always removes them from `properties`. Their values are no longer converted, so pass `True` or `False`, not `"true"`.
110
+
- An `options` value that is not a dict is logged as an error and ignored. The event is still sent.
111
+
- The legacy properties still work. They fill the matching option only when it is unset, and the SDK always removes them from `properties`. Their values are no longer converted, so pass `True` or `False`, not `"true"`.
- An option set at any layer wins over its legacy property set at any layer. For example, `super_options={"cookieless_mode": True}` wins over an event's `$cookieless_mode: False`. When you move a default to options, move the per-event overrides of that key to options too.
99
121
- A `None` option counts as unset, so a later step can fill it.
100
122
@@ -120,21 +142,26 @@ These changes follow from this order:
120
142
- A `$set`, `$set_once`, `$groups` or `$group_set` in `super_properties` no longer replaces the whole value of the call. The two merge, and the call wins key by key.
121
143
- 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.
122
144
- To change an option in `before_send`, edit `options`. A legacy property that `before_send` adds does not replace an option that is already set.
145
+
- When the server enables minimal `$feature_flag_called` events, those events now keep `$window_id`, `$cookieless_mode`, `$ignore_sent_at` and `$product_tour_id`, so their options still apply.
123
146
124
147
## AI capture
125
148
126
149
-`capture_ai` and every built-in AI integration send to `/i/v1/ai/events`. The AI endpoint accepts events up to 8 MiB.
127
150
-`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.
128
-
- 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.
151
+
- The AI integrations call your client's `capture_ai`. A client object without `capture_ai` gets `capture` calls instead. A custom client must accept the `options` keyword argument.
129
152
- Tests that pass a `Mock` client to an AI integration must assert on `mock.capture_ai`, not `mock.capture`.
130
-
- 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.
153
+
- 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. This is the only option the integrations pass. It wins over `super_options`, context options and a `$process_person_profile: true` property. `before_send` can still change it.
154
+
- The AI integrations have no `options` argument. To set options on their events, use `set_context_option`, `super_options`, or a legacy property such as `$cookieless_mode` in `posthog_properties`.
131
155
- MCP's `PostHogCaptureEvent` has an `options` key.
132
156
- New `Client` and `AsyncPosthog` arguments for the AI lane:
133
157
-`capture_ai_compression`: default none. `POSTHOG_CAPTURE_COMPRESSION` does not apply to it.
134
158
-`capture_ai_max_queue_size`: default 1000
135
159
-`capture_ai_timeout`: default 30 seconds
136
160
-`capture_ai_max_event_bytes`: default 8 MiB plus 64 KiB. You can only lower it.
161
+
- The AI lane does not use `max_queue_size`, `timeout` or `capture_compression`. An invalid `capture_ai_*` value raises `ValueError` when you create the client.
162
+
- The module-level client has no AI lane settings. To change them, create a `Client`.
137
163
-`AsyncPosthog` has `capture_ai` and `capture_ai_immediate`.
164
+
-`AsyncPosthog` sends events with `requests` in a worker thread. It uses `httpx` only for feature flags and remote config.
138
165
-`AsyncPosthog` accepts `privacy_mode` and `enable_full_ai_capture`, with the same meaning as on `Client`. An AI integration given an `AsyncPosthog` client used to always truncate and redact media.
0 commit comments