vybekiit 0.7.33 → 0.7.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +818 -92
- package/dist/global-skills/eas-app-stores/SKILL.md +2 -2
- package/dist/global-skills/eas-hosting/SKILL.md +2 -2
- package/dist/global-skills/eas-observe/SKILL.md +7 -15
- package/dist/global-skills/eas-observe/references/queries.md +51 -10
- package/dist/global-skills/eas-observe/references/setup.md +60 -7
- package/dist/global-skills/eas-simulator/SKILL.md +2 -2
- package/dist/global-skills/eas-simulator/references/run-your-app.md +2 -0
- package/dist/global-skills/eas-update/SKILL.md +2 -2
- package/dist/global-skills/eas-update-insights/SKILL.md +2 -2
- package/dist/global-skills/eas-workflows/SKILL.md +2 -2
- package/dist/global-skills/expo-animation/SKILL.md +2 -2
- package/dist/global-skills/expo-app-clip/SKILL.md +2 -2
- package/dist/global-skills/expo-brownfield/SKILL.md +2 -2
- package/dist/global-skills/expo-data-fetching/SKILL.md +2 -2
- package/dist/global-skills/expo-design-system/SKILL.md +2 -2
- package/dist/global-skills/expo-dev-client/SKILL.md +4 -2
- package/dist/global-skills/expo-dom/SKILL.md +2 -2
- package/dist/global-skills/expo-examples/SKILL.md +2 -2
- package/dist/global-skills/expo-migrate-module/SKILL.md +2 -2
- package/dist/global-skills/expo-module/SKILL.md +2 -2
- package/dist/global-skills/expo-native-ui/SKILL.md +2 -2
- package/dist/global-skills/expo-overview/SKILL.md +9 -4
- package/dist/global-skills/expo-overview/references/launch-without-dev-menu.md +24 -0
- package/dist/global-skills/expo-project-structure/SKILL.md +2 -2
- package/dist/global-skills/expo-router/SKILL.md +2 -2
- package/dist/global-skills/expo-ui/SKILL.md +2 -2
- package/dist/global-skills/expo-upgrade/SKILL.md +2 -2
- package/dist/global-skills/expo-web-to-native/SKILL.md +2 -2
- package/dist/global-skills/expo-web-to-native/references/verify-on-device.md +1 -1
- package/dist/global-skills/firebase-app-hosting-basics/SKILL.md +16 -3
- package/dist/global-skills/firebase-app-hosting-basics/references/cli_commands.md +10 -12
- package/dist/global-skills/firebase-app-hosting-basics/references/configuration.md +2 -1
- package/dist/global-skills/firebase-basics/SKILL.md +6 -4
- package/dist/global-skills/firebase-basics/references/web_setup.md +3 -3
- package/dist/global-skills/instrument-feature-flags/references/adding-feature-flag-code.md +81 -333
- package/dist/global-skills/instrument-feature-flags/references/android.md +19 -13
- package/dist/global-skills/instrument-feature-flags/references/api.md +17 -13
- package/dist/global-skills/instrument-feature-flags/references/best-practices.md +35 -35
- package/dist/global-skills/instrument-feature-flags/references/django.md +120 -72
- package/dist/global-skills/instrument-feature-flags/references/dotnet.md +48 -102
- package/dist/global-skills/instrument-feature-flags/references/elixir.md +4 -10
- package/dist/global-skills/instrument-feature-flags/references/flask.md +55 -39
- package/dist/global-skills/instrument-feature-flags/references/flutter.md +19 -13
- package/dist/global-skills/instrument-feature-flags/references/go.md +21 -13
- package/dist/global-skills/instrument-feature-flags/references/ios.md +19 -13
- package/dist/global-skills/instrument-feature-flags/references/java.md +4 -12
- package/dist/global-skills/instrument-feature-flags/references/laravel.md +18 -16
- package/dist/global-skills/instrument-feature-flags/references/next-js.md +44 -54
- package/dist/global-skills/instrument-feature-flags/references/nodejs.md +21 -13
- package/dist/global-skills/instrument-feature-flags/references/php.md +21 -13
- package/dist/global-skills/instrument-feature-flags/references/python.md +22 -14
- package/dist/global-skills/instrument-feature-flags/references/react-native.md +18 -13
- package/dist/global-skills/instrument-feature-flags/references/react.md +21 -14
- package/dist/global-skills/instrument-feature-flags/references/ruby-on-rails.md +31 -68
- package/dist/global-skills/instrument-feature-flags/references/ruby.md +21 -13
- package/dist/global-skills/instrument-feature-flags/references/rust.md +10 -34
- package/dist/global-skills/instrument-feature-flags/references/usage.md +94 -114
- package/dist/global-skills/instrument-feature-flags/references/web.md +21 -13
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-android.md +7 -7
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-expo.md +2 -2
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-fastapi.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-flask.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-laravel.md +2 -2
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-php.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-python.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-ruby.md +1 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-swift.md +4 -4
- package/dist/global-skills/instrument-product-analytics/references/android.md +64 -109
- package/dist/global-skills/instrument-product-analytics/references/angular.md +32 -28
- package/dist/global-skills/instrument-product-analytics/references/astro.md +29 -34
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +27 -42
- package/dist/global-skills/instrument-product-analytics/references/django.md +120 -72
- package/dist/global-skills/instrument-product-analytics/references/dotnet.md +48 -102
- package/dist/global-skills/instrument-product-analytics/references/elixir.md +25 -50
- package/dist/global-skills/instrument-product-analytics/references/flask.md +55 -39
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +94 -96
- package/dist/global-skills/instrument-product-analytics/references/go.md +39 -77
- package/dist/global-skills/instrument-product-analytics/references/identify-users.md +24 -26
- package/dist/global-skills/instrument-product-analytics/references/ios.md +22 -22
- package/dist/global-skills/instrument-product-analytics/references/laravel.md +18 -16
- package/dist/global-skills/instrument-product-analytics/references/next-js.md +44 -54
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js-3-6.md +32 -34
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js.md +36 -36
- package/dist/global-skills/instrument-product-analytics/references/php.md +42 -87
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +15 -12
- package/dist/global-skills/instrument-product-analytics/references/python.md +106 -154
- package/dist/global-skills/instrument-product-analytics/references/react-native.md +97 -176
- package/dist/global-skills/instrument-product-analytics/references/react-router-v6.md +29 -40
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-data-mode.md +29 -38
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-declarative-mode.md +29 -40
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-framework-mode.md +32 -37
- package/dist/global-skills/instrument-product-analytics/references/ruby-on-rails.md +31 -68
- package/dist/global-skills/instrument-product-analytics/references/ruby.md +40 -96
- package/dist/global-skills/instrument-product-analytics/references/svelte.md +34 -34
- package/dist/global-skills/instrument-product-analytics/references/tanstack-start.md +19 -19
- package/dist/global-skills/instrument-product-analytics/references/usage.md +94 -114
- package/dist/global-skills/instrument-product-analytics/references/vue-js.md +33 -45
- package/dist/global-skills/manifest.json +2 -1
- package/dist/global-skills/mongodb-search-and-ai/SKILL.md +40 -22
- package/dist/global-skills/mongodb-search-and-ai/references/automated-embedding.md +8 -2
- package/dist/global-skills/mongodb-search-and-ai/references/quick-start.md +725 -0
- package/dist/global-skills/mongodb-search-and-ai/scripts/quickstart_complete.py +386 -0
- package/dist/global-skills/neon/SKILL.md +15 -10
- package/dist/global-skills/neon/references/claimable-neon.md +2 -0
- package/dist/global-skills/neon-functions/SKILL.md +12 -11
- package/dist/global-skills/neon-functions/references/sse.md +2 -2
- package/dist/global-skills/neon-object-storage/SKILL.md +5 -4
- package/dist/global-skills/neon-postgres/SKILL.md +4 -1
- package/dist/global-skills/neon-realtime/SKILL.md +207 -0
- package/dist/global-skills/neon-realtime/references/mutations.md +743 -0
- package/dist/global-skills/neon-realtime/references/queries.md +509 -0
- package/dist/global-skills/neon-realtime/references/reactivity.md +407 -0
- package/dist/global-skills/neon-realtime/references/ssr.md +695 -0
- package/dist/global-skills/neon-realtime/references/subscribing.md +485 -0
- package/dist/global-skills/resend/SKILL.md +4 -2
- package/dist/global-skills/resend/references/inboxes.md +377 -0
- package/dist/global-skills/resend/references/webhooks.md +9 -0
- package/dist/global-skills/stripe-best-practices/SKILL.md +1 -1
- package/dist/global-skills/stripe-best-practices/references/connect.md +1 -1
- package/dist/global-skills/stripe-best-practices/references/security.md +9 -9
- package/dist/global-skills/vybekiitReferences/backend/AGENTS.md +1 -1
- package/dist/global-skills/vybekiitReferences/backend/agent/goal-routes.json +303 -18
- package/dist/global-skills/vybekiitReferences/extension/AGENTS.md +1 -1
- package/dist/global-skills/vybekiitReferences/extension/agent/goal-routes.json +352 -18
- package/dist/global-skills/vybekiitReferences/mobile/AGENTS.md +1 -1
- package/dist/global-skills/vybekiitReferences/mobile/agent/goal-routes.json +413 -22
- package/dist/global-skills/vybekiitReferences/spa/AGENTS.md +1 -1
- package/dist/global-skills/vybekiitReferences/spa/agent/goal-routes.json +391 -21
- package/dist/global-skills/vybekiitReferences/web/AGENTS.md +14 -2
- package/dist/global-skills/vybekiitReferences/web/agent/goal-routes.json +490 -32
- package/package.json +8 -8
|
@@ -2,26 +2,54 @@
|
|
|
2
2
|
|
|
3
3
|
# Python
|
|
4
4
|
|
|
5
|
+
Canonical URL: https://posthog.com/docs/libraries/python
|
|
6
|
+
|
|
7
|
+
> **Cloud region:** This page uses US Cloud hosts. For an EU Cloud project, use `https://eu.i.posthog.com` instead of `https://us.i.posthog.com` (ingestion host), and use `https://eu.posthog.com` instead of `https://app.posthog.com` (app host for links).
|
|
8
|
+
|
|
9
|
+
## On this page
|
|
10
|
+
|
|
11
|
+
- [Installation](#installation)
|
|
12
|
+
- [Use the asyncio client](#use-the-asyncio-client)
|
|
13
|
+
- [Identifying users](#identifying-users)
|
|
14
|
+
- [Capturing events](#capturing-events)
|
|
15
|
+
- [Person profiles and properties](#person-profiles-and-properties)
|
|
16
|
+
- [Alias](#alias)
|
|
17
|
+
- [Contexts](#contexts)
|
|
18
|
+
- [Group analytics](#group-analytics)
|
|
19
|
+
- [Feature flags](#feature-flags)
|
|
20
|
+
- [Experiments (A/B tests)](#experiments-ab-tests)
|
|
21
|
+
- [AI Observability](#ai-observability)
|
|
22
|
+
- [Error tracking](#error-tracking)
|
|
23
|
+
- [Distributed tracing](#distributed-tracing)
|
|
24
|
+
- [GeoIP properties](#geoip-properties)
|
|
25
|
+
- [Debug mode](#debug-mode)
|
|
26
|
+
- [Disabling requests during tests](#disabling-requests-during-tests)
|
|
27
|
+
- [Connection configuration](#connection-configuration)
|
|
28
|
+
- [Filtering or modifying events before sending](#filtering-or-modifying-events-before-sending)
|
|
29
|
+
- [Historical migrations](#historical-migrations)
|
|
30
|
+
- [Serverless environments (Render/Lambda/...)](#serverless-environments-renderlambda)
|
|
31
|
+
- [Django](#django)
|
|
32
|
+
- [ASGI request middleware](#asgi-request-middleware)
|
|
33
|
+
- [Alternative name](#alternative-name)
|
|
34
|
+
- [Thank you](#thank-you)
|
|
35
|
+
- [Supported versions](#supported-versions)
|
|
36
|
+
|
|
5
37
|
The Python SDK makes it easy to capture events, evaluate feature flags, track errors, and more in your Python apps.
|
|
6
38
|
|
|
7
39
|
> These docs cover version `7.x` of the Python SDK, which requires Python 3.10 or higher. On Python 3.9? See [supported versions](#supported-versions).
|
|
8
40
|
|
|
9
41
|
## Installation
|
|
10
42
|
|
|
11
|
-
Terminal
|
|
12
|
-
|
|
13
43
|
```bash
|
|
14
44
|
pip install posthog
|
|
15
45
|
```
|
|
16
46
|
|
|
17
47
|
**Upgrading to v6**
|
|
18
48
|
|
|
19
|
-
Version `6.x` of the PostHog Python SDK introduces a new [contexts](/docs/libraries/python.md#contexts) API and breaking changes. If you're upgrading from `5.x` to `6.x`, read the [migration guide](/tutorials/python-v6-migration.md) first to learn more.
|
|
49
|
+
Version `6.x` of the PostHog Python SDK introduces a new [contexts](https://posthog.com/docs/libraries/python.md#contexts) API and breaking changes. If you're upgrading from `5.x` to `6.x`, read the [migration guide](https://posthog.com/tutorials/python-v6-migration.md) first to learn more.
|
|
20
50
|
|
|
21
51
|
In your app, import the `posthog` library and set your project token and host **before** making any calls.
|
|
22
52
|
|
|
23
|
-
Python
|
|
24
|
-
|
|
25
53
|
```python
|
|
26
54
|
from posthog import Posthog
|
|
27
55
|
|
|
@@ -36,16 +64,12 @@ You can find your project token and instance address in the [project settings](h
|
|
|
36
64
|
|
|
37
65
|
The Python SDK includes an asyncio-native client in version `7.45.0` and later. Continue to use `Posthog` in synchronous apps. For an asyncio app, install the optional async dependencies:
|
|
38
66
|
|
|
39
|
-
Terminal
|
|
40
|
-
|
|
41
67
|
```bash
|
|
42
68
|
pip install "posthog[async]>=7.45.0"
|
|
43
69
|
```
|
|
44
70
|
|
|
45
71
|
Import `AsyncPosthog`, the customer-facing name for `AsyncClient`. Both names provide the same async context manager and lifecycle methods. Keep one client for the lifetime of your app. For example, use a FastAPI lifespan handler:
|
|
46
72
|
|
|
47
|
-
Python
|
|
48
|
-
|
|
49
73
|
```python
|
|
50
74
|
import os
|
|
51
75
|
from contextlib import asynccontextmanager
|
|
@@ -72,8 +96,6 @@ Exiting the context calls `shutdown()`. This flushes buffered events, waits for
|
|
|
72
96
|
|
|
73
97
|
`capture()` queues an event and returns without waiting for a network request. Don't await it:
|
|
74
98
|
|
|
75
|
-
Python
|
|
76
|
-
|
|
77
99
|
```python
|
|
78
100
|
posthog.capture(
|
|
79
101
|
"event_name",
|
|
@@ -84,8 +106,6 @@ posthog.capture(
|
|
|
84
106
|
|
|
85
107
|
Use `capture_immediate()` when your code must wait for that event's delivery attempt:
|
|
86
108
|
|
|
87
|
-
Python
|
|
88
|
-
|
|
89
109
|
```python
|
|
90
110
|
capture_id = await posthog.capture_immediate(
|
|
91
111
|
"event_name",
|
|
@@ -97,8 +117,6 @@ capture_id = await posthog.capture_immediate(
|
|
|
97
117
|
|
|
98
118
|
Await `evaluate_flags()` once, then use its snapshot with synchronous in-memory accessors. Pass the same snapshot to `capture()` to attach the exact values used for branching without another feature flag request:
|
|
99
119
|
|
|
100
|
-
Python
|
|
101
|
-
|
|
102
120
|
```python
|
|
103
121
|
flags = await posthog.evaluate_flags("user-distinct-id")
|
|
104
122
|
|
|
@@ -117,15 +135,13 @@ The snapshot provides synchronous `is_enabled()`, `get_flag()`, and `get_flag_pa
|
|
|
117
135
|
|
|
118
136
|
### Fetch remote config
|
|
119
137
|
|
|
120
|
-
Initialize the client with a server-side [
|
|
121
|
-
|
|
122
|
-
Python
|
|
138
|
+
Initialize the client with a server-side [secret API key](https://posthog.com/docs/feature-flags/remote-config.md#step-1-get-a-secret-api-key) as `secret_key`, then await the remote config request:
|
|
123
139
|
|
|
124
140
|
```python
|
|
125
141
|
config = await posthog.get_remote_config_payload("landing-page-config")
|
|
126
142
|
```
|
|
127
143
|
|
|
128
|
-
See [Remote config](/docs/feature-flags/remote-config.md) for setup and security details.
|
|
144
|
+
See [Remote config](https://posthog.com/docs/feature-flags/remote-config.md) for setup and security details.
|
|
129
145
|
|
|
130
146
|
## Identifying users
|
|
131
147
|
|
|
@@ -133,8 +149,6 @@ See [Remote config](/docs/feature-flags/remote-config.md) for setup and security
|
|
|
133
149
|
>
|
|
134
150
|
> In Python, you can do this through a context. All event captures in the same context will be tagged automatically with the correct `distinct_id`. Typically, you would set a fresh context and identify at the top of each route.
|
|
135
151
|
>
|
|
136
|
-
> Python
|
|
137
|
-
>
|
|
138
152
|
> ```python
|
|
139
153
|
> from posthog import new_context, identify_context, capture
|
|
140
154
|
>
|
|
@@ -152,8 +166,6 @@ See [Remote config](/docs/feature-flags/remote-config.md) for setup and security
|
|
|
152
166
|
|
|
153
167
|
You can send custom events using `capture`:
|
|
154
168
|
|
|
155
|
-
Python
|
|
156
|
-
|
|
157
169
|
```python
|
|
158
170
|
# Events captured with no context or explicit distinct_id are marked as personless and have an auto-generated distinct_id:
|
|
159
171
|
posthog.capture('some-anon-event')
|
|
@@ -171,13 +183,11 @@ with new_context():
|
|
|
171
183
|
|
|
172
184
|
> **Tip:** We recommend using a `[object] [verb]` format for your event names, where `[object]` is the entity that the behavior relates to, and `[verb]` is the behavior itself. For example, `project created`, `user signed up`, or `invite sent`.
|
|
173
185
|
|
|
174
|
-
> **Tip:** You can define event schemas with typed properties and generate type-safe code using [schema management](/docs/product-analytics/schema-management.md).
|
|
186
|
+
> **Tip:** You can define event schemas with typed properties and generate type-safe code using [schema management](https://posthog.com/docs/product-analytics/schema-management.md).
|
|
175
187
|
|
|
176
188
|
### Setting event properties
|
|
177
189
|
|
|
178
|
-
Optionally, you can include additional information with the event by including a [properties](/docs/data/events.md#event-properties) object:
|
|
179
|
-
|
|
180
|
-
Python
|
|
190
|
+
Optionally, you can include additional information with the event by including a [properties](https://posthog.com/docs/data/events.md#event-properties) object:
|
|
181
191
|
|
|
182
192
|
```python
|
|
183
193
|
posthog.capture(
|
|
@@ -194,17 +204,13 @@ posthog.capture(
|
|
|
194
204
|
|
|
195
205
|
If you're aiming for a backend-only implementation of PostHog and won't be capturing events from your frontend, you can send `pageviews` from your backend like so:
|
|
196
206
|
|
|
197
|
-
Python
|
|
198
|
-
|
|
199
207
|
```python
|
|
200
208
|
posthog.capture('$pageview', distinct_id="distinct_id_of_the_user", properties={'$current_url': 'https://example.com'})
|
|
201
209
|
```
|
|
202
210
|
|
|
203
211
|
## Person profiles and properties
|
|
204
212
|
|
|
205
|
-
The Python SDK captures identified events if the current context is identified or if you pass a distinct ID explicitly. These create [person profiles](/docs/data/persons.md). To set [person properties](/docs/product-analytics/person-properties.md) in these profiles, include them when capturing an event:
|
|
206
|
-
|
|
207
|
-
Python
|
|
213
|
+
The Python SDK captures identified events if the current context is identified or if you pass a distinct ID explicitly. These create [person profiles](https://posthog.com/docs/data/persons.md). To set [person properties](https://posthog.com/docs/product-analytics/person-properties.md) in these profiles, include them when capturing an event:
|
|
208
214
|
|
|
209
215
|
```python
|
|
210
216
|
# Passing a distinct id explicitly
|
|
@@ -224,11 +230,9 @@ with new_context():
|
|
|
224
230
|
posthog.capture('event_name')
|
|
225
231
|
```
|
|
226
232
|
|
|
227
|
-
For more details on the difference between `$set` and `$set_once`, see our [person properties docs](/docs/product-analytics/person-properties.md#what-is-the-difference-between-set-and-set_once).
|
|
228
|
-
|
|
229
|
-
To capture [anonymous events](/docs/data/anonymous-vs-identified-events.md) without person profiles, set the event's `$process_person_profile` property to `False`. Events captured with no context or explicit distinct\_id are marked as personless, and will have an auto-generated distinct\_id:
|
|
233
|
+
For more details on the difference between `$set` and `$set_once`, see our [person properties docs](https://posthog.com/docs/product-analytics/person-properties.md#what-is-the-difference-between-set-and-set_once).
|
|
230
234
|
|
|
231
|
-
|
|
235
|
+
To capture [anonymous events](https://posthog.com/docs/data/anonymous-vs-identified-events.md) without person profiles, set the event's `$process_person_profile` property to `False`. Events captured with no context or explicit distinct\_id are marked as personless, and will have an auto-generated distinct\_id:
|
|
232
236
|
|
|
233
237
|
```python
|
|
234
238
|
posthog.capture(
|
|
@@ -245,24 +249,20 @@ Sometimes, you want to assign multiple distinct IDs to a single user. This is he
|
|
|
245
249
|
|
|
246
250
|
In this case, you can use `alias` to assign another distinct ID to the same user.
|
|
247
251
|
|
|
248
|
-
Python
|
|
249
|
-
|
|
250
252
|
```python
|
|
251
253
|
posthog.alias(previous_id='distinct_id', distinct_id='alias_id')
|
|
252
254
|
```
|
|
253
255
|
|
|
254
|
-
We strongly recommend reading our docs on [alias](/docs/product-analytics/identify.md#alias-assigning-multiple-distinct-ids-to-the-same-user) to best understand how to correctly use this method.
|
|
256
|
+
We strongly recommend reading our docs on [alias](https://posthog.com/docs/product-analytics/identify.md#alias-assigning-multiple-distinct-ids-to-the-same-user) to best understand how to correctly use this method.
|
|
255
257
|
|
|
256
258
|
## Contexts
|
|
257
259
|
|
|
258
260
|
The Python SDK uses nested contexts for managing state that's shared across events. Contexts are the recommended way to manage things like "which user is taking this action" (through `identify_context`), rather than manually passing user state through your apps stack.
|
|
259
261
|
|
|
260
|
-
When events (including exceptions) are captured in a context, the event uses the user [distinct ID](/docs/getting-started/identify-users.md), [session ID](/docs/data/sessions.md), and tags that are (optionally) set in the context. This is useful for adding properties to multiple events during a single user's interaction with your product.
|
|
262
|
+
When events (including exceptions) are captured in a context, the event uses the user [distinct ID](https://posthog.com/docs/getting-started/identify-users.md), [session ID](https://posthog.com/docs/data/sessions.md), and tags that are (optionally) set in the context. This is useful for adding properties to multiple events during a single user's interaction with your product.
|
|
261
263
|
|
|
262
264
|
You can enter a context using the `with` statement:
|
|
263
265
|
|
|
264
|
-
Python
|
|
265
|
-
|
|
266
266
|
```python
|
|
267
267
|
from posthog import new_context, tag, set_context_session, identify_context
|
|
268
268
|
|
|
@@ -283,8 +283,6 @@ with new_context():
|
|
|
283
283
|
|
|
284
284
|
Contexts are persisted across function calls. If you enter one and then call a function and capture an event in the called function, it uses the context tags and session ID set in the parent context:
|
|
285
285
|
|
|
286
|
-
Python
|
|
287
|
-
|
|
288
286
|
```python
|
|
289
287
|
from posthog import new_context, tag
|
|
290
288
|
|
|
@@ -301,8 +299,6 @@ def outer_function():
|
|
|
301
299
|
|
|
302
300
|
Contexts are nested, so tags added to a parent context are inherited by child contexts. If you set the same tag in both a parent and child context, the child context's value overrides the parent's at event capture (but the parent context won't be affected). This nesting also applies to session IDs and distinct IDs.
|
|
303
301
|
|
|
304
|
-
Python
|
|
305
|
-
|
|
306
302
|
```python
|
|
307
303
|
from posthog import new_context, tag
|
|
308
304
|
|
|
@@ -320,8 +316,6 @@ with new_context():
|
|
|
320
316
|
|
|
321
317
|
You can disable this nesting behavior by passing `fresh=True` to `new_context`:
|
|
322
318
|
|
|
323
|
-
Python
|
|
324
|
-
|
|
325
319
|
```python
|
|
326
320
|
from posthog import new_context, tag
|
|
327
321
|
|
|
@@ -337,8 +331,6 @@ with new_context(fresh=True):
|
|
|
337
331
|
|
|
338
332
|
Contexts can be associated with a distinct ID by calling `posthog.identify_context`:
|
|
339
333
|
|
|
340
|
-
Python
|
|
341
|
-
|
|
342
334
|
```python
|
|
343
335
|
from posthog import identify_context
|
|
344
336
|
|
|
@@ -347,8 +339,6 @@ identify_context("distinct-id")
|
|
|
347
339
|
|
|
348
340
|
Within a context associated with a distinct ID, all events captured are associated with that user. You can override the distinct ID for a specific event by passing a `distinct_id` argument to `capture`:
|
|
349
341
|
|
|
350
|
-
Python
|
|
351
|
-
|
|
352
342
|
```python
|
|
353
343
|
from posthog import new_context, identify_context
|
|
354
344
|
|
|
@@ -360,14 +350,12 @@ with new_context():
|
|
|
360
350
|
|
|
361
351
|
It's recommended to pass the currently active distinct ID from the frontend to the backend, using the `X-POSTHOG-DISTINCT-ID` header. If you're using our Django middleware, this is extracted and associated with the request handler context automatically.
|
|
362
352
|
|
|
363
|
-
You can read more about identifying users in the [user identification documentation](/docs/product-analytics/identify.md).
|
|
353
|
+
You can read more about identifying users in the [user identification documentation](https://posthog.com/docs/product-analytics/identify.md).
|
|
364
354
|
|
|
365
355
|
### Contexts and sessions
|
|
366
356
|
|
|
367
357
|
Contexts can be associated with a session ID by calling `posthog.set_context_session`. When linking backend events to frontend sessions, use the session ID from the frontend SDK (PostHog session IDs are UUIDv7 strings).
|
|
368
358
|
|
|
369
|
-
Python
|
|
370
|
-
|
|
371
359
|
```python
|
|
372
360
|
from posthog import new_context, set_context_session
|
|
373
361
|
with new_context():
|
|
@@ -376,7 +364,7 @@ with new_context():
|
|
|
376
364
|
|
|
377
365
|
**Using PostHog on your frontend too?**
|
|
378
366
|
|
|
379
|
-
If you're using the PostHog JavaScript Web SDK on your frontend, it generates a session ID for you. Configure [`tracing_headers`](/docs/libraries/js/config.md#tracing-headers) for your backend hostname to add the session and distinct ID headers to browser requests automatically.
|
|
367
|
+
If you're using the PostHog JavaScript Web SDK on your frontend, it generates a session ID for you. Configure [`tracing_headers`](https://posthog.com/docs/libraries/js/config.md#tracing-headers) for your backend hostname to add the session and distinct ID headers to browser requests automatically.
|
|
380
368
|
|
|
381
369
|
You need to extract the header in your request handler (if you're using our Django middleware integration, this happens automatically).
|
|
382
370
|
|
|
@@ -385,13 +373,11 @@ If you associate a context with a session, you'll be able to do things like:
|
|
|
385
373
|
- See backend events on the session timeline when viewing session replays
|
|
386
374
|
- View session replays for users that triggered a backend exception in error tracking
|
|
387
375
|
|
|
388
|
-
You can read more about sessions in the [session tracking](/docs/data/sessions.md) documentation.
|
|
376
|
+
You can read more about sessions in the [session tracking](https://posthog.com/docs/data/sessions.md) documentation.
|
|
389
377
|
|
|
390
378
|
### Exception capture
|
|
391
379
|
|
|
392
|
-
By default exceptions raised within a context are captured and available in the [error tracking](/docs/error-tracking.md) dashboard. You can override this behavior by passing `capture_exceptions=False` to `new_context`:
|
|
393
|
-
|
|
394
|
-
Python
|
|
380
|
+
By default exceptions raised within a context are captured and available in the [error tracking](https://posthog.com/docs/error-tracking.md) dashboard. You can override this behavior by passing `capture_exceptions=False` to `new_context`:
|
|
395
381
|
|
|
396
382
|
```python
|
|
397
383
|
from posthog import new_context, tag
|
|
@@ -410,8 +396,6 @@ with new_context(capture_exceptions=False):
|
|
|
410
396
|
|
|
411
397
|
The SDK exposes a function decorator. It takes the same `fresh` and `capture_exceptions` arguments as `new_context` and provides a handy way to mark a whole function as being in a new context. For example:
|
|
412
398
|
|
|
413
|
-
Python
|
|
414
|
-
|
|
415
399
|
```python
|
|
416
400
|
from posthog import scoped, identify_context
|
|
417
401
|
|
|
@@ -424,22 +408,18 @@ def process_order(user, order_id):
|
|
|
424
408
|
|
|
425
409
|
## Group analytics
|
|
426
410
|
|
|
427
|
-
Group analytics allows you to associate an event with a group (e.g. teams, organizations, etc.). Read the [Group Analytics](/docs/user-guides/group-analytics.md) guide for more information.
|
|
411
|
+
Group analytics allows you to associate an event with a group (e.g. teams, organizations, etc.). Read the [Group Analytics](https://posthog.com/docs/user-guides/group-analytics.md) guide for more information.
|
|
428
412
|
|
|
429
|
-
> **Note:** This is a paid feature and is not available on the open-source or free cloud plan. Learn more on our [pricing page](/pricing.md).
|
|
413
|
+
> **Note:** This is a paid feature and is not available on the open-source or free cloud plan. Learn more on our [pricing page](https://posthog.com/pricing.md).
|
|
430
414
|
|
|
431
415
|
To capture an event and associate it with a group:
|
|
432
416
|
|
|
433
|
-
Python
|
|
434
|
-
|
|
435
417
|
```python
|
|
436
418
|
posthog.capture('some_event', groups={'company': 'company_id_in_your_db'})
|
|
437
419
|
```
|
|
438
420
|
|
|
439
421
|
To update properties on a group:
|
|
440
422
|
|
|
441
|
-
Python
|
|
442
|
-
|
|
443
423
|
```python
|
|
444
424
|
posthog.group_identify('company', 'company_id_in_your_db', {
|
|
445
425
|
'name': 'Awesome Inc.',
|
|
@@ -453,7 +433,7 @@ The `name` is a special property which is used in the PostHog UI for the name of
|
|
|
453
433
|
|
|
454
434
|
The examples in this section use the synchronous `Posthog` client. For `AsyncPosthog`, use the [awaited feature flag example](#evaluate-feature-flags). The returned snapshot uses the same accessors.
|
|
455
435
|
|
|
456
|
-
PostHog's [feature flags](/docs/feature-flags.md) enable you to safely deploy and roll back new features as well as target specific users and groups with them.
|
|
436
|
+
PostHog's [feature flags](https://posthog.com/docs/feature-flags.md) enable you to safely deploy and roll back new features as well as target specific users and groups with them.
|
|
457
437
|
|
|
458
438
|
There are two steps to implement feature flags in Python:
|
|
459
439
|
|
|
@@ -463,8 +443,6 @@ Call `posthog.evaluate_flags()` once for the user, then read values from the ret
|
|
|
463
443
|
|
|
464
444
|
#### Boolean feature flags
|
|
465
445
|
|
|
466
|
-
Python
|
|
467
|
-
|
|
468
446
|
```python
|
|
469
447
|
flags = posthog.evaluate_flags("distinct_id_of_your_user")
|
|
470
448
|
|
|
@@ -476,8 +454,6 @@ if flags.is_enabled("flag-key"):
|
|
|
476
454
|
|
|
477
455
|
#### Multivariate feature flags
|
|
478
456
|
|
|
479
|
-
Python
|
|
480
|
-
|
|
481
457
|
```python
|
|
482
458
|
flags = posthog.evaluate_flags("distinct_id_of_your_user")
|
|
483
459
|
|
|
@@ -495,9 +471,9 @@ if enabled_variant == "variant-key": # replace "variant-key" with the key of yo
|
|
|
495
471
|
|
|
496
472
|
### Step 2: Include feature flag information when capturing events
|
|
497
473
|
|
|
498
|
-
If you want use your feature flag to breakdown or filter events in your [insights](/docs/product-analytics/insights.md), you'll need to include feature flag information in those events. This ensures that the feature flag value is attributed correctly to the event.
|
|
474
|
+
If you want use your feature flag to breakdown or filter events in your [insights](https://posthog.com/docs/product-analytics/insights.md), you'll need to include feature flag information in those events. This ensures that the feature flag value is attributed correctly to the event.
|
|
499
475
|
|
|
500
|
-
> **Note:** This step is only required for events captured using our server-side SDKs or [API](/docs/api.md).
|
|
476
|
+
> **Note:** This step is only required for events captured using our server-side SDKs or [API](https://posthog.com/docs/api.md).
|
|
501
477
|
|
|
502
478
|
There are two methods you can use to include feature flag information in your events:
|
|
503
479
|
|
|
@@ -505,8 +481,6 @@ There are two methods you can use to include feature flag information in your ev
|
|
|
505
481
|
|
|
506
482
|
Pass the same `flags` object that you used for branching. This attaches the exact flag values from that evaluation and doesn't make another `/flags` request.
|
|
507
483
|
|
|
508
|
-
Python
|
|
509
|
-
|
|
510
484
|
```python
|
|
511
485
|
flags = posthog.evaluate_flags("distinct_id_of_your_user")
|
|
512
486
|
|
|
@@ -525,8 +499,6 @@ By default, this attaches every flag in the snapshot using `$feature/<flag-key>`
|
|
|
525
499
|
|
|
526
500
|
To reduce event property bloat, pass a filtered snapshot:
|
|
527
501
|
|
|
528
|
-
Python
|
|
529
|
-
|
|
530
502
|
```python
|
|
531
503
|
# Attach only flags accessed with is_enabled() or get_flag() before this call
|
|
532
504
|
posthog.capture(
|
|
@@ -549,8 +521,6 @@ posthog.capture(
|
|
|
549
521
|
|
|
550
522
|
In the event properties, include `$feature/feature_flag_name: variant_key`:
|
|
551
523
|
|
|
552
|
-
Python
|
|
553
|
-
|
|
554
524
|
```python
|
|
555
525
|
posthog.capture(
|
|
556
526
|
"event_name",
|
|
@@ -566,8 +536,6 @@ posthog.capture(
|
|
|
566
536
|
|
|
567
537
|
By default, `posthog.evaluate_flags()` evaluates every flag for the user. If you only need a few flags, pass `flag_keys` to request only those flags:
|
|
568
538
|
|
|
569
|
-
Python
|
|
570
|
-
|
|
571
539
|
```python
|
|
572
540
|
flags = posthog.evaluate_flags(
|
|
573
541
|
"distinct_id_of_your_user",
|
|
@@ -577,7 +545,7 @@ flags = posthog.evaluate_flags(
|
|
|
577
545
|
|
|
578
546
|
### Sending `$feature_flag_called` events
|
|
579
547
|
|
|
580
|
-
Capturing `$feature_flag_called` events enables PostHog to know when a flag was accessed by a user and provide [analytics and insights](/docs/product-analytics/insights.md) on the flag. With `posthog.evaluate_flags()`, the SDK sends this event when you call `flags.is_enabled()` or `flags.get_flag()` for a flag.
|
|
548
|
+
Capturing `$feature_flag_called` events enables PostHog to know when a flag was accessed by a user and provide [analytics and insights](https://posthog.com/docs/product-analytics/insights.md) on the flag. With `posthog.evaluate_flags()`, the SDK sends this event when you call `flags.is_enabled()` or `flags.get_flag()` for a flag.
|
|
581
549
|
|
|
582
550
|
The SDK deduplicates these events per `(distinct_id, flag, value)` in a local cache. If you reinitialize the PostHog client, the cache resets and `$feature_flag_called` events may be sent again. PostHog handles duplicates, so duplicate `$feature_flag_called` events don't affect your analytics.
|
|
583
551
|
|
|
@@ -585,14 +553,12 @@ The SDK deduplicates these events per `(distinct_id, flag, value)` in a local ca
|
|
|
585
553
|
|
|
586
554
|
### Advanced: Overriding server properties
|
|
587
555
|
|
|
588
|
-
Sometimes, you may want to evaluate feature flags using [person properties](/docs/product-analytics/person-properties.md), [groups](/docs/product-analytics/group-analytics.md), or group properties that haven't been ingested yet, or were set incorrectly earlier.
|
|
556
|
+
Sometimes, you may want to evaluate feature flags using [person properties](https://posthog.com/docs/product-analytics/person-properties.md), [groups](https://posthog.com/docs/product-analytics/group-analytics.md), or group properties that haven't been ingested yet, or were set incorrectly earlier.
|
|
589
557
|
|
|
590
558
|
You can provide properties to evaluate the flag with by using the `person properties`, `groups`, and `group properties` arguments. PostHog will then use these values to evaluate the flag, instead of any properties currently stored on your PostHog server.
|
|
591
559
|
|
|
592
560
|
For example:
|
|
593
561
|
|
|
594
|
-
Python
|
|
595
|
-
|
|
596
562
|
```python
|
|
597
563
|
flags = posthog.evaluate_flags(
|
|
598
564
|
"distinct_id_of_the_user",
|
|
@@ -642,8 +608,6 @@ Simply include any of these properties in the `person_properties` parameter alon
|
|
|
642
608
|
|
|
643
609
|
You can configure the `feature_flags_request_timeout_seconds` parameter when initializing your PostHog client to set a flag request timeout. This helps prevent your code from being blocked if PostHog's servers are too slow to respond. By default, this is set to 3 seconds.
|
|
644
610
|
|
|
645
|
-
Python
|
|
646
|
-
|
|
647
611
|
```python
|
|
648
612
|
posthog = Posthog(
|
|
649
613
|
"<ph_project_token>",
|
|
@@ -658,17 +622,15 @@ Evaluating feature flags requires making a request to PostHog for each flag. How
|
|
|
658
622
|
|
|
659
623
|
It is best practice to use local evaluation flags when possible, since this enables you to resolve flags faster and with fewer API calls.
|
|
660
624
|
|
|
661
|
-
For details on how to implement local evaluation, see our [local evaluation guide](/docs/feature-flags/local-evaluation.md).
|
|
625
|
+
For details on how to implement local evaluation, see our [local evaluation guide](https://posthog.com/docs/feature-flags/local-evaluation.md).
|
|
662
626
|
|
|
663
627
|
#### Distributed environments
|
|
664
628
|
|
|
665
|
-
In multi-worker or edge environments, you can implement custom caching for flag definitions using Redis, Cloudflare KV, or other storage backends. This enables sharing definitions across workers and coordinating fetches. See our guide for [local evaluation in distributed environments](/docs/feature-flags/local-evaluation/distributed-environments?tab=Python.md) for details.
|
|
629
|
+
In multi-worker or edge environments, you can implement custom caching for flag definitions using Redis, Cloudflare KV, or other storage backends. This enables sharing definitions across workers and coordinating fetches. See our guide for [local evaluation in distributed environments](https://posthog.com/docs/feature-flags/local-evaluation/distributed-environments?tab=Python.md) for details.
|
|
666
630
|
|
|
667
631
|
## Experiments (A/B tests)
|
|
668
632
|
|
|
669
|
-
Since [experiments](/docs/experiments/start-here.md) use feature flags, the code for running an experiment is very similar to the feature flags code. This example uses the synchronous `Posthog` client:
|
|
670
|
-
|
|
671
|
-
Python
|
|
633
|
+
Since [experiments](https://posthog.com/docs/experiments/start-here.md) use feature flags, the code for running an experiment is very similar to the feature flags code. This example uses the synchronous `Posthog` client:
|
|
672
634
|
|
|
673
635
|
```python
|
|
674
636
|
flags = posthog.evaluate_flags("user_distinct_id")
|
|
@@ -680,17 +642,15 @@ if variant == "variant-name":
|
|
|
680
642
|
|
|
681
643
|
With `AsyncPosthog`, await the evaluation: `flags = await posthog.evaluate_flags("user_distinct_id")`. The remaining snapshot access is the same.
|
|
682
644
|
|
|
683
|
-
It's also possible to [run experiments without using feature flags](/docs/experiments/running-experiments-without-feature-flags.md).
|
|
645
|
+
It's also possible to [run experiments without using feature flags](https://posthog.com/docs/experiments/running-experiments-without-feature-flags.md).
|
|
684
646
|
|
|
685
647
|
## AI Observability
|
|
686
648
|
|
|
687
|
-
Our Python SDK includes a built-in AI Observability feature. It enables you to capture LLM usage, performance, and more. Check out our [analytics docs](/docs/ai-observability.md) for more details on setting it up.
|
|
649
|
+
Our Python SDK includes a built-in AI Observability feature. It enables you to capture LLM usage, performance, and more. Check out our [analytics docs](https://posthog.com/docs/ai-observability.md) for more details on setting it up.
|
|
688
650
|
|
|
689
651
|
## Error tracking
|
|
690
652
|
|
|
691
|
-
You can [autocapture exceptions](/docs/error-tracking/installation.md) by setting the `enable_exception_autocapture` argument to `True` when initializing the PostHog client.
|
|
692
|
-
|
|
693
|
-
Python
|
|
653
|
+
You can [autocapture exceptions](https://posthog.com/docs/error-tracking/installation.md) by setting the `enable_exception_autocapture` argument to `True` when initializing the PostHog client.
|
|
694
654
|
|
|
695
655
|
```python
|
|
696
656
|
from posthog import Posthog
|
|
@@ -700,8 +660,6 @@ posthog = Posthog("<ph_project_token>", enable_exception_autocapture=True, ...)
|
|
|
700
660
|
|
|
701
661
|
You can also manually capture exceptions using the `capture_exception` method:
|
|
702
662
|
|
|
703
|
-
Python
|
|
704
|
-
|
|
705
663
|
```python
|
|
706
664
|
posthog.capture_exception(e, distinct_id='user_distinct_id', properties=additional_properties)
|
|
707
665
|
```
|
|
@@ -712,8 +670,6 @@ Contexts automatically capture exceptions thrown inside them, unless disable it
|
|
|
712
670
|
|
|
713
671
|
The Python SDK can automatically capture the state of local variables when an exception occurs. This gives you a debugger-like view of your application state at the time of the error:
|
|
714
672
|
|
|
715
|
-
Python
|
|
716
|
-
|
|
717
673
|
```python
|
|
718
674
|
posthog = Posthog(
|
|
719
675
|
"<ph_project_token>",
|
|
@@ -722,7 +678,7 @@ posthog = Posthog(
|
|
|
722
678
|
)
|
|
723
679
|
```
|
|
724
680
|
|
|
725
|
-
You can configure which variables are captured, masked, or ignored. See the [code variables documentation](/docs/error-tracking/code-variables/python.md) for detailed configuration options.
|
|
681
|
+
You can configure which variables are captured, masked, or ignored. See the [code variables documentation](https://posthog.com/docs/error-tracking/code-variables/python.md) for detailed configuration options.
|
|
726
682
|
|
|
727
683
|
## Distributed tracing
|
|
728
684
|
|
|
@@ -734,9 +690,7 @@ Tracing is new in the Python SDK and its API can still change in a minor release
|
|
|
734
690
|
|
|
735
691
|
Tracing records **spans** – timed units of work – so you can see where time went in a request and how work fans out across your services. Spans created inside a [context](#contexts) automatically carry the person and session they belong to, so a slow trace links back to the person who experienced it.
|
|
736
692
|
|
|
737
|
-
Tracing is off until you set the `traces` option. No OpenTelemetry dependency is required. For what you can do with spans once they arrive, see [Distributed tracing](/docs/distributed-tracing/start-here.md).
|
|
738
|
-
|
|
739
|
-
Python
|
|
693
|
+
Tracing is off until you set the `traces` option. No OpenTelemetry dependency is required. For what you can do with spans once they arrive, see [Distributed tracing](https://posthog.com/docs/distributed-tracing/start-here.md).
|
|
740
694
|
|
|
741
695
|
```python
|
|
742
696
|
from posthog import Posthog
|
|
@@ -758,8 +712,6 @@ Tracing is available on the synchronous `Posthog` client and the module-level AP
|
|
|
758
712
|
|
|
759
713
|
`start_span` returns a span. Use it in a `with` block to make it the active span for the block and end it when the block exits. Spans started inside the block nest underneath it automatically.
|
|
760
714
|
|
|
761
|
-
Python
|
|
762
|
-
|
|
763
715
|
```python
|
|
764
716
|
with posthog.start_span("POST /checkout", kind="server") as span:
|
|
765
717
|
span.set_attribute("plan", user.plan)
|
|
@@ -776,8 +728,6 @@ The recorded exception includes the stack trace, which contains file paths from
|
|
|
776
728
|
|
|
777
729
|
For work that can't wrap a block, call `start_span` without `with`. **A span started this way isn't active**, so spans started afterwards aren't its children unless you pass `parent` explicitly – and you must call `end()` yourself.
|
|
778
730
|
|
|
779
|
-
Python
|
|
780
|
-
|
|
781
731
|
```python
|
|
782
732
|
span = posthog.start_span("background-sync", attributes={"queue": "emails"})
|
|
783
733
|
try:
|
|
@@ -798,8 +748,6 @@ The active span is tracked with [`contextvars`](https://docs.python.org/3/librar
|
|
|
798
748
|
|
|
799
749
|
Span names should be low-cardinality operation names – `GET /users/:id`, not `GET /users/123`. Variable values belong in attributes. Strings, booleans, integers, and floats keep their type. Lists and dictionaries are sent as arrays and maps, but PostHog stores them as serialized strings. Setting an attribute to `None` removes it, and any other value is converted to a string.
|
|
800
750
|
|
|
801
|
-
Python
|
|
802
|
-
|
|
803
751
|
```python
|
|
804
752
|
with posthog.start_span("GET /users/:id", kind="server") as span:
|
|
805
753
|
span.set_attributes({"user.id": user_id, "db.rows": len(rows)})
|
|
@@ -867,9 +815,7 @@ A continued trace propagates the sampled flag it was handed, so a downstream sam
|
|
|
867
815
|
|
|
868
816
|
### Linking traces to people and sessions
|
|
869
817
|
|
|
870
|
-
Spans created inside a [context](#contexts) that has a distinct ID or session ID automatically carry `posthogDistinctId` and `sessionId` attributes, which is what makes a trace reachable from a person or a Session Replay recording. In Django, the [contexts middleware](/docs/libraries/django.md#django-contexts-middleware) sets these for every request. Elsewhere, set them yourself:
|
|
871
|
-
|
|
872
|
-
Python
|
|
818
|
+
Spans created inside a [context](#contexts) that has a distinct ID or session ID automatically carry `posthogDistinctId` and `sessionId` attributes, which is what makes a trace reachable from a person or a Session Replay recording. In Django, the [contexts middleware](https://posthog.com/docs/libraries/django.md#django-contexts-middleware) sets these for every request. Elsewhere, set them yourself:
|
|
873
819
|
|
|
874
820
|
```python
|
|
875
821
|
from posthog import new_context, identify_context, set_context_session
|
|
@@ -888,8 +834,6 @@ Spans created outside a context with those values omit the attributes.
|
|
|
888
834
|
|
|
889
835
|
`before_span_send` runs on every finished span before it's queued for export. It receives the span as a dict with `name`, `kind`, `status`, `attributes`, `events`, `start_time_ns`, `end_time_ns`, `trace_id`, `span_id`, and `parent_span_id`. Edit it and return it, or return `None` to drop the span entirely.
|
|
890
836
|
|
|
891
|
-
Python
|
|
892
|
-
|
|
893
837
|
```python
|
|
894
838
|
def scrub_spans(span):
|
|
895
839
|
if span["attributes"].get("http.route") == "/health":
|
|
@@ -951,15 +895,15 @@ An invalid value falls back to its default with a warning. The exception is `bef
|
|
|
951
895
|
|
|
952
896
|
Spans are exported on a background interval, even with `sync_mode` on. Both `flush()` and `shutdown()` export spans that have already ended. A span still open at `flush()` is exported once it ends; a span still open at `shutdown()` is discarded with a warning, so end your spans before shutting down – a `with` block does this for you. `shutdown()` gives queued spans up to 30 seconds to send.
|
|
953
897
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
Python
|
|
898
|
+
If your serverless handler reuses a client across invocations, call `flush()` before returning. It flushes events and ended spans concurrently without stopping the client. Reserve `shutdown()` for a disposable client or process exit.
|
|
957
899
|
|
|
958
900
|
```python
|
|
959
901
|
def handler(event, context):
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
902
|
+
try:
|
|
903
|
+
with posthog.start_span("handler"):
|
|
904
|
+
do_work()
|
|
905
|
+
finally:
|
|
906
|
+
posthog.flush()
|
|
963
907
|
```
|
|
964
908
|
|
|
965
909
|
A script that exits without calling `shutdown()` still gets a brief best-effort flush at exit, but don't rely on it for spans you need.
|
|
@@ -972,8 +916,6 @@ As of posthog-python v3.0, the default now is to disregard the server IP, not ad
|
|
|
972
916
|
|
|
973
917
|
You can go back to previous behavior by doing setting the `disable_geoip` argument in your initialization to `False`:
|
|
974
918
|
|
|
975
|
-
Python
|
|
976
|
-
|
|
977
919
|
```python
|
|
978
920
|
posthog = Posthog('api_key', disable_geoip=False)
|
|
979
921
|
```
|
|
@@ -990,8 +932,6 @@ The list of properties that this overrides:
|
|
|
990
932
|
|
|
991
933
|
You can also explicitly chose to enable or disable GeoIP for a single capture request like so:
|
|
992
934
|
|
|
993
|
-
Python
|
|
994
|
-
|
|
995
935
|
```python
|
|
996
936
|
posthog.capture('test_event', disable_geoip=True|False)
|
|
997
937
|
```
|
|
@@ -1002,8 +942,6 @@ If you're not seeing the expected events being captured, the feature flags being
|
|
|
1002
942
|
|
|
1003
943
|
You can enable debug mode by setting the `debug` option to `True` in the `PostHog` object. This will enable verbose logs about the inner workings of the SDK.
|
|
1004
944
|
|
|
1005
|
-
Python
|
|
1006
|
-
|
|
1007
945
|
```python
|
|
1008
946
|
posthog.debug = True
|
|
1009
947
|
```
|
|
@@ -1012,8 +950,6 @@ posthog.debug = True
|
|
|
1012
950
|
|
|
1013
951
|
You can disable requests during tests by setting the `disabled` option to `True` in the `PostHog` object. This means no events will be captured or no requests will be sent to PostHog.
|
|
1014
952
|
|
|
1015
|
-
Python
|
|
1016
|
-
|
|
1017
953
|
```python
|
|
1018
954
|
if settings.TEST:
|
|
1019
955
|
posthog.disabled = True
|
|
@@ -1029,8 +965,6 @@ You can configure connection behavior in several ways. The following settings sh
|
|
|
1029
965
|
|
|
1030
966
|
TCP keepalive probes help prevent idle connections from being dropped by network infrastructure. This is the recommended approach for most cases where idle connections are terminated.
|
|
1031
967
|
|
|
1032
|
-
Python
|
|
1033
|
-
|
|
1034
968
|
```python
|
|
1035
969
|
import posthog
|
|
1036
970
|
|
|
@@ -1043,8 +977,6 @@ This enables TCP keepalive with sensible defaults (60 second idle time, 60 secon
|
|
|
1043
977
|
|
|
1044
978
|
If you need each request to use a fresh connection, you can disable connection reuse entirely. This will incur additional overhead per request but may be desirable in some circumstances.
|
|
1045
979
|
|
|
1046
|
-
Python
|
|
1047
|
-
|
|
1048
980
|
```python
|
|
1049
981
|
import posthog
|
|
1050
982
|
|
|
@@ -1055,8 +987,6 @@ posthog.disable_connection_reuse()
|
|
|
1055
987
|
|
|
1056
988
|
For advanced use cases, you can configure arbitrary socket options on the underlying HTTP connection.
|
|
1057
989
|
|
|
1058
|
-
Python
|
|
1059
|
-
|
|
1060
990
|
```python
|
|
1061
991
|
import socket
|
|
1062
992
|
import posthog
|
|
@@ -1073,8 +1003,6 @@ Pass `None` to `set_socket_options()` to reset to default behavior.
|
|
|
1073
1003
|
|
|
1074
1004
|
Use `before_send` to modify or drop events before they are queued for delivery. Return the modified event dictionary to send it, or `None` to drop it.
|
|
1075
1005
|
|
|
1076
|
-
Python
|
|
1077
|
-
|
|
1078
1006
|
```python
|
|
1079
1007
|
from typing import Any
|
|
1080
1008
|
|
|
@@ -1104,7 +1032,7 @@ If your callback raises an exception, the SDK logs the error and continues with
|
|
|
1104
1032
|
|
|
1105
1033
|
## Historical migrations
|
|
1106
1034
|
|
|
1107
|
-
You can use the Python or Node SDK to run [historical migrations](/docs/migrate.md) of data into PostHog. To do so, set the `historical_migration` option to `true` when initializing the client.
|
|
1035
|
+
You can use the Python or Node SDK to run [historical migrations](https://posthog.com/docs/migrate.md) of data into PostHog. To do so, set the `historical_migration` option to `true` when initializing the client.
|
|
1108
1036
|
|
|
1109
1037
|
### Python
|
|
1110
1038
|
|
|
@@ -1181,12 +1109,13 @@ await client.shutdown()
|
|
|
1181
1109
|
|
|
1182
1110
|
### Synchronous `Posthog`
|
|
1183
1111
|
|
|
1184
|
-
By default, the synchronous `Posthog` client buffers events before sending them to the capture endpoint.
|
|
1112
|
+
By default, the synchronous `Posthog` client buffers events before sending them to the capture endpoint. A serverless platform can freeze or terminate the runtime before background delivery finishes.
|
|
1185
1113
|
|
|
1186
|
-
-
|
|
1187
|
-
-
|
|
1114
|
+
- For a client shared across invocations, call `posthog.flush()` before the handler returns, including when application code throws. This blocking call attempts to deliver queued events without stopping the client. Its `timeout_seconds` argument defaults to `10` seconds.
|
|
1115
|
+
- For a disposable client or process exit, call `posthog.shutdown()` after its final work. It attempts to deliver queued events and cleans up the client. Don't reuse the client afterward. Unlike Node's `shutdown()`, Python's `shutdown()` takes no timeout argument.
|
|
1116
|
+
- Alternatively, enable `sync_mode` when initializing the client so each `posthog.capture()` call attempts delivery before it returns.
|
|
1188
1117
|
|
|
1189
|
-
If you use [distributed tracing](#distributed-tracing), `sync_mode` doesn't apply to spans.
|
|
1118
|
+
These calls do not guarantee that PostHog received every event. If you use [distributed tracing](#distributed-tracing), `sync_mode` doesn't apply to spans. For a shared client, call `posthog.flush()` before the handler returns – see [Shutdown and short-lived processes](#shutdown-and-short-lived-processes).
|
|
1190
1119
|
|
|
1191
1120
|
### Asyncio `AsyncPosthog`
|
|
1192
1121
|
|
|
@@ -1194,7 +1123,38 @@ Keep one `AsyncPosthog` client for the lifetime of your application. Use buffere
|
|
|
1194
1123
|
|
|
1195
1124
|
## Django
|
|
1196
1125
|
|
|
1197
|
-
See our [Django docs](/docs/libraries/django.md) for how to set up PostHog in Django.
|
|
1126
|
+
See our [Django docs](https://posthog.com/docs/libraries/django.md) for how to set up PostHog in Django. The [Django contexts middleware](https://posthog.com/docs/libraries/django.md#django-contexts-middleware) adds request properties and authenticated user identity to events captured during a request. You can also opt in to browser session and distinct ID headers.
|
|
1127
|
+
|
|
1128
|
+
## ASGI request middleware
|
|
1129
|
+
|
|
1130
|
+
Version `7.69.0` and later of the Python SDK includes framework-independent ASGI middleware for FastAPI, Starlette, Litestar, and raw ASGI applications. It creates a PostHog context for each HTTP or WebSocket request, enriches captured events with request properties, and captures exceptions that escape the application.
|
|
1131
|
+
|
|
1132
|
+
For FastAPI or Starlette, add the middleware to your app:
|
|
1133
|
+
|
|
1134
|
+
```python
|
|
1135
|
+
from fastapi import FastAPI
|
|
1136
|
+
from posthog import Posthog
|
|
1137
|
+
from posthog.integrations.asgi import PosthogASGIMiddleware
|
|
1138
|
+
|
|
1139
|
+
posthog = Posthog(
|
|
1140
|
+
"<ph_project_token>",
|
|
1141
|
+
host="https://us.i.posthog.com",
|
|
1142
|
+
enable_exception_autocapture=True,
|
|
1143
|
+
)
|
|
1144
|
+
|
|
1145
|
+
app = FastAPI()
|
|
1146
|
+
app.add_middleware(PosthogASGIMiddleware, client=posthog)
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
The middleware's `capture_exceptions` option defaults to `None`, which inherits the client's `enable_exception_autocapture` setting. Set it to `True` or `False` to override the client. Use `request_filter` to skip selected requests and `extra_properties` to add properties from the ASGI scope. Both callbacks can be synchronous or asynchronous.
|
|
1150
|
+
|
|
1151
|
+
The middleware ignores `X-PostHog-Distinct-ID` and `X-PostHog-Session-ID` by default because clients can control them. Set `trust_tracing_headers=True` only when you want to accept these headers as analytics context. Don't use them for authentication or authorization.
|
|
1152
|
+
|
|
1153
|
+
To instrument another ASGI framework or a raw ASGI app, wrap the application directly:
|
|
1154
|
+
|
|
1155
|
+
```python
|
|
1156
|
+
app = PosthogASGIMiddleware(app, client=posthog)
|
|
1157
|
+
```
|
|
1198
1158
|
|
|
1199
1159
|
## Alternative name
|
|
1200
1160
|
|
|
@@ -1211,11 +1171,3 @@ These docs cover version `7.x` of the PostHog Python SDK, which requires Python
|
|
|
1211
1171
|
Everything on this page works the same way on `6.9.3`. Event capture, the context API (`new_context`, `identify_context`, `set_context_session`), and `PosthogContextMiddleware` are identical on `6.9.3` and `7.0.0` — `7.0.0` only dropped Python 3.9 and bumped the optional LLM provider SDKs. That includes the middleware identifying the request context from the `X-POSTHOG-DISTINCT-ID` header and falling back to the authenticated user, which behaves the same across both lines.
|
|
1212
1172
|
|
|
1213
1173
|
Later `7.x` releases add what the 6.x line does not receive, such as the Celery integration, tracing header sanitization, and `set_context_device_id`. They also changed the middleware's own captured properties: `7.x` sends the request IP as `$ip`, where `6.9.3` sends it as `$ip_address`, and `7.x` additionally captures `$request_path`, `$raw_user_agent`, and the authenticated user's `email`.
|
|
1214
|
-
|
|
1215
|
-
### Still have questions?
|
|
1216
|
-
|
|
1217
|
-
Ask PostHog AI
|
|
1218
|
-
|
|
1219
|
-
### Was this page useful?
|
|
1220
|
-
|
|
1221
|
-
HelpfulCould be better
|