Skip to content

Commit 5f6a5b3

Browse files
committed
Expose clients maxwait time in SHOW CLIENTS response via PgCat admin
Displays the maxwait via maxwait_seconds and maxwait_us columns for each client that can be used to track down the wait time per client in a case where the overall pool stats shows waiting time. The maxwait_us, similar to the pool stats setup, is configured to display as a remainder alongside the maxwait_seconds.
1 parent dae240d commit 5f6a5b3

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

src/admin.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,13 +690,16 @@ where
690690
("query_count", DataType::Numeric),
691691
("error_count", DataType::Numeric),
692692
("age_seconds", DataType::Numeric),
693+
("maxwait_seconds", DataType::Numeric),
694+
("maxwait_us", DataType::Numeric),
693695
];
694696

695697
let new_map = get_client_stats();
696698
let mut res = BytesMut::new();
697699
res.put(row_description(&columns));
698700

699701
for (_, client) in new_map {
702+
let max_wait = client.max_wait_time.load(Ordering::Relaxed);
700703
let row = vec![
701704
format!("{:#010X}", client.client_id()),
702705
client.pool_name(),
@@ -710,6 +713,8 @@ where
710713
.duration_since(client.connect_time())
711714
.as_secs()
712715
.to_string(),
716+
(max_wait / 1_000_000).to_string(),
717+
(max_wait % 1_000_000).to_string(),
713718
];
714719

715720
res.put(data_row(&row));

tests/ruby/stats_spec.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,40 @@
329329
admin_conn.close
330330
connections.map(&:close)
331331
end
332+
333+
context "when client has waited for a server" do
334+
let(:processes) { Helpers::Pgcat.single_instance_setup("sharded_db", 2) }
335+
336+
it "shows correct maxwait" do
337+
threads = []
338+
connections = Array.new(3) { |i| PG::connect("#{pgcat_conn_str}?application_name=app#{i}") }
339+
connections.each do |c|
340+
threads << Thread.new { c.async_exec("SELECT pg_sleep(1.5)") rescue nil }
341+
end
342+
343+
sleep(2.5) # Allow time for stats to update
344+
admin_conn = PG::connect(processes.pgcat.admin_connection_string)
345+
results = admin_conn.async_exec("SHOW CLIENTS")
346+
347+
normal_client_results = results.reject { |r| r["database"] == "pgcat" }
348+
349+
non_waiting_clients = normal_client_results.select { |c| c["maxwait_seconds"] == "0" }
350+
waiting_clients = normal_client_results.select { |c| c["maxwait_seconds"].to_i > 0 }
351+
352+
expect(non_waiting_clients.count).to eq(2)
353+
non_waiting_clients.each do |client|
354+
expect(client["maxwait_us"].to_i).to be_between(0, 50_000)
355+
end
356+
357+
expect(waiting_clients.count).to eq(1)
358+
waiting_clients.each do |client|
359+
expect(client["maxwait_us"].to_i).to be_within(200_000).of(500_000)
360+
end
361+
362+
admin_conn.close
363+
connections.map(&:close)
364+
end
365+
end
332366
end
333367

334368

0 commit comments

Comments
 (0)