pg_monitor 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c4c7d58e46ed8ee3d95495bb02fc8476bbc38b6f58e00f372b685b69691f37c
4
- data.tar.gz: f59c2029bb6a99e861c65702ab590fdc6980e9b46eca30186629165da1b43e94
3
+ metadata.gz: a3ed6ac82b08dfd9c2df7acac700b04737c1d0c00a5c7d754dd116bad4fe2571
4
+ data.tar.gz: dc7f2645d7eb226fc0a319143286a67273a41d3dc150c20815edc84358b7bedd
5
5
  SHA512:
6
- metadata.gz: e5480cd130a99bd63468032c7cfbb45ce012b89fabbaba67495eaa418a723b08eec1b0ee67765447b84bad37211f1185d78b10244fb5f78bd46d05baaa937f34
7
- data.tar.gz: d2a72a77da40a346dee9edc1e573c9c668dce9a291e7edb043a2e4c13e05db1518aa3dc70ec65b0868a8e20bb6f12f4b0d0a700b5b60f86b78ce86cf6f712f8c
6
+ metadata.gz: 707e852d5b13d32d44624b5c1eee434a3568b1eea08c27ba7aab4e8fb68a6beb372b7b9577dbb7ec4c7f322f1f82249d1ce589d01a4516ddd20d750e9f17d29f
7
+ data.tar.gz: 47343bed61b2214ce0df361531ff3e6318635c0f676042fafd4400cb5062bafd07d54be3d170a776d6aa48dd7b8809ee74924080aba53da8bc8e015766d7410d
data/README.md CHANGED
@@ -7,8 +7,8 @@ It would integrate seamlessly with a Rails application in the future, and would
7
7
 
8
8
  - View index usage statistics (last used, scan count, etc.)
9
9
  - Identify slow queries using `pg_stat_statements`
10
- - Works with the existing Rails database configuration
11
- - [TBD] Provides a simple HTML interface for monitoring
10
+ - Works with existing Rails database configuration, if present
11
+ - Provides a simple HTML interface for monitoring
12
12
 
13
13
  ## Installation
14
14
 
@@ -59,17 +59,19 @@ Execute the above SQL query by connecting to your database using `psql` or any o
59
59
 
60
60
  ## Usage
61
61
 
62
- Mount the engine in `config/routes.rb`:
62
+ To run the PgMonitor, follow these steps:
63
63
 
64
- ```ruby
65
- mount PgMonitor::Engine, at: '/pg_monitor'
66
- ```
64
+ 1. Ensure you have all the dependencies installed:
65
+ ```sh
66
+ bundle install
67
+ ```
67
68
 
68
- Then, navigate to:
69
+ 2. Run the server using the Rake task:
70
+ ```sh
71
+ rake server
72
+ ```
69
73
 
70
- ```
71
- http://localhost:3000/pg_monitor
72
- ```
74
+ 3. The application should now be running. You can access it in your web browser at `http://localhost:4567`.
73
75
 
74
76
  ### Programmatic Access
75
77
 
data/Rakefile CHANGED
@@ -8,3 +8,10 @@ RSpec::Core::RakeTask.new(:spec)
8
8
  require "standard/rake"
9
9
 
10
10
  task default: %i[spec standard]
11
+
12
+ require_relative "lib/pg_monitor/web_app"
13
+
14
+ desc "Start the PgMonitor web application"
15
+ task :server do
16
+ PgMonitorApp.run!
17
+ end
@@ -7,13 +7,15 @@ module PgMonitor
7
7
  def fetch
8
8
  query = <<~SQL
9
9
  SELECT
10
- pg_class.relname AS table_name,
10
+ relname AS table_name,
11
11
  indexrelname AS index_name,
12
12
  idx_scan AS index_scan_count,
13
13
  idx_tup_read AS tuples_read,
14
- idx_tup_fetch AS tuples_fetched
15
- FROM pg_stat_all_indexes
16
- JOIN pg_class ON pg_stat_all_indexes.relid = pg_class.oid
14
+ idx_tup_fetch AS tuples_fetched,
15
+ last_idx_scan AS last_index_scan,
16
+ pg_size_pretty(pg_relation_size(indexrelid)) AS index_size,
17
+ pg_size_pretty(pg_total_relation_size(indexrelid)) AS total_index_size
18
+ FROM pg_stat_user_indexes
17
19
  ORDER BY idx_scan DESC;
18
20
  SQL
19
21
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgMonitor
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
@@ -0,0 +1,44 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>PgMonitor</title>
5
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
6
+ <script>
7
+ function showTab(tabId) {
8
+ document.querySelectorAll('.tab').forEach(tab => {
9
+ tab.classList.remove('active');
10
+ });
11
+ document.getElementById(tabId).classList.add('active');
12
+ }
13
+ </script>
14
+ <style>
15
+ .tab {
16
+ display: none;
17
+ }
18
+ .tab.active {
19
+ display: block;
20
+ }
21
+ body {
22
+ padding: 10px;
23
+ }
24
+ </style>
25
+ </head>
26
+ <body>
27
+ <div class="container">
28
+ <div class="btn-group tab-buttons" role="group">
29
+ <button type="button" class="btn btn-primary" onclick="showTab('index-usage')">Index Usage</button>
30
+ <button type="button" class="btn btn-secondary" onclick="showTab('slow-queries')">Slow Queries</button>
31
+ </div>
32
+
33
+ <div id="index-usage" class="tab active">
34
+ <h1>Index Usage Statistics</h1>
35
+ <%= erb :index_usage_table, layout: false, locals: { index_usage: @index_usage } %>
36
+ </div>
37
+
38
+ <div id="slow-queries" class="tab">
39
+ <h1>Slow Queries</h1>
40
+ <%= erb :slow_queries_table, layout: false, locals: { slow_queries: @slow_queries } %>
41
+ </div>
42
+ </div>
43
+ </body>
44
+ </html>
@@ -0,0 +1,28 @@
1
+ <table class="table table-striped">
2
+ <thead class="thead-light">
3
+ <tr>
4
+ <th>Table Name</th>
5
+ <th>Index Name</th>
6
+ <th>Index Scan Count</th>
7
+ <th>Tuples Read</th>
8
+ <th>Tuples Fetched</th>
9
+ <th>Last Index Scan</th>
10
+ <th>Index Size</th>
11
+ <th>Total Index Size</th>
12
+ </tr>
13
+ </thead>
14
+ <tbody>
15
+ <% index_usage.each do |row| %>
16
+ <tr>
17
+ <td><%= row["table_name"] %></td>
18
+ <td><%= row["index_name"] %></td>
19
+ <td><%= row["index_scan_count"] %></td>
20
+ <td><%= row["tuples_read"] %></td>
21
+ <td><%= row["tuples_fetched"] %></td>
22
+ <td><%= row["last_index_scan"] %></td>
23
+ <td><%= row["index_size"] %></td>
24
+ <td><%= row["total_index_size"] %></td>
25
+ </tr>
26
+ <% end %>
27
+ </tbody>
28
+ </table>
@@ -0,0 +1,35 @@
1
+ <table class="table table-striped">
2
+ <thead class="thead-light">
3
+ <tr>
4
+ <th>Query</th>
5
+ <th>Calls</th>
6
+ <th>Total Time</th>
7
+ <th>Mean Time</th>
8
+ <th>Max Time</th>
9
+ </tr>
10
+ </thead>
11
+ <tbody>
12
+ <% slow_queries.each do |row| %>
13
+ <tr>
14
+ <td>
15
+ <% full_query = row["query"] %>
16
+ <% if full_query.length > 100 %>
17
+ <span class="query-short" data-full-query="<%= ERB::Util.html_escape full_query %>">
18
+ <%= full_query[0, 100] %>...
19
+ </span>
20
+ <a href="#" class="show-more"
21
+ onclick="var el = this.previousElementSibling; el.textContent = el.getAttribute('data-full-query'); this.style.display='none'; return false;">
22
+ show more
23
+ </a>
24
+ <% else %>
25
+ <%= full_query %>
26
+ <% end %>
27
+ </td>
28
+ <td><%= row["calls"] %></td>
29
+ <td><%= row["total_time"] %></td>
30
+ <td><%= row["mean_time"] %></td>
31
+ <td><%= row["max_time"] %></td>
32
+ </tr>
33
+ <% end %>
34
+ </tbody>
35
+ </table>
@@ -0,0 +1,12 @@
1
+ require "sinatra"
2
+ require_relative "db_connection"
3
+ require_relative "index_usage"
4
+ require_relative "slow_queries"
5
+
6
+ class PgMonitorApp < Sinatra::Base
7
+ get "/" do
8
+ @index_usage = PgMonitor::IndexUsage.fetch
9
+ @slow_queries = PgMonitor::SlowQueries.fetch(limit: 10)
10
+ erb :index
11
+ end
12
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_monitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hassan Murtaza
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-03-08 00:00:00.000000000 Z
11
+ date: 2025-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -45,6 +45,10 @@ files:
45
45
  - lib/pg_monitor/index_usage.rb
46
46
  - lib/pg_monitor/slow_queries.rb
47
47
  - lib/pg_monitor/version.rb
48
+ - lib/pg_monitor/views/index.erb
49
+ - lib/pg_monitor/views/index_usage_table.erb
50
+ - lib/pg_monitor/views/slow_queries_table.erb
51
+ - lib/pg_monitor/web_app.rb
48
52
  - postgresql.conf
49
53
  - sig/pg_monitor.rbs
50
54
  homepage: https://github.com/hmurtaza7/pg_monitor