pghero 3.1.0 → 3.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/app/assets/javascripts/pghero/Chart.bundle.js +23379 -19766
- data/app/assets/javascripts/pghero/application.js +13 -12
- data/app/assets/javascripts/pghero/chartkick.js +834 -764
- data/app/assets/javascripts/pghero/highlight.min.js +440 -0
- data/app/assets/javascripts/pghero/jquery.js +318 -197
- data/app/assets/javascripts/pghero/nouislider.js +676 -1066
- data/app/assets/stylesheets/pghero/application.css +8 -2
- data/app/assets/stylesheets/pghero/nouislider.css +4 -10
- data/app/controllers/pg_hero/home_controller.rb +41 -12
- data/app/helpers/pg_hero/home_helper.rb +2 -2
- data/app/views/layouts/pg_hero/application.html.erb +1 -1
- data/app/views/pg_hero/home/_query_stats_slider.html.erb +6 -6
- data/app/views/pg_hero/home/connections.html.erb +6 -6
- data/app/views/pg_hero/home/index.html.erb +3 -1
- data/app/views/pg_hero/home/queries.html.erb +4 -2
- data/app/views/pg_hero/home/relation_space.html.erb +1 -1
- data/app/views/pg_hero/home/show_query.html.erb +16 -12
- data/app/views/pg_hero/home/space.html.erb +44 -40
- data/app/views/pg_hero/home/system.html.erb +6 -6
- data/lib/generators/pghero/query_stats_generator.rb +1 -0
- data/lib/generators/pghero/space_stats_generator.rb +1 -0
- data/lib/pghero/engine.rb +1 -1
- data/lib/pghero/methods/basic.rb +5 -8
- data/lib/pghero/methods/connections.rb +4 -4
- data/lib/pghero/methods/constraints.rb +1 -1
- data/lib/pghero/methods/indexes.rb +8 -8
- data/lib/pghero/methods/kill.rb +1 -1
- data/lib/pghero/methods/maintenance.rb +3 -3
- data/lib/pghero/methods/queries.rb +2 -2
- data/lib/pghero/methods/query_stats.rb +19 -19
- data/lib/pghero/methods/replication.rb +2 -2
- data/lib/pghero/methods/sequences.rb +2 -2
- data/lib/pghero/methods/space.rb +18 -12
- data/lib/pghero/methods/suggested_indexes.rb +11 -6
- data/lib/pghero/methods/system.rb +10 -4
- data/lib/pghero/methods/tables.rb +4 -5
- data/lib/pghero/version.rb +1 -1
- data/lib/pghero.rb +28 -26
- data/lib/tasks/pghero.rake +11 -1
- data/licenses/LICENSE-chart.js.txt +1 -1
- data/licenses/LICENSE-date-fns.txt +21 -20
- data/licenses/LICENSE-kurkle-color.txt +9 -0
- metadata +5 -4
- data/app/assets/javascripts/pghero/highlight.pack.js +0 -2
@@ -2,7 +2,7 @@ module PgHero
|
|
2
2
|
module Methods
|
3
3
|
module Indexes
|
4
4
|
def index_hit_rate
|
5
|
-
select_one
|
5
|
+
select_one <<~SQL
|
6
6
|
SELECT
|
7
7
|
(sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read), 0) AS rate
|
8
8
|
FROM
|
@@ -11,7 +11,7 @@ module PgHero
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def index_caching
|
14
|
-
select_all
|
14
|
+
select_all <<~SQL
|
15
15
|
SELECT
|
16
16
|
schemaname AS schema,
|
17
17
|
relname AS table,
|
@@ -29,7 +29,7 @@ module PgHero
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def index_usage
|
32
|
-
select_all
|
32
|
+
select_all <<~SQL
|
33
33
|
SELECT
|
34
34
|
schemaname AS schema,
|
35
35
|
relname AS table,
|
@@ -47,7 +47,7 @@ module PgHero
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def missing_indexes
|
50
|
-
select_all
|
50
|
+
select_all <<~SQL
|
51
51
|
SELECT
|
52
52
|
schemaname AS schema,
|
53
53
|
relname AS table,
|
@@ -69,7 +69,7 @@ module PgHero
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def unused_indexes(max_scans: 50, across: [])
|
72
|
-
result = select_all_size
|
72
|
+
result = select_all_size <<~SQL
|
73
73
|
SELECT
|
74
74
|
schemaname AS schema,
|
75
75
|
relname AS table,
|
@@ -104,7 +104,7 @@ module PgHero
|
|
104
104
|
end
|
105
105
|
|
106
106
|
def last_stats_reset_time
|
107
|
-
select_one
|
107
|
+
select_one <<~SQL
|
108
108
|
SELECT
|
109
109
|
pg_stat_get_db_stat_reset_time(oid) AS reset_time
|
110
110
|
FROM
|
@@ -126,7 +126,7 @@ module PgHero
|
|
126
126
|
# TODO parse array properly
|
127
127
|
# https://stackoverflow.com/questions/2204058/list-columns-with-indexes-in-postgresql
|
128
128
|
def indexes
|
129
|
-
indexes = select_all(
|
129
|
+
indexes = select_all(<<~SQL
|
130
130
|
SELECT
|
131
131
|
schemaname AS schema,
|
132
132
|
t.relname AS table,
|
@@ -186,7 +186,7 @@ module PgHero
|
|
186
186
|
# thanks @jberkus and @mbanck
|
187
187
|
def index_bloat(min_size: nil)
|
188
188
|
min_size ||= index_bloat_bytes
|
189
|
-
select_all
|
189
|
+
select_all <<~SQL
|
190
190
|
WITH btree_index_atts AS (
|
191
191
|
SELECT
|
192
192
|
nspname, relname, reltuples, relpages, indrelid, relam,
|
data/lib/pghero/methods/kill.rb
CHANGED
@@ -9,7 +9,7 @@ module PgHero
|
|
9
9
|
max_value = max_value.to_i
|
10
10
|
threshold = threshold.to_i
|
11
11
|
|
12
|
-
select_all
|
12
|
+
select_all <<~SQL
|
13
13
|
SELECT
|
14
14
|
n.nspname AS schema,
|
15
15
|
c.relname AS table,
|
@@ -35,7 +35,7 @@ module PgHero
|
|
35
35
|
|
36
36
|
def vacuum_progress
|
37
37
|
if server_version_num >= 90600
|
38
|
-
select_all
|
38
|
+
select_all <<~SQL
|
39
39
|
SELECT
|
40
40
|
pid,
|
41
41
|
phase
|
@@ -50,7 +50,7 @@ module PgHero
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def maintenance_info
|
53
|
-
select_all
|
53
|
+
select_all <<~SQL
|
54
54
|
SELECT
|
55
55
|
schemaname AS schema,
|
56
56
|
relname AS table,
|
@@ -2,7 +2,7 @@ module PgHero
|
|
2
2
|
module Methods
|
3
3
|
module Queries
|
4
4
|
def running_queries(min_duration: nil, all: false)
|
5
|
-
query =
|
5
|
+
query = <<~SQL
|
6
6
|
SELECT
|
7
7
|
pid,
|
8
8
|
state,
|
@@ -36,7 +36,7 @@ module PgHero
|
|
36
36
|
# from https://wiki.postgresql.org/wiki/Lock_Monitoring
|
37
37
|
# and https://big-elephants.com/2013-09/exploring-query-locks-in-postgres/
|
38
38
|
def blocked_queries
|
39
|
-
query =
|
39
|
+
query = <<~SQL
|
40
40
|
SELECT
|
41
41
|
COALESCE(blockingl.relation::regclass::text,blockingl.locktype) as locked_item,
|
42
42
|
blockeda.pid AS blocked_pid,
|
@@ -162,8 +162,9 @@ module PgHero
|
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
165
|
-
def clean_query_stats
|
166
|
-
|
165
|
+
def clean_query_stats(before: nil)
|
166
|
+
before ||= 14.days.ago
|
167
|
+
PgHero::QueryStats.where(database: id).where("captured_at < ?", before).delete_all
|
167
168
|
end
|
168
169
|
|
169
170
|
def slow_queries(query_stats: nil, **options)
|
@@ -171,10 +172,11 @@ module PgHero
|
|
171
172
|
query_stats.select { |q| q[:calls].to_i >= slow_query_calls.to_i && q[:average_time].to_f >= slow_query_ms.to_f }
|
172
173
|
end
|
173
174
|
|
175
|
+
# TODO option to include current period
|
174
176
|
def query_hash_stats(query_hash, user: nil)
|
175
177
|
if historical_query_stats_enabled? && supports_query_hash?
|
176
178
|
start_at = 24.hours.ago
|
177
|
-
select_all_stats
|
179
|
+
select_all_stats <<~SQL
|
178
180
|
SELECT
|
179
181
|
captured_at,
|
180
182
|
total_time / 1000 / 60 AS total_minutes,
|
@@ -204,7 +206,7 @@ module PgHero
|
|
204
206
|
limit ||= 100
|
205
207
|
sort ||= "total_minutes"
|
206
208
|
total_time = server_version_num >= 130000 ? "(total_plan_time + total_exec_time)" : "total_time"
|
207
|
-
query =
|
209
|
+
query = <<~SQL
|
208
210
|
WITH query_stats AS (
|
209
211
|
SELECT
|
210
212
|
LEFT(query, 10000) AS query,
|
@@ -237,7 +239,7 @@ module PgHero
|
|
237
239
|
FROM
|
238
240
|
query_stats
|
239
241
|
ORDER BY
|
240
|
-
#{
|
242
|
+
#{quote_column_name(sort)} DESC
|
241
243
|
LIMIT #{limit.to_i}
|
242
244
|
SQL
|
243
245
|
|
@@ -253,7 +255,7 @@ module PgHero
|
|
253
255
|
def historical_query_stats(sort: nil, start_at: nil, end_at: nil, query_hash: nil)
|
254
256
|
if historical_query_stats_enabled?
|
255
257
|
sort ||= "total_minutes"
|
256
|
-
query =
|
258
|
+
query = <<~SQL
|
257
259
|
WITH query_stats AS (
|
258
260
|
SELECT
|
259
261
|
#{supports_query_hash? ? "query_hash" : "md5(query)"} AS query_hash,
|
@@ -286,7 +288,7 @@ module PgHero
|
|
286
288
|
FROM
|
287
289
|
query_stats
|
288
290
|
ORDER BY
|
289
|
-
#{
|
291
|
+
#{quote_column_name(sort)} DESC
|
290
292
|
LIMIT 100
|
291
293
|
SQL
|
292
294
|
|
@@ -329,19 +331,17 @@ module PgHero
|
|
329
331
|
def insert_query_stats(db_id, db_query_stats, now)
|
330
332
|
values =
|
331
333
|
db_query_stats.map do |qs|
|
332
|
-
|
333
|
-
db_id,
|
334
|
-
qs[:query],
|
335
|
-
qs[:total_minutes] * 60 * 1000,
|
336
|
-
qs[:calls],
|
337
|
-
now,
|
338
|
-
supports_query_hash? ? qs[:query_hash] : nil,
|
339
|
-
qs[:user]
|
340
|
-
|
334
|
+
{
|
335
|
+
database: db_id,
|
336
|
+
query: qs[:query],
|
337
|
+
total_time: qs[:total_minutes] * 60 * 1000,
|
338
|
+
calls: qs[:calls],
|
339
|
+
captured_at: now,
|
340
|
+
query_hash: supports_query_hash? ? qs[:query_hash] : nil,
|
341
|
+
user: qs[:user]
|
342
|
+
}
|
341
343
|
end
|
342
|
-
|
343
|
-
columns = %w[database query total_time calls captured_at query_hash user]
|
344
|
-
insert_stats("pghero_query_stats", columns, values)
|
344
|
+
PgHero::QueryStats.insert_all!(values)
|
345
345
|
end
|
346
346
|
end
|
347
347
|
end
|
@@ -18,7 +18,7 @@ module PgHero
|
|
18
18
|
"pg_last_xlog_receive_location() = pg_last_xlog_replay_location()"
|
19
19
|
end
|
20
20
|
|
21
|
-
select_one
|
21
|
+
select_one <<~SQL
|
22
22
|
SELECT
|
23
23
|
CASE
|
24
24
|
WHEN NOT pg_is_in_recovery() OR #{lag_condition} THEN 0
|
@@ -32,7 +32,7 @@ module PgHero
|
|
32
32
|
def replication_slots
|
33
33
|
if server_version_num >= 90400
|
34
34
|
with_feature_support(:replication_slots, []) do
|
35
|
-
select_all
|
35
|
+
select_all <<~SQL
|
36
36
|
SELECT
|
37
37
|
slot_name,
|
38
38
|
database,
|
@@ -7,7 +7,7 @@ module PgHero
|
|
7
7
|
# it's what information_schema.columns uses
|
8
8
|
# also, exclude temporary tables to prevent error
|
9
9
|
# when accessing across sessions
|
10
|
-
sequences = select_all
|
10
|
+
sequences = select_all <<~SQL
|
11
11
|
SELECT
|
12
12
|
n.nspname AS table_schema,
|
13
13
|
c.relname AS table,
|
@@ -84,7 +84,7 @@ module PgHero
|
|
84
84
|
# also adds schema if missing
|
85
85
|
def add_sequence_attributes(sequences)
|
86
86
|
# fetch data
|
87
|
-
sequence_attributes = select_all
|
87
|
+
sequence_attributes = select_all <<~SQL
|
88
88
|
SELECT
|
89
89
|
n.nspname AS schema,
|
90
90
|
c.relname AS sequence,
|
data/lib/pghero/methods/space.rb
CHANGED
@@ -6,7 +6,7 @@ module PgHero
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def relation_sizes
|
9
|
-
select_all_size
|
9
|
+
select_all_size <<~SQL
|
10
10
|
SELECT
|
11
11
|
n.nspname AS schema,
|
12
12
|
c.relname AS relation,
|
@@ -27,7 +27,7 @@ module PgHero
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def table_sizes
|
30
|
-
select_all_size
|
30
|
+
select_all_size <<~SQL
|
31
31
|
SELECT
|
32
32
|
n.nspname AS schema,
|
33
33
|
c.relname AS table,
|
@@ -52,7 +52,7 @@ module PgHero
|
|
52
52
|
sizes = relation_sizes.to_h { |r| [[r[:schema], r[:relation]], r[:size_bytes]] }
|
53
53
|
start_at = days.days.ago
|
54
54
|
|
55
|
-
stats = select_all_stats
|
55
|
+
stats = select_all_stats <<~SQL
|
56
56
|
WITH t AS (
|
57
57
|
SELECT
|
58
58
|
schema,
|
@@ -95,7 +95,7 @@ module PgHero
|
|
95
95
|
sizes = relation_sizes.map { |r| [[r[:schema], r[:relation]], r[:size_bytes]] }.to_h
|
96
96
|
start_at = 30.days.ago
|
97
97
|
|
98
|
-
stats = select_all_stats
|
98
|
+
stats = select_all_stats <<~SQL
|
99
99
|
SELECT
|
100
100
|
captured_at,
|
101
101
|
size AS size_bytes
|
@@ -121,16 +121,22 @@ module PgHero
|
|
121
121
|
|
122
122
|
def capture_space_stats
|
123
123
|
now = Time.now
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
124
|
+
values =
|
125
|
+
relation_sizes.map do |rs|
|
126
|
+
{
|
127
|
+
database: id,
|
128
|
+
schema: rs[:schema],
|
129
|
+
relation: rs[:relation],
|
130
|
+
size: rs[:size_bytes].to_i,
|
131
|
+
captured_at: now
|
132
|
+
}
|
133
|
+
end
|
134
|
+
PgHero::SpaceStats.insert_all!(values) if values.any?
|
130
135
|
end
|
131
136
|
|
132
|
-
def clean_space_stats
|
133
|
-
|
137
|
+
def clean_space_stats(before: nil)
|
138
|
+
before ||= 90.days.ago
|
139
|
+
PgHero::SpaceStats.where(database: id).where("captured_at < ?", before).delete_all
|
134
140
|
end
|
135
141
|
|
136
142
|
def space_stats_enabled?
|
@@ -79,7 +79,7 @@ module PgHero
|
|
79
79
|
suggested_indexes.each do |index|
|
80
80
|
p index
|
81
81
|
if create
|
82
|
-
connection.execute("CREATE INDEX CONCURRENTLY ON #{quote_table_name(index[:table])} (#{index[:columns].map { |c|
|
82
|
+
connection.execute("CREATE INDEX CONCURRENTLY ON #{quote_table_name(index[:table])} (#{index[:columns].map { |c| quote_column_name(c) }.join(",")})")
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
@@ -194,6 +194,7 @@ module PgHero
|
|
194
194
|
end
|
195
195
|
|
196
196
|
def best_index_structure(statement)
|
197
|
+
return {error: "Empty statement"} if statement.to_s.empty?
|
197
198
|
return {error: "Too large"} if statement.to_s.length > 10000
|
198
199
|
|
199
200
|
begin
|
@@ -286,27 +287,31 @@ module PgHero
|
|
286
287
|
else
|
287
288
|
raise "Not Implemented"
|
288
289
|
end
|
289
|
-
elsif aexpr && ["=", "<>", ">", ">=", "<", "<=", "~~", "~~*", "BETWEEN"].include?(aexpr.name.first.string.
|
290
|
-
[{column: aexpr.lexpr.column_ref.fields.last.string.
|
290
|
+
elsif aexpr && ["=", "<>", ">", ">=", "<", "<=", "~~", "~~*", "BETWEEN"].include?(aexpr.name.first.string.send(str_method))
|
291
|
+
[{column: aexpr.lexpr.column_ref.fields.last.string.send(str_method), op: aexpr.name.first.string.send(str_method)}]
|
291
292
|
elsif tree.null_test
|
292
293
|
op = tree.null_test.nulltesttype == :IS_NOT_NULL ? "not_null" : "null"
|
293
|
-
[{column: tree.null_test.arg.column_ref.fields.last.string.
|
294
|
+
[{column: tree.null_test.arg.column_ref.fields.last.string.send(str_method), op: op}]
|
294
295
|
else
|
295
296
|
raise "Not Implemented"
|
296
297
|
end
|
297
298
|
end
|
298
299
|
|
300
|
+
def str_method
|
301
|
+
@str_method ||= Gem::Version.new(PgQuery::VERSION) >= Gem::Version.new("4") ? :sval : :str
|
302
|
+
end
|
303
|
+
|
299
304
|
def parse_sort(sort_clause)
|
300
305
|
sort_clause.map do |v|
|
301
306
|
{
|
302
|
-
column: v.sort_by.node.column_ref.fields.last.string.
|
307
|
+
column: v.sort_by.node.column_ref.fields.last.string.send(str_method),
|
303
308
|
direction: v.sort_by.sortby_dir == :SORTBY_DESC ? "desc" : "asc"
|
304
309
|
}
|
305
310
|
end
|
306
311
|
end
|
307
312
|
|
308
313
|
def column_stats(schema: nil, table: nil)
|
309
|
-
select_all
|
314
|
+
select_all <<~SQL
|
310
315
|
SELECT
|
311
316
|
schemaname AS schema,
|
312
317
|
tablename AS table,
|
@@ -102,7 +102,8 @@ module PgHero
|
|
102
102
|
end
|
103
103
|
|
104
104
|
client = Azure::Monitor::Profiles::Latest::Mgmt::Client.new
|
105
|
-
|
105
|
+
# call utc to convert +00:00 to Z
|
106
|
+
timespan = "#{start_time.utc.iso8601}/#{end_time.utc.iso8601}"
|
106
107
|
results = client.metrics.list(
|
107
108
|
azure_resource_id,
|
108
109
|
metricnames: metric_name,
|
@@ -269,12 +270,13 @@ module PgHero
|
|
269
270
|
used = azure_stats("storage_used", **options)
|
270
271
|
free_space(quota, used)
|
271
272
|
else
|
272
|
-
|
273
|
-
# could add io_consumption_percent
|
273
|
+
replication_lag_stat = azure_flexible_server? ? "physical_replication_delay_in_seconds" : "pg_replica_log_delay_in_seconds"
|
274
274
|
metrics = {
|
275
275
|
cpu: "cpu_percent",
|
276
276
|
connections: "active_connections",
|
277
|
-
replication_lag:
|
277
|
+
replication_lag: replication_lag_stat,
|
278
|
+
read_iops: "read_iops", # flexible server only
|
279
|
+
write_iops: "write_iops" # flexible server only
|
278
280
|
}
|
279
281
|
raise Error, "Metric not supported" unless metrics[metric_key]
|
280
282
|
azure_stats(metrics[metric_key], **options)
|
@@ -284,6 +286,10 @@ module PgHero
|
|
284
286
|
end
|
285
287
|
end
|
286
288
|
|
289
|
+
def azure_flexible_server?
|
290
|
+
azure_resource_id.include?("/Microsoft.DBforPostgreSQL/flexibleServers/")
|
291
|
+
end
|
292
|
+
|
287
293
|
# only use data points included in both series
|
288
294
|
# this also eliminates need to align Time.now
|
289
295
|
def free_space(quota, used)
|
@@ -2,17 +2,16 @@ module PgHero
|
|
2
2
|
module Methods
|
3
3
|
module Tables
|
4
4
|
def table_hit_rate
|
5
|
-
select_one
|
5
|
+
select_one <<~SQL
|
6
6
|
SELECT
|
7
7
|
sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read), 0) AS rate
|
8
8
|
FROM
|
9
9
|
pg_statio_user_tables
|
10
10
|
SQL
|
11
|
-
)
|
12
11
|
end
|
13
12
|
|
14
13
|
def table_caching
|
15
|
-
select_all
|
14
|
+
select_all <<~SQL
|
16
15
|
SELECT
|
17
16
|
schemaname AS schema,
|
18
17
|
relname AS table,
|
@@ -29,7 +28,7 @@ module PgHero
|
|
29
28
|
end
|
30
29
|
|
31
30
|
def unused_tables
|
32
|
-
select_all
|
31
|
+
select_all <<~SQL
|
33
32
|
SELECT
|
34
33
|
schemaname AS schema,
|
35
34
|
relname AS table,
|
@@ -45,7 +44,7 @@ module PgHero
|
|
45
44
|
end
|
46
45
|
|
47
46
|
def table_stats(schema: nil, table: nil)
|
48
|
-
select_all
|
47
|
+
select_all <<~SQL
|
49
48
|
SELECT
|
50
49
|
nspname AS schema,
|
51
50
|
relname AS table,
|
data/lib/pghero/version.rb
CHANGED
data/lib/pghero.rb
CHANGED
@@ -1,29 +1,31 @@
|
|
1
1
|
# dependencies
|
2
2
|
require "active_support"
|
3
|
+
|
4
|
+
# stdlib
|
3
5
|
require "forwardable"
|
4
6
|
|
5
7
|
# methods
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
8
|
+
require_relative "pghero/methods/basic"
|
9
|
+
require_relative "pghero/methods/connections"
|
10
|
+
require_relative "pghero/methods/constraints"
|
11
|
+
require_relative "pghero/methods/explain"
|
12
|
+
require_relative "pghero/methods/indexes"
|
13
|
+
require_relative "pghero/methods/kill"
|
14
|
+
require_relative "pghero/methods/maintenance"
|
15
|
+
require_relative "pghero/methods/queries"
|
16
|
+
require_relative "pghero/methods/query_stats"
|
17
|
+
require_relative "pghero/methods/replication"
|
18
|
+
require_relative "pghero/methods/sequences"
|
19
|
+
require_relative "pghero/methods/settings"
|
20
|
+
require_relative "pghero/methods/space"
|
21
|
+
require_relative "pghero/methods/suggested_indexes"
|
22
|
+
require_relative "pghero/methods/system"
|
23
|
+
require_relative "pghero/methods/tables"
|
24
|
+
require_relative "pghero/methods/users"
|
25
|
+
|
26
|
+
require_relative "pghero/database"
|
27
|
+
require_relative "pghero/engine" if defined?(Rails)
|
28
|
+
require_relative "pghero/version"
|
27
29
|
|
28
30
|
module PgHero
|
29
31
|
autoload :Connection, "pghero/connection"
|
@@ -119,7 +121,7 @@ module PgHero
|
|
119
121
|
|
120
122
|
config_file_exists = File.exist?(path)
|
121
123
|
|
122
|
-
config = YAML.
|
124
|
+
config = YAML.safe_load(ERB.new(File.read(path)).result) if config_file_exists
|
123
125
|
config ||= {}
|
124
126
|
|
125
127
|
@file_config =
|
@@ -222,15 +224,15 @@ module PgHero
|
|
222
224
|
# delete previous stats
|
223
225
|
# go database by database to use an index
|
224
226
|
# stats for old databases are not cleaned up since we can't use an index
|
225
|
-
def clean_query_stats
|
227
|
+
def clean_query_stats(before: nil)
|
226
228
|
each_database do |database|
|
227
|
-
database.clean_query_stats
|
229
|
+
database.clean_query_stats(before: before)
|
228
230
|
end
|
229
231
|
end
|
230
232
|
|
231
|
-
def clean_space_stats
|
233
|
+
def clean_space_stats(before: nil)
|
232
234
|
each_database do |database|
|
233
|
-
database.clean_space_stats
|
235
|
+
database.clean_space_stats(before: before)
|
234
236
|
end
|
235
237
|
end
|
236
238
|
|
data/lib/tasks/pghero.rake
CHANGED
@@ -22,6 +22,16 @@ namespace :pghero do
|
|
22
22
|
desc "Remove old query stats"
|
23
23
|
task clean_query_stats: :environment do
|
24
24
|
puts "Deleting old query stats..."
|
25
|
-
|
25
|
+
options = {}
|
26
|
+
options[:before] = Float(ENV["KEEP_DAYS"]).days.ago if ENV["KEEP_DAYS"].present?
|
27
|
+
PgHero.clean_query_stats(**options)
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Remove old space stats"
|
31
|
+
task clean_space_stats: :environment do
|
32
|
+
puts "Deleting old space stats..."
|
33
|
+
options = {}
|
34
|
+
options[:before] = Float(ENV["KEEP_DAYS"]).days.ago if ENV["KEEP_DAYS"].present?
|
35
|
+
PgHero.clean_space_stats(**options)
|
26
36
|
end
|
27
37
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2014-
|
3
|
+
Copyright (c) 2014-2022 Chart.js Contributors
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
6
|
|
@@ -1,20 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
The
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2021 Sasha Koss and Lesha Koss https://kossnocorp.mit-license.org
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,9 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018-2021 Jukka Kurkela
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
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: 3.
|
4
|
+
version: 3.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -38,7 +38,7 @@ files:
|
|
38
38
|
- app/assets/javascripts/pghero/Chart.bundle.js
|
39
39
|
- app/assets/javascripts/pghero/application.js
|
40
40
|
- app/assets/javascripts/pghero/chartkick.js
|
41
|
-
- app/assets/javascripts/pghero/highlight.
|
41
|
+
- app/assets/javascripts/pghero/highlight.min.js
|
42
42
|
- app/assets/javascripts/pghero/jquery.js
|
43
43
|
- app/assets/javascripts/pghero/nouislider.js
|
44
44
|
- app/assets/stylesheets/pghero/application.css
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- licenses/LICENSE-date-fns.txt
|
104
104
|
- licenses/LICENSE-highlight.js.txt
|
105
105
|
- licenses/LICENSE-jquery.txt
|
106
|
+
- licenses/LICENSE-kurkle-color.txt
|
106
107
|
- licenses/LICENSE-nouislider.txt
|
107
108
|
homepage: https://github.com/ankane/pghero
|
108
109
|
licenses:
|
@@ -123,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
124
|
- !ruby/object:Gem::Version
|
124
125
|
version: '0'
|
125
126
|
requirements: []
|
126
|
-
rubygems_version: 3.4.
|
127
|
+
rubygems_version: 3.4.10
|
127
128
|
signing_key:
|
128
129
|
specification_version: 4
|
129
130
|
summary: A performance dashboard for Postgres
|