Skip to content

Commit

Permalink
Merge e9e43f5 into e3bb056
Browse files Browse the repository at this point in the history
  • Loading branch information
fgarces committed Feb 26, 2020
2 parents e3bb056 + e9e43f5 commit 09f174a
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# postgres-vacuum-monitor

## v.0.8.0
- Also report on queries that are being blocked by another process.

## v.0.7.0
- Lower the default `LongTransactions` threshold from 1 hour to 5 minutes and make this configurable via
the `long_running_transaction_threshold_seconds` setting.
Expand Down
12 changes: 12 additions & 0 deletions lib/postgres/vacuum/jobs/monitor_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class MonitorJob

AUTOVACUUM_LAGGING_EVENT = 'AutoVacuumLagging'.freeze
LONG_TRANSACTIONS = 'LongTransactions'.freeze
BLOCKED_QUERIES = 'BlockedQueries'.freeze

def perform(*)
with_each_db_name_and_connection do |name, connection|
Expand Down Expand Up @@ -33,6 +34,17 @@ def perform(*)
tuples_over_limit: row['dead_tuples'].to_i - row['autovacuum_vacuum_tuples'].to_i
)
end

connection.execute(Postgres::Vacuum::Monitor::Query.blocked_queries).each do |row|
reporter_class.report_event(
BLOCKED_QUERIES,
database_name: name,
blocked_pid: row['blocked_pid'],
blocked_statement: row['blocked_statement'],
blocking_pid: row['blocking_pid'],
current_statement_in_blocking_process: row['current_statement_in_blocking_process']
)
end
end

true
Expand Down
30 changes: 30 additions & 0 deletions lib/postgres/vacuum/monitor/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,36 @@ def tables_eligible_vacuuming
ORDER BY age(relfrozenxid) DESC LIMIT 50;
SQL
end

def blocked_queries
# The query was taken from https://wiki.postgresql.org/wiki/Lock_Monitoring
<<-SQL
SELECT blocked_locks.pid AS blocked_pid,
blocked_activity.usename AS blocked_user,
blocking_locks.pid AS blocking_pid,
blocking_activity.usename AS blocking_user,
blocked_activity.query AS blocked_statement,
blocking_activity.query AS current_statement_in_blocking_process,
blocked_activity.application_name AS blocked_application,
blocking_activity.application_name AS blocking_application
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks blocking_locks
ON blocking_locks.locktype = blocked_locks.locktype
AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.GRANTED;
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.7.0'.freeze
VERSION = '0.8.0'.freeze
end
end
end
26 changes: 24 additions & 2 deletions spec/postgres/vacuum/jobs/monitor_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,28 @@ def self.report_event(name, attributes = {})
)
end

it "reports blocked queries" do
allow(mock_connection).to receive(:execute).with(Postgres::Vacuum::Monitor::Query.blocked_queries).and_return(
[
'blocked_pid' => 2,
'blocked_statement' => 'SELECT 1 FROM products',
'blocking_pid' => 3,
'current_statement_in_blocking_process' => 'SELECT 2 FROM products'
]
)

job.perform

expect(TestMetricsReporter).to have_received(:report_event).with(
Postgres::Vacuum::Jobs::MonitorJob::BLOCKED_QUERIES,
database_name: 'postgres_vacuum_monitor_test',
blocked_pid: 2,
blocked_statement: 'SELECT 1 FROM products',
blocking_pid: 3,
current_statement_in_blocking_process: 'SELECT 2 FROM products'
)
end

context "with multiple connection pools" do

class SecondPool < ActiveRecord::Base
Expand All @@ -81,7 +103,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).twice
expect(mock_connection).to have_received(:execute).exactly(3)
end

context "to different databases" do
Expand All @@ -93,7 +115,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(4)
expect(mock_connection).to have_received(:execute).exactly(6)
end
end
end
Expand Down

0 comments on commit 09f174a

Please sign in to comment.