Skip to content

Commit 2fe179a

Browse files
fix: pass before_send through module-level setup (#472)
1 parent d3f48e6 commit 2fe179a

3 files changed

Lines changed: 72 additions & 8 deletions

File tree

posthog/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
SocketOptions as SocketOptions,
5757
)
5858
from posthog.types import (
59+
BeforeSendCallback as BeforeSendCallback,
5960
FeatureFlag,
6061
FlagsAndPayloads,
6162
)
@@ -250,6 +251,7 @@ def get_tags() -> Dict[str, Any]:
250251
project_root = None # type: Optional[str]
251252
# Used for our AI observability feature to not capture any prompt or output just usage + metadata
252253
privacy_mode = False # type: bool
254+
before_send = None # type: Optional[BeforeSendCallback]
253255
# Whether to enable feature flag polling for local evaluation by default. Defaults to True.
254256
# We recommend setting this to False if you are only using the personalApiKey for evaluating remote config payloads via `get_remote_config_payload` and not using local evaluation.
255257
enable_local_evaluation = True # type: bool
@@ -875,6 +877,7 @@ def setup() -> Client:
875877
# or deprecate this proxy option fully (it's already in the process of deprecation, no new clients should be using this method since like 5-6 months)
876878
enable_exception_autocapture=enable_exception_autocapture,
877879
log_captured_exceptions=log_captured_exceptions,
880+
before_send=before_send,
878881
enable_local_evaluation=enable_local_evaluation,
879882
flag_definition_cache_provider=flag_definition_cache_provider,
880883
capture_exception_code_variables=capture_exception_code_variables,
@@ -886,6 +889,7 @@ def setup() -> Client:
886889
# always set incase user changes it
887890
default_client.disabled = disabled
888891
default_client.debug = debug
892+
default_client._set_before_send(before_send)
889893

890894
return default_client
891895

posthog/client.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -288,14 +288,7 @@ def __init__(
288288
else:
289289
self.log.setLevel(logging.WARNING)
290290

291-
if before_send is not None:
292-
if callable(before_send):
293-
self.before_send = before_send
294-
else:
295-
self.log.warning("before_send is not callable, it will be ignored")
296-
self.before_send = None
297-
else:
298-
self.before_send = None
291+
self._set_before_send(before_send)
299292

300293
if self.enable_exception_autocapture:
301294
self.exception_capture = ExceptionCapture(self)
@@ -332,6 +325,16 @@ def __init__(
332325
if send:
333326
consumer.start()
334327

328+
def _set_before_send(self, before_send):
329+
if before_send is not None:
330+
if callable(before_send):
331+
self.before_send = before_send
332+
else:
333+
self.log.warning("before_send is not callable, it will be ignored")
334+
self.before_send = None
335+
else:
336+
self.before_send = None
337+
335338
def new_context(self, fresh=False, capture_exceptions=True):
336339
"""
337340
Create a new context for managing shared state. Learn more about [contexts](/docs/libraries/python#contexts).

posthog/test/test_before_send.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import importlib
12
import unittest
23

34
import mock
5+
import posthog
46

57
from posthog.client import Client
68
from posthog.test.test_utils import FAKE_TEST_API_KEY
@@ -216,3 +218,58 @@ def scrub_pii(event):
216218
self.assertEqual(enqueued_msg["properties"]["email"], "***@example.com")
217219
self.assertNotIn("credit_card", enqueued_msg["properties"])
218220
self.assertEqual(enqueued_msg["properties"]["form_name"], "contact")
221+
222+
223+
class TestModuleLevelBeforeSend(unittest.TestCase):
224+
def setUp(self):
225+
importlib.reload(posthog)
226+
227+
def tearDown(self):
228+
if posthog.default_client:
229+
posthog.shutdown()
230+
importlib.reload(posthog)
231+
232+
def test_before_send_callback_used_during_module_level_setup(self):
233+
def my_before_send(event):
234+
event["properties"]["module_level_before_send"] = True
235+
return event
236+
237+
with mock.patch("posthog.client.batch_post") as mock_post:
238+
posthog.api_key = FAKE_TEST_API_KEY
239+
posthog.before_send = my_before_send
240+
posthog.sync_mode = True
241+
242+
msg_uuid = posthog.capture("test_event", distinct_id="user1")
243+
244+
self.assertIsNotNone(msg_uuid)
245+
self.assertIs(posthog.default_client.before_send, my_before_send)
246+
247+
mock_post.assert_called_once()
248+
batch_data = mock_post.call_args[1]["batch"]
249+
enqueued_msg = batch_data[0]
250+
self.assertTrue(enqueued_msg["properties"]["module_level_before_send"])
251+
252+
def test_before_send_callback_updates_after_client_initialization(self):
253+
def my_before_send(event):
254+
event["properties"]["updated_after_init"] = True
255+
return event
256+
257+
with mock.patch("posthog.client.batch_post") as mock_post:
258+
posthog.api_key = FAKE_TEST_API_KEY
259+
posthog.sync_mode = True
260+
261+
first_msg_uuid = posthog.capture("first_event", distinct_id="user1")
262+
263+
posthog.before_send = my_before_send
264+
second_msg_uuid = posthog.capture("second_event", distinct_id="user1")
265+
266+
self.assertIsNotNone(first_msg_uuid)
267+
self.assertIsNotNone(second_msg_uuid)
268+
self.assertIs(posthog.default_client.before_send, my_before_send)
269+
270+
self.assertEqual(mock_post.call_count, 2)
271+
first_batch = mock_post.call_args_list[0][1]["batch"]
272+
second_batch = mock_post.call_args_list[1][1]["batch"]
273+
274+
self.assertNotIn("updated_after_init", first_batch[0]["properties"])
275+
self.assertTrue(second_batch[0]["properties"]["updated_after_init"])

0 commit comments

Comments
 (0)