@@ -110,6 +110,87 @@ def test_transactions(sentry_init, capture_events, mongo_server, with_pii):
110110 assert insert_fail ["tags" ]["status" ] == "internal_error"
111111
112112
113+ DATA_COLLECTION_DATABASE_QUERY_DATA_USE_CASES = [
114+ pytest .param (
115+ {"_experiments" : {"data_collection" : {"database_query_data" : True }}},
116+ True ,
117+ id = "query_data_enabled" ,
118+ ),
119+ pytest .param (
120+ {"_experiments" : {"data_collection" : {"database_query_data" : False }}},
121+ False ,
122+ id = "query_data_disabled" ,
123+ ),
124+ pytest .param (
125+ {"_experiments" : {"data_collection" : {}}},
126+ True ,
127+ id = "query_data_default" ,
128+ ),
129+ pytest .param (
130+ {
131+ "send_default_pii" : False ,
132+ "_experiments" : {"data_collection" : {"database_query_data" : True }},
133+ },
134+ True ,
135+ id = "data_collection_overrides_pii_off" ,
136+ ),
137+ pytest .param (
138+ {
139+ "send_default_pii" : True ,
140+ "_experiments" : {"data_collection" : {"database_query_data" : False }},
141+ },
142+ False ,
143+ id = "data_collection_overrides_pii_on" ,
144+ ),
145+ ]
146+
147+
148+ @pytest .mark .parametrize (
149+ "init_kwargs,expect_query_values" , DATA_COLLECTION_DATABASE_QUERY_DATA_USE_CASES
150+ )
151+ def test_transactions_with_data_collection (
152+ sentry_init , capture_events , mongo_server , init_kwargs , expect_query_values
153+ ):
154+ sentry_init (
155+ integrations = [PyMongoIntegration ()],
156+ traces_sample_rate = 1.0 ,
157+ ** init_kwargs ,
158+ )
159+ events = capture_events ()
160+
161+ connection = MongoClient (mongo_server .uri )
162+
163+ with start_transaction ():
164+ list (
165+ connection ["test_db" ]["test_collection" ].find ({"foobar" : 1 })
166+ ) # force query execution
167+ connection ["test_db" ]["test_collection" ].insert_one ({"foo" : 2 })
168+ try :
169+ connection ["test_db" ]["erroneous" ].insert_many ([{"bar" : 3 }, {"baz" : 4 }])
170+ pytest .fail ("Request should raise" )
171+ except Exception :
172+ pass
173+
174+ (event ,) = events
175+ (find , insert_success , insert_fail ) = event ["spans" ]
176+
177+ assert find ["description" ].startswith ('{"find' )
178+ assert insert_success ["description" ].startswith ('{"insert' )
179+ assert insert_fail ["description" ].startswith ('{"insert' )
180+
181+ if expect_query_values :
182+ assert "1" in find ["description" ]
183+ assert "2" in insert_success ["description" ]
184+ assert "3" in insert_fail ["description" ] and "4" in insert_fail ["description" ]
185+ else :
186+ assert "1" not in find ["description" ]
187+ assert "2" not in insert_success ["description" ]
188+ assert (
189+ "3" not in insert_fail ["description" ]
190+ and "4" not in insert_fail ["description" ]
191+ )
192+
193+
113194@pytest .mark .parametrize ("with_pii" , [False , True ])
114195def test_segment_span_streaming (sentry_init , capture_items , mongo_server , with_pii ):
115196 sentry_init (
@@ -179,6 +260,57 @@ def test_segment_span_streaming(sentry_init, capture_items, mongo_server, with_p
179260 assert insert_fail ["status" ] == "error"
180261
181262
263+ @pytest .mark .parametrize (
264+ "init_kwargs,expect_query_values" , DATA_COLLECTION_DATABASE_QUERY_DATA_USE_CASES
265+ )
266+ def test_segment_span_streaming_with_data_collection (
267+ sentry_init , capture_items , mongo_server , init_kwargs , expect_query_values
268+ ):
269+ sentry_init (
270+ integrations = [PyMongoIntegration ()],
271+ traces_sample_rate = 1.0 ,
272+ trace_lifecycle = "stream" ,
273+ ** init_kwargs ,
274+ )
275+ items = capture_items ("span" )
276+
277+ connection = MongoClient (mongo_server .uri )
278+
279+ with sentry_sdk .traces .start_span (name = "test_segment" ):
280+ list (
281+ connection ["test_db" ]["test_collection" ].find ({"foobar" : 1 })
282+ ) # force query execution
283+ connection ["test_db" ]["test_collection" ].insert_one ({"foo" : 2 })
284+ try :
285+ connection ["test_db" ]["erroneous" ].insert_many ([{"bar" : 3 }, {"baz" : 4 }])
286+ pytest .fail ("Request should raise" )
287+ except Exception :
288+ pass
289+ sentry_sdk .flush ()
290+
291+ spans = [item .payload for item in items ]
292+ assert len (spans ) == 4
293+
294+ (find , insert_success , insert_fail , segment ) = spans
295+ assert segment ["name" ] == "test_segment"
296+
297+ assert find ["name" ].startswith ('{"find' )
298+ assert insert_success ["name" ].startswith ('{"insert' )
299+ assert insert_fail ["name" ].startswith ('{"insert' )
300+
301+ for span in find , insert_success , insert_fail :
302+ assert span ["attributes" ][SPANDATA .DB_QUERY_TEXT ] == span ["name" ]
303+
304+ if expect_query_values :
305+ assert "1" in find ["name" ]
306+ assert "2" in insert_success ["name" ]
307+ assert "3" in insert_fail ["name" ] and "4" in insert_fail ["name" ]
308+ else :
309+ assert "1" not in find ["name" ]
310+ assert "2" not in insert_success ["name" ]
311+ assert "3" not in insert_fail ["name" ] and "4" not in insert_fail ["name" ]
312+
313+
182314@pytest .mark .parametrize ("with_pii" , [False , True ])
183315def test_breadcrumbs (sentry_init , capture_events , mongo_server , with_pii ):
184316 sentry_init (
@@ -216,6 +348,38 @@ def test_breadcrumbs(sentry_init, capture_events, mongo_server, with_pii):
216348 }
217349
218350
351+ @pytest .mark .parametrize (
352+ "init_kwargs,expect_query_values" , DATA_COLLECTION_DATABASE_QUERY_DATA_USE_CASES
353+ )
354+ def test_breadcrumbs_with_data_collection (
355+ sentry_init , capture_events , mongo_server , init_kwargs , expect_query_values
356+ ):
357+ sentry_init (
358+ integrations = [PyMongoIntegration ()],
359+ traces_sample_rate = 1.0 ,
360+ ** init_kwargs ,
361+ )
362+ events = capture_events ()
363+
364+ connection = MongoClient (mongo_server .uri )
365+
366+ list (
367+ connection ["test_db" ]["test_collection" ].find ({"foobar" : 1 })
368+ ) # force query execution
369+ capture_message ("hi" )
370+
371+ (event ,) = events
372+ (crumb ,) = event ["breadcrumbs" ]["values" ]
373+
374+ assert crumb ["category" ] == "query"
375+ assert crumb ["message" ].startswith ('{"find' )
376+ if expect_query_values :
377+ assert "1" in crumb ["message" ]
378+ else :
379+ assert "1" not in crumb ["message" ]
380+ assert crumb ["type" ] == "db"
381+
382+
219383@pytest .mark .parametrize ("with_pii" , [False , True ])
220384def test_breadcrumbs_span_streaming (sentry_init , capture_items , mongo_server , with_pii ):
221385 sentry_init (
@@ -257,6 +421,40 @@ def test_breadcrumbs_span_streaming(sentry_init, capture_items, mongo_server, wi
257421 assert data [SPANDATA .SERVER_PORT ] == mongo_server .port
258422
259423
424+ @pytest .mark .parametrize (
425+ "init_kwargs,expect_query_values" , DATA_COLLECTION_DATABASE_QUERY_DATA_USE_CASES
426+ )
427+ def test_breadcrumbs_span_streaming_with_data_collection (
428+ sentry_init , capture_items , mongo_server , init_kwargs , expect_query_values
429+ ):
430+ sentry_init (
431+ integrations = [PyMongoIntegration ()],
432+ traces_sample_rate = 1.0 ,
433+ trace_lifecycle = "stream" ,
434+ ** init_kwargs ,
435+ )
436+ items = capture_items ("event" )
437+
438+ connection = MongoClient (mongo_server .uri )
439+
440+ list (
441+ connection ["test_db" ]["test_collection" ].find ({"foobar" : 1 })
442+ ) # force query execution
443+ capture_message ("hi" )
444+
445+ event = items [0 ].payload
446+ (crumb ,) = event ["breadcrumbs" ]["values" ]
447+
448+ assert crumb ["category" ] == "query"
449+ assert crumb ["message" ].startswith ('{"find' )
450+ if expect_query_values :
451+ assert "1" in crumb ["message" ]
452+ else :
453+ assert "1" not in crumb ["message" ]
454+ assert crumb ["type" ] == "db"
455+ assert crumb ["data" ]["db.query.text" ] == crumb ["message" ]
456+
457+
260458@pytest .mark .parametrize (
261459 "testcase" ,
262460 [
0 commit comments