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).start(4)

# 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



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

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

Instance Method Details

#exec(sql, *args) ⇒ Array

Execute a SQL query and track its execution.

Parameters:

  • sql (String)

    The SQL query with params inside (possibly)

  • args (Array)

    List of arguments

Returns:

  • (Array)

    Result rows



70
71
72
73
74
75
# File 'lib/pgtk/spy.rb', line 70

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

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

Run a transaction with spying on each SQL query.

Yields:

Returns:

  • (Object)

    Result of the block



81
82
83
84
85
# File 'lib/pgtk/spy.rb', line 81

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



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

def version
  @pool.version
end