Skip to content

Commit dc9abbe

Browse files
committed
feat: change config name, add some tests, add limiter
1 parent b65e3cf commit dc9abbe

File tree

5 files changed

+236
-39
lines changed

5 files changed

+236
-39
lines changed

posthog/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
tag as inner_tag,
1111
set_context_session as inner_set_context_session,
1212
identify_context as inner_identify_context,
13-
set_code_variables_enabled_context as inner_set_code_variables_enabled_context,
13+
set_capture_exception_code_variables_context as inner_set_capture_exception_code_variables_context,
1414
set_code_variables_mask_patterns_context as inner_set_code_variables_mask_patterns_context,
1515
set_code_variables_ignore_patterns_context as inner_set_code_variables_ignore_patterns_context,
1616
)
@@ -109,11 +109,11 @@ def identify_context(distinct_id: str):
109109
return inner_identify_context(distinct_id)
110110

111111

112-
def set_code_variables_enabled_context(enabled: bool):
112+
def set_capture_exception_code_variables_context(enabled: bool):
113113
"""
114114
Set whether code variables are captured for the current context.
115115
"""
116-
return inner_set_code_variables_enabled_context(enabled)
116+
return inner_set_capture_exception_code_variables_context(enabled)
117117

118118

119119
def set_code_variables_mask_patterns_context(mask_patterns: list):

posthog/client.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
_get_current_context,
4343
get_context_distinct_id,
4444
get_context_session_id,
45-
get_code_variables_enabled_context,
45+
get_capture_exception_code_variables_context,
4646
get_code_variables_mask_patterns_context,
4747
get_code_variables_ignore_patterns_context,
4848
new_context,
@@ -185,7 +185,7 @@ def __init__(
185185
before_send=None,
186186
flag_fallback_cache_url=None,
187187
enable_local_evaluation=True,
188-
code_variables_enabled=False,
188+
capture_exception_code_variables=False,
189189
code_variables_mask_patterns=None,
190190
code_variables_ignore_patterns=None,
191191
):
@@ -243,8 +243,7 @@ def __init__(
243243
self.privacy_mode = privacy_mode
244244
self.enable_local_evaluation = enable_local_evaluation
245245

246-
# Code variables configuration
247-
self.code_variables_enabled = code_variables_enabled
246+
self.capture_exception_code_variables = capture_exception_code_variables
248247
self.code_variables_mask_patterns = (
249248
code_variables_mask_patterns
250249
if code_variables_mask_patterns is not None
@@ -1002,14 +1001,14 @@ def capture_exception(
10021001
**properties,
10031002
}
10041003

1005-
context_enabled = get_code_variables_enabled_context()
1004+
context_enabled = get_capture_exception_code_variables_context()
10061005
context_mask = get_code_variables_mask_patterns_context()
10071006
context_ignore = get_code_variables_ignore_patterns_context()
10081007

10091008
enabled = (
10101009
context_enabled
10111010
if context_enabled is not None
1012-
else self.code_variables_enabled
1011+
else self.capture_exception_code_variables
10131012
)
10141013
mask_patterns = (
10151014
context_mask

posthog/contexts.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def __init__(
2222
self.session_id: Optional[str] = None
2323
self.distinct_id: Optional[str] = None
2424
self.tags: Dict[str, Any] = {}
25-
self.code_variables_enabled: Optional[bool] = None
25+
self.capture_exception_code_variables: Optional[bool] = None
2626
self.code_variables_mask_patterns: Optional[list] = None
2727
self.code_variables_ignore_patterns: Optional[list] = None
2828

@@ -35,8 +35,8 @@ def set_distinct_id(self, distinct_id: str):
3535
def add_tag(self, key: str, value: Any):
3636
self.tags[key] = value
3737

38-
def set_code_variables_enabled(self, enabled: bool):
39-
self.code_variables_enabled = enabled
38+
def set_capture_exception_code_variables(self, enabled: bool):
39+
self.capture_exception_code_variables = enabled
4040

4141
def set_code_variables_mask_patterns(self, mask_patterns: list):
4242
self.code_variables_mask_patterns = mask_patterns
@@ -71,11 +71,11 @@ def collect_tags(self) -> Dict[str, Any]:
7171
tags.update(new_tags)
7272
return tags
7373

74-
def get_code_variables_enabled(self) -> Optional[bool]:
75-
if self.code_variables_enabled is not None:
76-
return self.code_variables_enabled
74+
def get_capture_exception_code_variables(self) -> Optional[bool]:
75+
if self.capture_exception_code_variables is not None:
76+
return self.capture_exception_code_variables
7777
if self.parent is not None and not self.fresh:
78-
return self.parent.get_code_variables_enabled()
78+
return self.parent.get_capture_exception_code_variables()
7979
return None
8080

8181
def get_code_variables_mask_patterns(self) -> Optional[list]:
@@ -276,13 +276,13 @@ def get_context_distinct_id() -> Optional[str]:
276276
return None
277277

278278

279-
def set_code_variables_enabled_context(enabled: bool) -> None:
279+
def set_capture_exception_code_variables_context(enabled: bool) -> None:
280280
"""
281281
Set whether code variables are captured for the current context.
282282
"""
283283
current_context = _get_current_context()
284284
if current_context:
285-
current_context.set_code_variables_enabled(enabled)
285+
current_context.set_capture_exception_code_variables(enabled)
286286

287287

288288
def set_code_variables_mask_patterns_context(mask_patterns: list) -> None:
@@ -303,10 +303,10 @@ def set_code_variables_ignore_patterns_context(ignore_patterns: list) -> None:
303303
current_context.set_code_variables_ignore_patterns(ignore_patterns)
304304

305305

306-
def get_code_variables_enabled_context() -> Optional[bool]:
306+
def get_capture_exception_code_variables_context() -> Optional[bool]:
307307
current_context = _get_current_context()
308308
if current_context:
309-
return current_context.get_code_variables_enabled()
309+
return current_context.get_capture_exception_code_variables()
310310
return None
311311

312312

posthog/exception_utils.py

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,24 @@
6060

6161
CODE_VARIABLES_REDACTED_VALUE = "$$_posthog_redacted_based_on_masking_rules_$$"
6262

63+
DEFAULT_TOTAL_VARIABLES_SIZE_LIMIT = 20 * 1024
64+
65+
66+
class VariableSizeLimiter:
67+
def __init__(self, max_size=DEFAULT_TOTAL_VARIABLES_SIZE_LIMIT):
68+
self.max_size = max_size
69+
self.current_size = 0
70+
71+
def can_add(self, size):
72+
return self.current_size + size <= self.max_size
73+
74+
def add(self, size):
75+
self.current_size += size
76+
77+
def get_remaining_space(self):
78+
return self.max_size - self.current_size
79+
80+
6381
LogLevelStr = Literal["fatal", "critical", "error", "warning", "info", "debug"]
6482

6583
Event = TypedDict(
@@ -923,37 +941,51 @@ def _pattern_matches(name, patterns):
923941
return False
924942

925943

926-
def _serialize_variable_value(value, max_length=1024):
944+
def _serialize_variable_value(value, limiter, max_length=1024):
927945
try:
928946
if value is None:
929-
return "None"
947+
result = "None"
930948
elif isinstance(value, bool):
931-
return str(value)
949+
result = str(value)
932950
elif isinstance(value, (int, float)):
933951
result = str(value)
934952
elif isinstance(value, str):
935953
result = repr(value)
936954
else:
937955
result = json.dumps(value)
938956

939-
# Truncate if too long
940957
if len(result) > max_length:
941958
result = result[: max_length - 3] + "..."
942959

960+
result_size = len(result)
961+
if not limiter.can_add(result_size):
962+
return None
963+
limiter.add(result_size)
964+
943965
return result
944966
except Exception:
945967
try:
946-
return f"<{type(value).__name__}>"
968+
fallback = f"<{type(value).__name__}>"
969+
fallback_size = len(fallback)
970+
if not limiter.can_add(fallback_size):
971+
return None
972+
limiter.add(fallback_size)
973+
return fallback
947974
except Exception:
948-
return "<unserializable object>"
975+
fallback = "<unserializable object>"
976+
fallback_size = len(fallback)
977+
if not limiter.can_add(fallback_size):
978+
return None
979+
limiter.add(fallback_size)
980+
return fallback
949981

950982

951983
def _is_simple_type(value):
952984
return isinstance(value, (type(None), bool, int, float, str))
953985

954986

955987
def serialize_code_variables(
956-
frame, mask_patterns=None, ignore_patterns=None, max_vars=20, max_length=1024
988+
frame, limiter, mask_patterns=None, ignore_patterns=None, max_length=1024
957989
):
958990
if mask_patterns is None:
959991
mask_patterns = []
@@ -981,23 +1013,25 @@ def serialize_code_variables(
9811013
complex_vars[name] = value
9821014

9831015
result = {}
984-
count = 0
9851016

9861017
all_vars = {**simple_vars, **complex_vars}
9871018
ordered_names = list(sorted(simple_vars.keys())) + list(sorted(complex_vars.keys()))
9881019

9891020
for name in ordered_names:
990-
if count >= max_vars:
991-
break
992-
9931021
value = all_vars[name]
9941022

9951023
if _pattern_matches(name, compiled_mask):
996-
result[name] = CODE_VARIABLES_REDACTED_VALUE
1024+
redacted_value = CODE_VARIABLES_REDACTED_VALUE
1025+
redacted_size = len(redacted_value)
1026+
if not limiter.can_add(redacted_size):
1027+
break
1028+
limiter.add(redacted_size)
1029+
result[name] = redacted_value
9971030
else:
998-
result[name] = _serialize_variable_value(value, max_length)
999-
1000-
count += 1
1031+
serialized = _serialize_variable_value(value, limiter, max_length)
1032+
if serialized is None:
1033+
break
1034+
result[name] = serialized
10011035

10021036
return result
10031037

@@ -1015,6 +1049,8 @@ def try_attach_code_variables_to_frames(
10151049
if not tb_frames:
10161050
return
10171051

1052+
limiter = VariableSizeLimiter()
1053+
10181054
for exception in all_exceptions:
10191055
stacktrace = exception.get("stacktrace")
10201056
if not stacktrace or "frames" not in stacktrace:
@@ -1028,9 +1064,9 @@ def try_attach_code_variables_to_frames(
10281064

10291065
variables = serialize_code_variables(
10301066
tb_item.tb_frame,
1067+
limiter,
10311068
mask_patterns=mask_patterns,
10321069
ignore_patterns=ignore_patterns,
1033-
max_vars=20,
10341070
max_length=1024,
10351071
)
10361072

0 commit comments

Comments
 (0)