diff --git a/CHANGELOG.md b/CHANGELOG.md index f5008e64..63b0c111 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.7.3 - 2024-11-25 + +1. Use personless mode when sending an exception without a provided `distinct_id`. + ## 3.7.2 - 2024-11-19 1. Add `type` property to exception stacks. diff --git a/posthog/__init__.py b/posthog/__init__.py index 062e137b..fa56e8b8 100644 --- a/posthog/__init__.py +++ b/posthog/__init__.py @@ -2,7 +2,7 @@ from typing import Callable, Dict, List, Optional, Tuple # noqa: F401 from posthog.client import Client -from posthog.exception_capture import DEFAULT_DISTINCT_ID, Integrations # noqa: F401 +from posthog.exception_capture import Integrations # noqa: F401 from posthog.version import VERSION __version__ = VERSION @@ -289,7 +289,7 @@ def capture_exception( return _proxy( "capture_exception", exception=exception, - distinct_id=distinct_id or DEFAULT_DISTINCT_ID, + distinct_id=distinct_id, properties=properties, context=context, timestamp=timestamp, diff --git a/posthog/client.py b/posthog/client.py index 8aad8a9f..3707d555 100644 --- a/posthog/client.py +++ b/posthog/client.py @@ -4,13 +4,13 @@ import os import sys from datetime import datetime, timedelta -from uuid import UUID +from uuid import UUID, uuid4 from dateutil.tz import tzutc from six import string_types from posthog.consumer import Consumer -from posthog.exception_capture import DEFAULT_DISTINCT_ID, ExceptionCapture +from posthog.exception_capture import ExceptionCapture from posthog.exception_utils import exc_info_from_error, exceptions_from_error_tuple, handle_in_app from posthog.feature_flags import InconclusiveMatchError, match_feature_flag_properties from posthog.poller import Poller @@ -362,7 +362,7 @@ def page( def capture_exception( self, exception=None, - distinct_id=DEFAULT_DISTINCT_ID, + distinct_id=None, properties=None, context=None, timestamp=None, @@ -373,6 +373,13 @@ def capture_exception( # this is important to ensure we don't unexpectedly re-raise exceptions in the user's code. try: properties = properties or {} + + # if there's no distinct_id, we'll generate one and set personless mode + # via $process_person_profile = false + if distinct_id is None: + properties["$process_person_profile"] = False + distinct_id = uuid4() + require("distinct_id", distinct_id, ID_TYPES) require("properties", properties, dict) @@ -385,7 +392,7 @@ def capture_exception( self.log.warning("No exception information available") return - # Format stack trace like sentry + # Format stack trace for cymbal all_exceptions_with_trace = exceptions_from_error_tuple(exc_info) # Add in-app property to frames in the exceptions diff --git a/posthog/exception_capture.py b/posthog/exception_capture.py index 54d50e10..26e7c1a3 100644 --- a/posthog/exception_capture.py +++ b/posthog/exception_capture.py @@ -12,9 +12,6 @@ class Integrations(str, Enum): Django = "django" -DEFAULT_DISTINCT_ID = "python-exceptions" - - class ExceptionCapture: # TODO: Add client side rate limiting to prevent spamming the server with exceptions @@ -61,14 +58,7 @@ def exception_receiver(self, exc_info, extra_properties): def capture_exception(self, exception, metadata=None): try: - # if hasattr(sys, "ps1"): - # # Disable the excepthook for interactive Python shells - # return - - distinct_id = metadata.get("distinct_id") if metadata else DEFAULT_DISTINCT_ID - # Make sure we have a distinct_id if its empty in metadata - distinct_id = distinct_id or DEFAULT_DISTINCT_ID - + distinct_id = metadata.get("distinct_id") if metadata else None self.client.capture_exception(exception, distinct_id) except Exception as e: self.log.exception(f"Failed to capture exception: {e}") diff --git a/posthog/test/test_client.py b/posthog/test/test_client.py index feb5dd2e..6bdb7388 100644 --- a/posthog/test/test_client.py +++ b/posthog/test/test_client.py @@ -104,11 +104,11 @@ def test_basic_capture_exception(self): with mock.patch.object(Client, "capture", return_value=None) as patch_capture: client = self.client exception = Exception("test exception") - client.capture_exception(exception) + client.capture_exception(exception, distinct_id="distinct_id") self.assertTrue(patch_capture.called) capture_call = patch_capture.call_args[0] - self.assertEqual(capture_call[0], "python-exceptions") + self.assertEqual(capture_call[0], "distinct_id") self.assertEqual(capture_call[1], "$exception") self.assertEqual( capture_call[2], @@ -123,7 +123,7 @@ def test_basic_capture_exception(self): "value": "test exception", } ], - "$exception_personURL": "https://us.i.posthog.com/project/random_key/person/python-exceptions", + "$exception_personURL": "https://us.i.posthog.com/project/random_key/person/distinct_id", }, ) @@ -218,11 +218,11 @@ def test_basic_capture_exception_with_no_exception_given(self): try: raise Exception("test exception") except Exception: - client.capture_exception() + client.capture_exception(distinct_id="distinct_id") self.assertTrue(patch_capture.called) capture_call = patch_capture.call_args[0] - self.assertEqual(capture_call[0], "python-exceptions") + self.assertEqual(capture_call[0], "distinct_id") self.assertEqual(capture_call[1], "$exception") self.assertEqual(capture_call[2]["$exception_type"], "Exception") self.assertEqual(capture_call[2]["$exception_message"], "test exception") diff --git a/posthog/version.py b/posthog/version.py index f0f5a9e2..74b62d61 100644 --- a/posthog/version.py +++ b/posthog/version.py @@ -1,4 +1,4 @@ -VERSION = "3.7.2" +VERSION = "3.7.3" if __name__ == "__main__": print(VERSION, end="") # noqa: T201