pghero 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pghero might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +6 -0
- data/app/controllers/pg_hero/home_controller.rb +1 -0
- data/app/views/layouts/pg_hero/application.html.erb +4 -0
- data/app/views/pg_hero/home/_queries_table.html.erb +1 -1
- data/app/views/pg_hero/home/index.html.erb +2 -2
- data/app/views/pg_hero/home/indexes.html.erb +1 -1
- data/app/views/pg_hero/home/space.html.erb +2 -0
- data/lib/pghero.rb +48 -16
- data/lib/pghero/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfc35959d2a721f371bbc7f28c7e415485a268c9
|
4
|
+
data.tar.gz: 788408cad05a467b557df63bfb1e8891c2842929
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7246d02545036c314c9191870b48e26698a8eb73bba6ca01fd28a0f98a4110aac2777d1695d1fa4d7870e6101b769b195e6ece9a363828c3d02c36e4716fe7fd
|
7
|
+
data.tar.gz: 7ed33909351e100883ec0b5c6c7fa05100d78cdd7c8b0277ecd8c723bd353482d5146f3cd99fc3a1d2f7ef746a503a69300ced87a266118da5611894bec19012
|
data/README.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
:tada: Database insights made easy
|
4
4
|
|
5
|
+
[View the demo](https://pghero.herokuapp.com/)
|
6
|
+
|
7
|
+
![Screenshot](https://pghero.herokuapp.com/assets/screenshot-691982ac8e93cdaf6d386e318e971dd5.png)
|
8
|
+
|
5
9
|
Supports PostgreSQL 9.2+
|
6
10
|
|
7
11
|
For pure SQL, check out [PgHero.sql](https://github.com/ankane/pghero.sql)
|
@@ -32,6 +36,8 @@ PgHero.long_running_queries
|
|
32
36
|
PgHero.index_usage
|
33
37
|
PgHero.missing_indexes
|
34
38
|
PgHero.unused_indexes
|
39
|
+
PgHero.unused_tables
|
40
|
+
PgHero.database_size
|
35
41
|
PgHero.relation_sizes
|
36
42
|
PgHero.index_hit_rate
|
37
43
|
PgHero.table_hit_rate
|
@@ -16,7 +16,7 @@
|
|
16
16
|
<td><%= query["state"] %></td>
|
17
17
|
<td><%= query["source"] %></td>
|
18
18
|
<td><%= query["waiting"] == "t" ? "true" : "false" %></td>
|
19
|
-
<td><%= query["
|
19
|
+
<td><%= time_ago_in_words(query["started_at"], include_seconds: true) %></td>
|
20
20
|
<td class="text-right"><%= button_to "Kill", kill_path(pid: query["pid"]), class: "btn btn-info" %></td>
|
21
21
|
</tr>
|
22
22
|
<tr>
|
@@ -15,14 +15,14 @@
|
|
15
15
|
</div>
|
16
16
|
<div class="alert alert-<%= @missing_indexes.empty? ? "success" : "warning" %>">
|
17
17
|
<% if @missing_indexes.any? %>
|
18
|
-
<%= pluralize(@missing_indexes.size, "possibly missing
|
18
|
+
<%= pluralize(@missing_indexes.size, "possibly missing index") %>
|
19
19
|
<% else %>
|
20
20
|
No missing indexes
|
21
21
|
<% end %>
|
22
22
|
</div>
|
23
23
|
<div class="alert alert-<%= @unused_indexes.empty? ? "success" : "warning" %>">
|
24
24
|
<% if @unused_indexes.any? %>
|
25
|
-
<%= pluralize(@unused_indexes.size, "unused
|
25
|
+
<%= pluralize(@unused_indexes.size, "unused index") %>
|
26
26
|
<% else %>
|
27
27
|
No unused indexes
|
28
28
|
<% end %>
|
@@ -13,7 +13,7 @@
|
|
13
13
|
<tr>
|
14
14
|
<td><%= query["table"] %></td>
|
15
15
|
<td style="width: 30%;"><%= query["percent_of_times_index_used"] %></td>
|
16
|
-
<td style="width: 20%;"><%= query["rows_in_table"] %></td>
|
16
|
+
<td style="width: 20%;"><%= number_with_delimiter(query["rows_in_table"]) %></td>
|
17
17
|
</tr>
|
18
18
|
<% end %>
|
19
19
|
</tbody>
|
data/lib/pghero.rb
CHANGED
@@ -2,17 +2,23 @@ require "pghero/version"
|
|
2
2
|
require "pghero/engine" if defined?(Rails)
|
3
3
|
|
4
4
|
module PgHero
|
5
|
+
# hack for connection
|
6
|
+
class Connection < ActiveRecord::Base
|
7
|
+
establish_connection ENV["PGHERO_DATABASE_URL"] if ENV["PGHERO_DATABASE_URL"]
|
8
|
+
end
|
9
|
+
|
5
10
|
class << self
|
6
11
|
|
7
12
|
def running_queries
|
8
|
-
|
13
|
+
select_all %Q{
|
9
14
|
SELECT
|
10
15
|
pid,
|
11
16
|
state,
|
12
17
|
application_name AS source,
|
13
18
|
age(now(), xact_start) AS duration,
|
14
19
|
waiting,
|
15
|
-
query
|
20
|
+
query,
|
21
|
+
xact_start AS started_at
|
16
22
|
FROM
|
17
23
|
pg_stat_activity
|
18
24
|
WHERE
|
@@ -25,14 +31,15 @@ module PgHero
|
|
25
31
|
end
|
26
32
|
|
27
33
|
def long_running_queries
|
28
|
-
|
34
|
+
select_all %Q{
|
29
35
|
SELECT
|
30
36
|
pid,
|
31
37
|
state,
|
32
38
|
application_name AS source,
|
33
39
|
age(now(), xact_start) AS duration,
|
34
40
|
waiting,
|
35
|
-
query
|
41
|
+
query,
|
42
|
+
xact_start AS started_at
|
36
43
|
FROM
|
37
44
|
pg_stat_activity
|
38
45
|
WHERE
|
@@ -46,7 +53,7 @@ module PgHero
|
|
46
53
|
end
|
47
54
|
|
48
55
|
def index_hit_rate
|
49
|
-
|
56
|
+
select_all(%Q{
|
50
57
|
SELECT
|
51
58
|
(sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read),0) AS rate
|
52
59
|
FROM
|
@@ -55,7 +62,7 @@ module PgHero
|
|
55
62
|
end
|
56
63
|
|
57
64
|
def table_hit_rate
|
58
|
-
|
65
|
+
select_all(%Q{
|
59
66
|
SELECT
|
60
67
|
sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read),0) AS rate
|
61
68
|
FROM
|
@@ -64,7 +71,7 @@ module PgHero
|
|
64
71
|
end
|
65
72
|
|
66
73
|
def index_usage
|
67
|
-
|
74
|
+
select_all %Q{
|
68
75
|
SELECT
|
69
76
|
relname AS table,
|
70
77
|
CASE idx_scan
|
@@ -81,8 +88,9 @@ module PgHero
|
|
81
88
|
end
|
82
89
|
|
83
90
|
def missing_indexes
|
84
|
-
|
85
|
-
SELECT
|
91
|
+
select_all %Q{
|
92
|
+
SELECT
|
93
|
+
relname AS table,
|
86
94
|
CASE idx_scan
|
87
95
|
WHEN 0 THEN 'Insufficient data'
|
88
96
|
ELSE (100 * idx_scan / (seq_scan + idx_scan))::text
|
@@ -91,7 +99,8 @@ module PgHero
|
|
91
99
|
FROM
|
92
100
|
pg_stat_user_tables
|
93
101
|
WHERE
|
94
|
-
idx_scan
|
102
|
+
idx_scan > 0
|
103
|
+
AND idx_scan < 95
|
95
104
|
AND n_live_tup >= 10000
|
96
105
|
ORDER BY
|
97
106
|
n_live_tup DESC,
|
@@ -99,8 +108,23 @@ module PgHero
|
|
99
108
|
}
|
100
109
|
end
|
101
110
|
|
111
|
+
def unused_tables
|
112
|
+
select_all %Q{
|
113
|
+
SELECT
|
114
|
+
relname AS table,
|
115
|
+
n_live_tup rows_in_table
|
116
|
+
FROM
|
117
|
+
pg_stat_user_tables
|
118
|
+
WHERE
|
119
|
+
idx_scan = 0
|
120
|
+
ORDER BY
|
121
|
+
n_live_tup DESC,
|
122
|
+
relname ASC
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
102
126
|
def unused_indexes
|
103
|
-
|
127
|
+
select_all %Q{
|
104
128
|
SELECT
|
105
129
|
relname AS table,
|
106
130
|
indexrelname AS index,
|
@@ -121,7 +145,7 @@ module PgHero
|
|
121
145
|
end
|
122
146
|
|
123
147
|
def relation_sizes
|
124
|
-
|
148
|
+
select_all %Q{
|
125
149
|
SELECT
|
126
150
|
c.relname AS name,
|
127
151
|
CASE WHEN c.relkind = 'r' THEN 'table' ELSE 'index' END AS type,
|
@@ -140,12 +164,16 @@ module PgHero
|
|
140
164
|
}
|
141
165
|
end
|
142
166
|
|
167
|
+
def database_size
|
168
|
+
select_all("SELECT pg_size_pretty(pg_database_size(current_database()))").first["pg_size_pretty"]
|
169
|
+
end
|
170
|
+
|
143
171
|
def kill(pid)
|
144
|
-
|
172
|
+
connection.execute("SELECT pg_cancel_backend(#{pid.to_i})").first["pg_cancel_backend"] == "t"
|
145
173
|
end
|
146
174
|
|
147
175
|
def kill_all
|
148
|
-
|
176
|
+
select_all %Q{
|
149
177
|
SELECT
|
150
178
|
pg_terminate_backend(pid)
|
151
179
|
FROM
|
@@ -157,9 +185,13 @@ module PgHero
|
|
157
185
|
true
|
158
186
|
end
|
159
187
|
|
160
|
-
def
|
188
|
+
def select_all(sql)
|
161
189
|
# squish for logs
|
162
|
-
|
190
|
+
connection.select_all(sql.squish).to_a
|
191
|
+
end
|
192
|
+
|
193
|
+
def connection
|
194
|
+
@connection ||= Connection.connection
|
163
195
|
end
|
164
196
|
|
165
197
|
end
|
data/lib/pghero/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pghero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|