Skip to content

Commit 4625391

Browse files
authored
[DBMON-6133] Postgres split out and stabilize flaky test_session_idle_and_killed tests (DataDog#22503)
* Split out and stabilize flaky tests * Loosen up our assertion
1 parent b14482e commit 4625391

1 file changed

Lines changed: 62 additions & 10 deletions

File tree

postgres/tests/test_pg_integration.py

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,9 @@ def test_session_number(aggregator, integration_check, pg_instance):
237237

238238

239239
@requires_over_14
240-
def test_session_idle_and_killed(aggregator, integration_check, pg_instance):
241-
# Reset idle time to 0
240+
def test_session_killed_and_abandoned(aggregator, integration_check, pg_instance):
241+
"""Test session counter metrics (killed, fatal, abandoned) - deterministic event counts."""
242+
# Reset stats to 0
242243
postgres_conn = _get_superconn(pg_instance)
243244
with postgres_conn.cursor() as cur:
244245
cur.execute("select pg_stat_reset();")
@@ -250,18 +251,17 @@ def test_session_idle_and_killed(aggregator, integration_check, pg_instance):
250251
check.run()
251252
expected_tags = _get_expected_tags(check, pg_instance, db=DB_NAME)
252253

253-
aggregator.assert_metric('postgresql.sessions.idle_in_transaction_time', value=0, count=1, tags=expected_tags)
254+
# Verify baseline counters are 0
254255
aggregator.assert_metric('postgresql.sessions.killed', value=0, count=1, tags=expected_tags)
255256
aggregator.assert_metric('postgresql.sessions.fatal', value=0, count=1, tags=expected_tags)
256257
aggregator.assert_metric('postgresql.sessions.abandoned', value=0, count=1, tags=expected_tags)
257258

258-
conn = _get_conn(pg_instance)
259+
# Create a session to kill
260+
conn = _get_conn(pg_instance, autocommit=False)
259261
with conn.cursor() as cur:
260262
cur.execute('BEGIN;')
261263
_increase_txid(cur)
262264
cur.fetchall()
263-
# Keep transaction idle for 500ms
264-
time.sleep(0.5)
265265
cur.execute('select pg_backend_pid();')
266266
pid = cur.fetchall()[0][0]
267267

@@ -270,20 +270,72 @@ def test_session_idle_and_killed(aggregator, integration_check, pg_instance):
270270
cur.execute("SELECT pg_terminate_backend({})".format(pid))
271271
cur.fetchall()
272272

273-
# Abandon session
273+
# Abandon session by shutting down the socket
274274
sock = socket.fromfd(postgres_conn.fileno(), socket.AF_INET, socket.SOCK_STREAM)
275275
sock.shutdown(socket.SHUT_RDWR)
276276

277+
# Wait for stats collector to update
278+
time.sleep(0.5)
279+
277280
aggregator.reset()
278281
check.run()
279282

280-
assert_metric_at_least(
281-
aggregator, 'postgresql.sessions.idle_in_transaction_time', count=1, lower_bound=0.5, tags=expected_tags
282-
)
283+
# Verify counter metrics incremented correctly
283284
aggregator.assert_metric('postgresql.sessions.killed', value=1, count=1, tags=expected_tags)
284285
aggregator.assert_metric('postgresql.sessions.fatal', value=0, count=1, tags=expected_tags)
285286
aggregator.assert_metric('postgresql.sessions.abandoned', value=1, count=1, tags=expected_tags)
286287

288+
# Clean up connection objects (connections are already in bad state from kill/abandon)
289+
try:
290+
conn.close()
291+
except Exception:
292+
pass # Connection was killed, close may fail
293+
try:
294+
postgres_conn.close()
295+
except Exception:
296+
pass # Socket was shut down, close may fail
297+
298+
299+
@requires_over_14
300+
@pytest.mark.flaky(max_runs=3)
301+
def test_session_idle_in_transaction_time(aggregator, integration_check, pg_instance):
302+
"""Test idle_in_transaction_time metric tracks time spent idle in a transaction."""
303+
postgres_conn = _get_superconn(pg_instance)
304+
with postgres_conn.cursor() as cur:
305+
cur.execute("select pg_stat_reset();")
306+
cur.fetchall()
307+
time.sleep(0.5)
308+
309+
check = integration_check(pg_instance)
310+
check.run()
311+
expected_tags = _get_expected_tags(check, pg_instance, db=DB_NAME)
312+
313+
aggregator.assert_metric('postgresql.sessions.idle_in_transaction_time', value=0, count=1, tags=expected_tags)
314+
315+
# Use autocommit=False to keep the transaction open during the sleep
316+
conn = _get_conn(pg_instance, autocommit=False)
317+
with conn.cursor() as cur:
318+
cur.execute('BEGIN')
319+
_increase_txid(cur)
320+
cur.fetchall()
321+
# Keep transaction idle for 5 seconds
322+
time.sleep(5.0)
323+
324+
# Close the connection to end the transaction
325+
conn.close()
326+
327+
# Wait for stats collector to update
328+
time.sleep(1.0)
329+
aggregator.reset()
330+
check.run()
331+
332+
# Verify we now have a greater than 0 seconds of idle transaction time
333+
assert_metric_at_least(
334+
aggregator, 'postgresql.sessions.idle_in_transaction_time', count=1, lower_bound=0.1, tags=expected_tags
335+
)
336+
337+
postgres_conn.close()
338+
287339

288340
def test_unsupported_replication(aggregator, integration_check, pg_instance):
289341
check = integration_check(pg_instance)

0 commit comments

Comments
 (0)