Skip to content

Commit

Permalink
Expose clients maxwait time in SHOW CLIENTS response via admin (#639)
Browse files Browse the repository at this point in the history
* 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.

* Use maxwait instead of maxwait_seconds to match pools column name

---------

Co-authored-by: Calvin Hughes <9379992+calvinhughes@users.noreply.github.com>
  • Loading branch information
calvinhughes and calvinhughes authored Nov 13, 2023
1 parent 7c37da2 commit 998cc16
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,13 +690,16 @@ where
("query_count", DataType::Numeric),
("error_count", DataType::Numeric),
("age_seconds", DataType::Numeric),
("maxwait", DataType::Numeric),
("maxwait_us", DataType::Numeric),
];

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

for (_, client) in new_map {
let max_wait = client.max_wait_time.load(Ordering::Relaxed);
let row = vec![
format!("{:#010X}", client.client_id()),
client.pool_name(),
Expand All @@ -710,6 +713,8 @@ where
.duration_since(client.connect_time())
.as_secs()
.to_string(),
(max_wait / 1_000_000).to_string(),
(max_wait % 1_000_000).to_string(),
];

res.put(data_row(&row));
Expand Down
34 changes: 34 additions & 0 deletions tests/ruby/stats_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,40 @@
admin_conn.close
connections.map(&:close)
end

context "when client has waited for a server" do
let(:processes) { Helpers::Pgcat.single_instance_setup("sharded_db", 2) }

it "shows correct maxwait" do
threads = []
connections = Array.new(3) { |i| PG::connect("#{pgcat_conn_str}?application_name=app#{i}") }
connections.each do |c|
threads << Thread.new { c.async_exec("SELECT pg_sleep(1.5)") rescue nil }
end

sleep(2.5) # Allow time for stats to update
admin_conn = PG::connect(processes.pgcat.admin_connection_string)
results = admin_conn.async_exec("SHOW CLIENTS")

normal_client_results = results.reject { |r| r["database"] == "pgcat" }

non_waiting_clients = normal_client_results.select { |c| c["maxwait"] == "0" }
waiting_clients = normal_client_results.select { |c| c["maxwait"].to_i > 0 }

expect(non_waiting_clients.count).to eq(2)
non_waiting_clients.each do |client|
expect(client["maxwait_us"].to_i).to be_between(0, 50_000)
end

expect(waiting_clients.count).to eq(1)
waiting_clients.each do |client|
expect(client["maxwait_us"].to_i).to be_within(200_000).of(500_000)
end

admin_conn.close
connections.map(&:close)
end
end
end


Expand Down

0 comments on commit 998cc16

Please sign in to comment.