Skip to content

Commit

Permalink
Add connection monitoring (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
fgarces committed Oct 15, 2020
1 parent 1f6fc20 commit 068437a
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 4 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# postgres-vacuum-monitor

## v.0.8.0
## v.10.0
- Add events for connection idle time and state.

## v.0.9.0
- Add the application name in the event.

## v.0.8.0
Expand Down
16 changes: 16 additions & 0 deletions lib/postgres/vacuum/jobs/monitor_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class MonitorJob
AUTOVACUUM_LAGGING_EVENT = 'AutoVacuumLagging'.freeze
LONG_TRANSACTIONS = 'LongTransactions'.freeze
BLOCKED_QUERIES = 'BlockedQueries'.freeze
CONNECTION_STATE = 'ConnectionState'.freeze
CONNECTION_IDLE_TIME = 'ConnectionIdleTime'.freeze

def perform(*)
with_each_db_name_and_connection do |name, connection|
Expand Down Expand Up @@ -47,6 +49,20 @@ def perform(*)
current_statement_in_blocking_process: row['current_statement_in_blocking_process']
)
end

connection.execute(Postgres::Vacuum::Monitor::Query.connection_state).each do |row|
reporter_class.report_event(CONNECTION_STATE, database_name: name, state: row['state'], connection_count: row['connection_count'])
end

connection.execute(Postgres::Vacuum::Monitor::Query.connection_idle_time).each do |row|
reporter_class.report_event(
CONNECTION_IDLE_TIME,
database_name: name,
max: row['max'],
median: row['median'],
percentile_90: row['percentile_90']
)
end
end

true
Expand Down
22 changes: 22 additions & 0 deletions lib/postgres/vacuum/monitor/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,28 @@ def blocked_queries
WHERE NOT blocked_locks.GRANTED;
SQL
end

def connection_state
<<-SQL
SELECT
state, count(*) as connection_count
FROM pg_stat_activity
GROUP BY state
ORDER BY count DESC;
SQL
end

def connection_idle_time
<<-SQL
SELECT
max(EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - state_change))) as max,
percentile_cont(0.5) within GROUP (ORDER BY EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - state_change)) DESC) AS median,
percentile_cont(0.9) within GROUP (ORDER BY EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - state_change)) DESC) AS percentile_90
FROM pg_stat_activity
WHERE state = 'idle'
LIMIT 1000;
SQL
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/postgres/vacuum/monitor/version.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Postgres
module Vacuum
module Monitor
VERSION = '0.9.0'.freeze
VERSION = '0.10.0'.freeze
end
end
end
35 changes: 33 additions & 2 deletions spec/postgres/vacuum/jobs/monitor_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,37 @@ def self.report_event(name, attributes = {})
)
end

it "reports connection state" do
allow(mock_connection).to receive(:execute).with(Postgres::Vacuum::Monitor::Query.connection_state).and_return(
['connection_count' => 4, 'state' => 'idle']
)

job.perform

expect(TestMetricsReporter).to have_received(:report_event).with(
Postgres::Vacuum::Jobs::MonitorJob::CONNECTION_STATE,
database_name: 'postgres_vacuum_monitor_test',
connection_count: 4,
state: 'idle'
)
end

it "reports connection idle time" do
allow(mock_connection).to receive(:execute).with(Postgres::Vacuum::Monitor::Query.connection_idle_time).and_return(
['max' => 3.1, 'median' => 222.22, 'percentile_90' => 9323.323]
)

job.perform

expect(TestMetricsReporter).to have_received(:report_event).with(
Postgres::Vacuum::Jobs::MonitorJob::CONNECTION_IDLE_TIME,
database_name: 'postgres_vacuum_monitor_test',
max: 3.1,
median: 222.22,
percentile_90: 9323.323
)
end

context "with multiple connection pools" do

class SecondPool < ActiveRecord::Base
Expand All @@ -107,7 +138,7 @@ class SecondPool < ActiveRecord::Base

it "reports once for a single database." do
expect(job.perform).to eq true
expect(mock_connection).to have_received(:execute).exactly(3)
expect(mock_connection).to have_received(:execute).exactly(5)
end

context "to different databases" do
Expand All @@ -119,7 +150,7 @@ class SecondPool < ActiveRecord::Base

it "reports twice for two databases" do
expect(job.perform).to eq true
expect(mock_connection).to have_received(:execute).exactly(6)
expect(mock_connection).to have_received(:execute).exactly(10)
end
end
end
Expand Down

0 comments on commit 068437a

Please sign in to comment.