Class: Pgtk::Spy

Inherits:
Object
  • Object
show all
Defined in:
lib/pgtk/spy.rb

Overview

Spy is a decorator for Pool that intercepts and tracks SQL queries. It provides observability into database operations by invoking a callback with the SQL query and its execution time for each database operation.

This class implements the same interface as Pool, but adds instrumentation functionality while delegating actual database operations to the decorated pool. Use Spy for debugging, performance monitoring, or audit logging.

Basic usage:

# Create and configure a regular pool
pool = Pgtk::Pool.new(wire, max: 4)
pool.start!

# Wrap the pool in a spy that tracks all executed queries
queries = []
spy = Pgtk::Spy.new(pool) do |sql, duration|
puts "Query: #{sql}"
puts "Duration: #{duration} seconds"
queries << sql
end

# Use the spy just like a regular pool, with automatic tracking
spy.exec('SELECT * FROM users')

# Transactions also track each query inside the transaction
spy.transaction do |t|
t.exec('UPDATE users SET active = true WHERE id = $1', [42])
t.exec('INSERT INTO audit_log (user_id, action) VALUES ($1, $2)', [42, 'activated'])
end

# Examine collected queries for analysis
puts "Total queries: #{queries.size}"
puts "First query: #{queries.first}"
Author

Yegor Bugayenko ([email protected])

Copyright

Copyright (c) 2019-2026 Yegor Bugayenko

License

MIT

Instance Method Summary collapse

Constructor Details

#initialize(pool) {|String, Float| ... } ⇒ Spy

Constructor.

Yields:

  • (String, Float) —

    Yields the SQL query and execution time



54
55
56
57
# File 'lib/pgtk/spy.rb', line 54

def initialize(pool, &block)
  @pool = pool
  @block = block
end

Instance Method Details

#dump ⇒ Object

Convert internal state into text.



72
73
74
75
76
77
78
# File 'lib/pgtk/spy.rb', line 72

def dump
  [
    @pool.dump,
    '',
    'Pgtk::Spy'
  ].join("\n")
end

#exec(sql) ⇒ Array

Execute a SQL query and track its execution.



84
85
86
87
88
89
# File 'lib/pgtk/spy.rb', line 84

def exec(sql, *)
  start = Time.now
  @pool.exec(sql, *).tap do
    @block&.call(sql.is_a?(Array) ? sql.join(' ') : sql, Time.now - start)
  end
end

#session {|Pgtk::Spy| ... } ⇒ Object

Run statements on a single connection (no transaction) with spying on each SQL query.

Yields:

  • (Pgtk::Spy) —

    Yields a spy bound to one connection



106
107
108
109
110
# File 'lib/pgtk/spy.rb', line 106

def session
  @pool.session do |t|
    yield(Pgtk::Spy.new(t, &@block))
  end
end

#start! ⇒ Object

Start a new connection pool with the given arguments.



60
61
62
# File 'lib/pgtk/spy.rb', line 60

def start!
  @pool.start!
end

#transaction {|Pgtk::Spy| ... } ⇒ Object

Run a transaction with spying on each SQL query.

Yields:



95
96
97
98
99
# File 'lib/pgtk/spy.rb', line 95

def transaction
  @pool.transaction do |t|
    yield(Pgtk::Spy.new(t, &@block))
  end
end

#version ⇒ String

Get the version of PostgreSQL server.



67
68
69
# File 'lib/pgtk/spy.rb', line 67

def version
  @pool.version
end