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 © 2019-2025 Yegor Bugayenko

License

MIT

Instance Method Summary collapse

Constructor Details

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

Constructor.

Parameters:

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

#dumpObject

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.

Parameters:

  • sql (String)

    The SQL query with params inside (possibly)

Returns:

  • (Array)

    Result rows



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

def exec(sql, *)
  start = Time.now
  ret = @pool.exec(sql, *)
  @block&.call(sql.is_a?(Array) ? sql.join(' ') : sql, Time.now - start)
  ret
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:

Returns:

  • (Object)

    Result of the block



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

#versionString

Get the version of PostgreSQL server.

Returns:

  • (String)

    Version of PostgreSQL server



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

def version
  @pool.version
end