@@ -450,3 +450,143 @@ def trigger_error():
450450 assert "<CustomReprClass: custom representation>" in output
451451 assert "<lambda>" in output
452452 assert "<function trigger_error at" in output
453+
454+
455+ def test_code_variables_too_long_string_value_replaced (tmpdir ):
456+ app = tmpdir .join ("app.py" )
457+ app .write (
458+ dedent (
459+ """
460+ import os
461+ from posthog import Posthog
462+
463+ posthog = Posthog(
464+ 'phc_x',
465+ host='https://eu.i.posthog.com',
466+ debug=True,
467+ enable_exception_autocapture=True,
468+ capture_exception_code_variables=True,
469+ project_root=os.path.dirname(os.path.abspath(__file__))
470+ )
471+
472+ def trigger_error():
473+ short_value = "I am short"
474+ long_value = "x" * 20000
475+ long_blob = "password_" + "a" * 20000
476+
477+ 1/0
478+
479+ trigger_error()
480+ """
481+ )
482+ )
483+
484+ with pytest .raises (subprocess .CalledProcessError ) as excinfo :
485+ subprocess .check_output ([sys .executable , str (app )], stderr = subprocess .STDOUT )
486+
487+ output = excinfo .value .output .decode ("utf-8" )
488+
489+ assert "ZeroDivisionError" in output
490+ assert "code_variables" in output
491+
492+ assert "'short_value': 'I am short'" in output
493+
494+ assert "$$_posthog_value_too_long_$$" in output
495+
496+ assert "'long_blob': '$$_posthog_value_too_long_$$'" in output
497+
498+
499+ def test_code_variables_too_long_string_in_nested_dict (tmpdir ):
500+ app = tmpdir .join ("app.py" )
501+ app .write (
502+ dedent (
503+ """
504+ import os
505+ from posthog import Posthog
506+
507+ posthog = Posthog(
508+ 'phc_x',
509+ host='https://eu.i.posthog.com',
510+ debug=True,
511+ enable_exception_autocapture=True,
512+ capture_exception_code_variables=True,
513+ project_root=os.path.dirname(os.path.abspath(__file__))
514+ )
515+
516+ def trigger_error():
517+ my_data = {
518+ "short_key": "short_val",
519+ "long_key": "y" * 20000,
520+ "nested": {
521+ "deep_long": "z" * 20000,
522+ "deep_short": "ok",
523+ },
524+ }
525+
526+ 1/0
527+
528+ trigger_error()
529+ """
530+ )
531+ )
532+
533+ with pytest .raises (subprocess .CalledProcessError ) as excinfo :
534+ subprocess .check_output ([sys .executable , str (app )], stderr = subprocess .STDOUT )
535+
536+ output = excinfo .value .output .decode ("utf-8" )
537+
538+ assert "ZeroDivisionError" in output
539+ assert "code_variables" in output
540+
541+ assert "short_val" in output
542+ assert "ok" in output
543+
544+ assert "$$_posthog_value_too_long_$$" in output
545+ assert "y" * 1000 not in output
546+ assert "z" * 1000 not in output
547+
548+
549+ def test_mask_sensitive_data_too_long_dict_key ():
550+ from posthog .exception_utils import (
551+ CODE_VARIABLES_TOO_LONG_VALUE ,
552+ _compile_patterns ,
553+ _mask_sensitive_data ,
554+ )
555+
556+ compiled_mask = _compile_patterns ([r"(?i)password" ])
557+
558+ result = _mask_sensitive_data (
559+ {
560+ "short" : "visible" ,
561+ "k" * 20000 : "hidden_val" ,
562+ "password" : "secret" ,
563+ },
564+ compiled_mask ,
565+ )
566+
567+ assert result ["short" ] == "visible"
568+ # This then gets shortened by the JSON truncation at 1024 chars anyways so no worries
569+ assert result ["k" * 20000 ] == CODE_VARIABLES_TOO_LONG_VALUE
570+ assert result ["password" ] == "$$_posthog_redacted_based_on_masking_rules_$$"
571+
572+
573+ def test_mask_sensitive_data_circular_ref ():
574+ from posthog .exception_utils import _compile_patterns , _mask_sensitive_data
575+
576+ compiled_mask = _compile_patterns ([r"(?i)password" ])
577+
578+ # Circular dict
579+ circular_dict = {"key" : "value" }
580+ circular_dict ["self" ] = circular_dict
581+
582+ result = _mask_sensitive_data (circular_dict , compiled_mask )
583+ assert result ["key" ] == "value"
584+ assert result ["self" ] == "<circular ref>"
585+
586+ # Circular list
587+ circular_list = ["item" ]
588+ circular_list .append (circular_list )
589+
590+ result = _mask_sensitive_data (circular_list , compiled_mask )
591+ assert result [0 ] == "item"
592+ assert result [1 ] == "<circular ref>"
0 commit comments