1515from flask .views import View
1616from flask_login import LoginManager , login_user
1717
18+ from sentry_sdk .traces import SpanStatus
19+
1820try :
1921 from werkzeug .wrappers .request import UnsupportedMediaType
2022except ImportError :
@@ -82,6 +84,7 @@ def test_has_context(sentry_init, app, capture_events):
8284 assert event ["request" ]["url" ] == "http://localhost/message"
8385
8486
87+ @pytest .mark .parametrize ("span_streaming" , [True , False ])
8588@pytest .mark .parametrize (
8689 "url,transaction_style,expected_transaction,expected_source" ,
8790 [
@@ -91,29 +94,45 @@ def test_has_context(sentry_init, app, capture_events):
9194 ("/message/123456" , "url" , "/message/<int:message_id>" , "route" ),
9295 ],
9396)
94- def test_transaction_style (
97+ def test_transaction_or_segment_style (
9598 sentry_init ,
9699 app ,
97100 capture_events ,
101+ capture_items ,
98102 url ,
99103 transaction_style ,
100104 expected_transaction ,
101105 expected_source ,
106+ span_streaming ,
102107):
103108 sentry_init (
104109 integrations = [
105110 flask_sentry .FlaskIntegration (transaction_style = transaction_style )
106- ]
111+ ],
112+ traces_sample_rate = 1.0 ,
113+ _experiments = {"trace_lifecycle" : "stream" if span_streaming else "static" },
107114 )
108- events = capture_events ()
115+
116+ if span_streaming :
117+ items = capture_items ("span" )
118+ else :
119+ events = capture_events ()
109120
110121 client = app .test_client ()
111122 response = client .get (url )
112123 assert response .status_code == 200
113124
114- (event ,) = events
115- assert event ["transaction" ] == expected_transaction
116- assert event ["transaction_info" ] == {"source" : expected_source }
125+ if span_streaming :
126+ sentry_sdk .flush ()
127+ spans = [i .payload for i in items if i .type == "span" ]
128+ assert len (spans ) == 1
129+ (segment ,) = spans
130+ assert segment ["name" ] == expected_transaction
131+ assert segment ["attributes" ]["sentry.span.source" ] == expected_source
132+ else :
133+ (_ , event ) = events
134+ assert event ["transaction" ] == expected_transaction
135+ assert event ["transaction_info" ] == {"source" : expected_source }
117136
118137
119138@pytest .mark .parametrize ("debug" , (True , False ))
@@ -763,8 +782,15 @@ def zerodivision(e):
763782 assert not events
764783
765784
766- def test_tracing_success (sentry_init , capture_events , app ):
767- sentry_init (traces_sample_rate = 1.0 , integrations = [flask_sentry .FlaskIntegration ()])
785+ @pytest .mark .parametrize ("span_streaming" , [True , False ])
786+ def test_tracing_success (
787+ sentry_init , capture_events , capture_items , app , span_streaming
788+ ):
789+ sentry_init (
790+ traces_sample_rate = 1.0 ,
791+ integrations = [flask_sentry .FlaskIntegration ()],
792+ _experiments = {"trace_lifecycle" : "stream" if span_streaming else "static" },
793+ )
768794
769795 @app .before_request
770796 def _ ():
@@ -776,30 +802,61 @@ def hi_tx():
776802 capture_message ("hi" )
777803 return "ok"
778804
779- events = capture_events ()
805+ if span_streaming :
806+ items = capture_items ("event" , "span" )
807+ else :
808+ events = capture_events ()
780809
781810 with app .test_client () as client :
782811 response = client .get ("/message_tx" )
783812 assert response .status_code == 200
784813
785- message_event , transaction_event = events
814+ if span_streaming :
815+ sentry_sdk .flush ()
816+ spans = [i .payload for i in items if i .type == "span" ]
817+ message_events = [i .payload for i in items if i .type == "event" ]
786818
787- assert transaction_event ["type" ] == "transaction"
788- assert transaction_event ["transaction" ] == "hi_tx"
789- assert transaction_event ["contexts" ]["trace" ]["status" ] == "ok"
790- assert transaction_event ["tags" ]["view" ] == "yes"
791- assert transaction_event ["tags" ]["before_request" ] == "yes"
819+ assert len (spans ) == 1
820+ assert len (message_events ) == 1
792821
793- assert message_event ["message" ] == "hi"
794- assert message_event ["transaction" ] == "hi_tx"
795- assert message_event ["tags" ]["view" ] == "yes"
796- assert message_event ["tags" ]["before_request" ] == "yes"
822+ (segment ,) = spans
823+ (message_event ,) = message_events
797824
825+ assert segment ["name" ] == "hi_tx"
826+ assert segment ["status" ] == SpanStatus .OK
827+ assert segment ["attributes" ]["sentry.origin" ] == "auto.http.flask"
798828
799- def test_tracing_error (sentry_init , capture_events , app ):
800- sentry_init (traces_sample_rate = 1.0 , integrations = [flask_sentry .FlaskIntegration ()])
829+ assert message_event ["message" ] == "hi"
830+ assert message_event ["transaction" ] == "hi_tx"
831+ assert message_event ["tags" ]["view" ] == "yes"
832+ assert message_event ["tags" ]["before_request" ] == "yes"
833+ else :
834+ message_event , transaction_event = events
801835
802- events = capture_events ()
836+ assert transaction_event ["type" ] == "transaction"
837+ assert transaction_event ["transaction" ] == "hi_tx"
838+ assert transaction_event ["contexts" ]["trace" ]["status" ] == "ok"
839+ assert transaction_event ["tags" ]["view" ] == "yes"
840+ assert transaction_event ["tags" ]["before_request" ] == "yes"
841+
842+ assert message_event ["message" ] == "hi"
843+ assert message_event ["transaction" ] == "hi_tx"
844+ assert message_event ["tags" ]["view" ] == "yes"
845+ assert message_event ["tags" ]["before_request" ] == "yes"
846+
847+
848+ @pytest .mark .parametrize ("span_streaming" , [True , False ])
849+ def test_tracing_error (sentry_init , capture_events , capture_items , app , span_streaming ):
850+ sentry_init (
851+ traces_sample_rate = 1.0 ,
852+ integrations = [flask_sentry .FlaskIntegration ()],
853+ _experiments = {"trace_lifecycle" : "stream" if span_streaming else "static" },
854+ )
855+
856+ if span_streaming :
857+ items = capture_items ("event" , "span" )
858+ else :
859+ events = capture_events ()
803860
804861 @app .route ("/error" )
805862 def error ():
@@ -810,15 +867,33 @@ def error():
810867 response = client .get ("/error" )
811868 assert response .status_code == 500
812869
813- error_event , transaction_event = events
870+ if span_streaming :
871+ sentry_sdk .flush ()
872+ spans = [i .payload for i in items if i .type == "span" ]
873+ error_events = [i .payload for i in items if i .type == "event" ]
814874
815- assert transaction_event ["type" ] == "transaction"
816- assert transaction_event ["transaction" ] == "error"
817- assert transaction_event ["contexts" ]["trace" ]["status" ] == "internal_error"
875+ assert len (spans ) == 1
876+ assert len (error_events ) == 1
818877
819- assert error_event ["transaction" ] == "error"
820- (exception ,) = error_event ["exception" ]["values" ]
821- assert exception ["type" ] == "ZeroDivisionError"
878+ (segment ,) = spans
879+ (error_event ,) = error_events
880+
881+ assert segment ["name" ] == "error"
882+ assert segment ["status" ] == SpanStatus .ERROR
883+
884+ assert error_event ["transaction" ] == "error"
885+ (exception ,) = error_event ["exception" ]["values" ]
886+ assert exception ["type" ] == "ZeroDivisionError"
887+ else :
888+ error_event , transaction_event = events
889+
890+ assert transaction_event ["type" ] == "transaction"
891+ assert transaction_event ["transaction" ] == "error"
892+ assert transaction_event ["contexts" ]["trace" ]["status" ] == "internal_error"
893+
894+ assert error_event ["transaction" ] == "error"
895+ (exception ,) = error_event ["exception" ]["values" ]
896+ assert exception ["type" ] == "ZeroDivisionError"
822897
823898
824899def test_error_has_trace_context_if_tracing_disabled (sentry_init , capture_events , app ):
@@ -995,34 +1070,54 @@ def test_response_status_code_not_found_in_transaction_context(
9951070 assert transaction ["contexts" ]["response" ]["status_code" ] == 404
9961071
9971072
998- def test_span_origin (sentry_init , app , capture_events ):
1073+ @pytest .mark .parametrize ("span_streaming" , [True , False ])
1074+ def test_span_origin (sentry_init , app , capture_events , capture_items , span_streaming ):
9991075 sentry_init (
10001076 integrations = [flask_sentry .FlaskIntegration ()],
10011077 traces_sample_rate = 1.0 ,
1078+ _experiments = {"trace_lifecycle" : "stream" if span_streaming else "static" },
10021079 )
1003- events = capture_events ()
1080+
1081+ if span_streaming :
1082+ items = capture_items ("span" )
1083+ else :
1084+ events = capture_events ()
10041085
10051086 client = app .test_client ()
10061087 client .get ("/message" )
10071088
1008- (_ , event ) = events
1009-
1010- assert event ["contexts" ]["trace" ]["origin" ] == "auto.http.flask"
1089+ if span_streaming :
1090+ sentry_sdk .flush ()
1091+ spans = [i .payload for i in items if i .type == "span" ]
1092+ assert len (spans ) == 1
1093+ (segment ,) = spans
1094+ assert segment ["attributes" ]["sentry.origin" ] == "auto.http.flask"
1095+ else :
1096+ (_ , event ) = events
1097+ assert event ["contexts" ]["trace" ]["origin" ] == "auto.http.flask"
10111098
10121099
1013- def test_transaction_http_method_default (
1100+ @pytest .mark .parametrize ("span_streaming" , [True , False ])
1101+ def test_transaction_or_segment_http_method_default (
10141102 sentry_init ,
10151103 app ,
10161104 capture_events ,
1105+ capture_items ,
1106+ span_streaming ,
10171107):
10181108 """
1019- By default OPTIONS and HEAD requests do not create a transaction.
1109+ By default OPTIONS and HEAD requests do not create a transaction or segment .
10201110 """
10211111 sentry_init (
10221112 traces_sample_rate = 1.0 ,
10231113 integrations = [flask_sentry .FlaskIntegration ()],
1114+ _experiments = {"trace_lifecycle" : "stream" if span_streaming else "static" },
10241115 )
1025- events = capture_events ()
1116+
1117+ if span_streaming :
1118+ items = capture_items ("span" )
1119+ else :
1120+ events = capture_events ()
10261121
10271122 client = app .test_client ()
10281123 response = client .get ("/nomessage" )
@@ -1034,16 +1129,25 @@ def test_transaction_http_method_default(
10341129 response = client .head ("/nomessage" )
10351130 assert response .status_code == 200
10361131
1037- (event ,) = events
1038-
1039- assert len (events ) == 1
1040- assert event ["request" ]["method" ] == "GET"
1132+ if span_streaming :
1133+ sentry_sdk .flush ()
1134+ spans = [i .payload for i in items if i .type == "span" ]
1135+ assert len (spans ) == 1
1136+ (segment ,) = spans
1137+ assert segment ["attributes" ]["http.request.method" ] == "GET"
1138+ else :
1139+ (event ,) = events
1140+ assert len (events ) == 1
1141+ assert event ["request" ]["method" ] == "GET"
10411142
10421143
1043- def test_transaction_http_method_custom (
1144+ @pytest .mark .parametrize ("span_streaming" , [True , False ])
1145+ def test_transaction_or_segment_http_method_custom (
10441146 sentry_init ,
10451147 app ,
10461148 capture_events ,
1149+ capture_items ,
1150+ span_streaming ,
10471151):
10481152 """
10491153 Configure FlaskIntegration to ONLY capture OPTIONS and HEAD requests.
@@ -1058,8 +1162,13 @@ def test_transaction_http_method_custom(
10581162 ) # capitalization does not matter
10591163 ) # case does not matter
10601164 ],
1165+ _experiments = {"trace_lifecycle" : "stream" if span_streaming else "static" },
10611166 )
1062- events = capture_events ()
1167+
1168+ if span_streaming :
1169+ items = capture_items ("span" )
1170+ else :
1171+ events = capture_events ()
10631172
10641173 client = app .test_client ()
10651174 response = client .get ("/nomessage" )
@@ -1071,8 +1180,15 @@ def test_transaction_http_method_custom(
10711180 response = client .head ("/nomessage" )
10721181 assert response .status_code == 200
10731182
1074- assert len (events ) == 2
1075-
1076- (event1 , event2 ) = events
1077- assert event1 ["request" ]["method" ] == "OPTIONS"
1078- assert event2 ["request" ]["method" ] == "HEAD"
1183+ if span_streaming :
1184+ sentry_sdk .flush ()
1185+ spans = [i .payload for i in items if i .type == "span" ]
1186+ assert len (spans ) == 2
1187+ (options_segment , head_segment ) = spans
1188+ assert options_segment ["attributes" ]["http.request.method" ] == "OPTIONS"
1189+ assert head_segment ["attributes" ]["http.request.method" ] == "HEAD"
1190+ else :
1191+ assert len (events ) == 2
1192+ (event1 , event2 ) = events
1193+ assert event1 ["request" ]["method" ] == "OPTIONS"
1194+ assert event2 ["request" ]["method" ] == "HEAD"
0 commit comments