pghero 2.2.1 → 2.7.0
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/CHANGELOG.md +100 -53
- data/README.md +20 -8
- data/app/assets/javascripts/pghero/Chart.bundle.js +16260 -15580
- data/app/assets/javascripts/pghero/application.js +8 -7
- data/app/assets/javascripts/pghero/chartkick.js +1973 -1325
- data/app/assets/javascripts/pghero/highlight.pack.js +2 -2
- data/app/assets/javascripts/pghero/jquery.js +3605 -4015
- data/app/assets/javascripts/pghero/nouislider.js +2479 -0
- data/app/assets/stylesheets/pghero/application.css +1 -1
- data/app/assets/stylesheets/pghero/nouislider.css +299 -0
- data/app/controllers/pg_hero/home_controller.rb +97 -42
- data/app/helpers/pg_hero/home_helper.rb +11 -0
- data/app/views/pg_hero/home/_live_queries_table.html.erb +14 -3
- data/app/views/pg_hero/home/connections.html.erb +9 -0
- data/app/views/pg_hero/home/index.html.erb +49 -10
- data/app/views/pg_hero/home/live_queries.html.erb +1 -1
- data/app/views/pg_hero/home/maintenance.html.erb +16 -2
- data/app/views/pg_hero/home/relation_space.html.erb +2 -2
- data/app/views/pg_hero/home/show_query.html.erb +4 -5
- data/app/views/pg_hero/home/space.html.erb +3 -3
- data/app/views/pg_hero/home/system.html.erb +4 -4
- data/app/views/pg_hero/home/tune.html.erb +2 -1
- data/lib/generators/pghero/config_generator.rb +1 -1
- data/lib/generators/pghero/query_stats_generator.rb +3 -20
- data/lib/generators/pghero/space_stats_generator.rb +3 -20
- data/lib/generators/pghero/templates/config.yml.tt +21 -1
- data/lib/pghero.rb +82 -17
- data/lib/pghero/database.rb +104 -19
- data/lib/pghero/methods/basic.rb +34 -25
- data/lib/pghero/methods/connections.rb +35 -0
- data/lib/pghero/methods/constraints.rb +30 -0
- data/lib/pghero/methods/explain.rb +1 -1
- data/lib/pghero/methods/indexes.rb +1 -1
- data/lib/pghero/methods/maintenance.rb +3 -1
- data/lib/pghero/methods/queries.rb +7 -3
- data/lib/pghero/methods/query_stats.rb +93 -25
- data/lib/pghero/methods/sequences.rb +1 -1
- data/lib/pghero/methods/space.rb +4 -0
- data/lib/pghero/methods/suggested_indexes.rb +1 -1
- data/lib/pghero/methods/system.rb +219 -23
- data/lib/pghero/methods/users.rb +4 -0
- data/lib/pghero/query_stats.rb +1 -3
- data/lib/pghero/space_stats.rb +5 -0
- data/lib/pghero/stats.rb +6 -0
- data/lib/pghero/version.rb +1 -1
- data/lib/tasks/pghero.rake +10 -4
- metadata +15 -12
- data/app/assets/javascripts/pghero/jquery.nouislider.min.js +0 -31
- data/app/assets/stylesheets/pghero/jquery.nouislider.css +0 -165
@@ -15,5 +15,16 @@ module PgHero
|
|
15
15
|
def pghero_js_var(name, value)
|
16
16
|
"var #{name} = #{json_escape(value.to_json(root: false))};".html_safe
|
17
17
|
end
|
18
|
+
|
19
|
+
def pghero_remove_index(query)
|
20
|
+
if query[:columns]
|
21
|
+
columns = query[:columns].map(&:to_sym)
|
22
|
+
columns = columns.first if columns.size == 1
|
23
|
+
end
|
24
|
+
ret = String.new("remove_index #{query[:table].to_sym.inspect}")
|
25
|
+
ret << ", name: #{(query[:name] || query[:index]).to_s.inspect}"
|
26
|
+
ret << ", column: #{columns.inspect}" if columns
|
27
|
+
ret
|
28
|
+
end
|
18
29
|
end
|
19
30
|
end
|
@@ -11,7 +11,17 @@
|
|
11
11
|
<% queries.reverse.each do |query| %>
|
12
12
|
<tr>
|
13
13
|
<td><%= query[:pid] %></td>
|
14
|
-
<td
|
14
|
+
<td>
|
15
|
+
<% sec = query[:duration_ms] / 1000.0 %>
|
16
|
+
<% if sec < 1.minute %>
|
17
|
+
<%= sec.round(1) %> s
|
18
|
+
<% elsif sec < 1.day %>
|
19
|
+
<%= Time.at(sec).utc.strftime("%H:%M:%S") %>
|
20
|
+
<% else %>
|
21
|
+
<% days = (sec / 1.day).floor %>
|
22
|
+
<%= days %>d <%= Time.at(sec - days.days).utc.strftime("%H:%M:%S") %>
|
23
|
+
<% end %>
|
24
|
+
</td>
|
15
25
|
<td>
|
16
26
|
<%= query[:state] %>
|
17
27
|
<% if vacuum_progress[query[:pid]] %>
|
@@ -20,8 +30,9 @@
|
|
20
30
|
<% end %>
|
21
31
|
</td>
|
22
32
|
<td class="text-right">
|
23
|
-
<%
|
24
|
-
|
33
|
+
<% unless @database.filter_data %>
|
34
|
+
<%= button_to "Explain", explain_path, params: {query: query[:query]}, form: {target: "_blank"}, class: "btn btn-info" %>
|
35
|
+
<% end %>
|
25
36
|
<%= button_to "Kill", kill_path(pid: query[:pid]), class: "btn btn-danger" %>
|
26
37
|
</td>
|
27
38
|
</tr>
|
@@ -18,6 +18,15 @@
|
|
18
18
|
new Chartkick.PieChart("chart-2", <%= json_escape(@connections_by_user.to_json).html_safe %>);
|
19
19
|
</script>
|
20
20
|
|
21
|
+
<% if @connections_by_ssl_status %>
|
22
|
+
<h3>By Security</h3>
|
23
|
+
|
24
|
+
<div id="chart-3" class="chart" style="height: 260px; line-height: 260px; margin-bottom: 20px;">Loading...</div>
|
25
|
+
<script>
|
26
|
+
new Chartkick.PieChart("chart-3", <%= json_escape(@connections_by_ssl_status.to_json).html_safe %>);
|
27
|
+
</script>
|
28
|
+
<% end %>
|
29
|
+
|
21
30
|
<%= render partial: "connections_table", locals: {connection_sources: @connection_sources} %>
|
22
31
|
<% end %>
|
23
32
|
</div>
|
@@ -62,11 +62,17 @@
|
|
62
62
|
(<%= link_to pluralize(@unreadable_sequences.size, "unreadable sequence", "unreadable sequences"), {unreadable: "t"} %>)
|
63
63
|
<% end %>
|
64
64
|
</div>
|
65
|
-
<div class="alert alert-<%= @invalid_indexes.empty? ? "success" : "warning" %>">
|
66
|
-
<% if @invalid_indexes.
|
67
|
-
|
65
|
+
<div class="alert alert-<%= @invalid_indexes.empty? && @invalid_constraints.empty? ? "success" : "warning" %>">
|
66
|
+
<% if @invalid_indexes.empty? && @invalid_constraints.empty? %>
|
67
|
+
No invalid indexes or constraints
|
68
68
|
<% else %>
|
69
|
-
|
69
|
+
<% if @invalid_indexes.any? %>
|
70
|
+
<%= pluralize(@invalid_indexes.size, "invalid index", "invalid indexes") %>
|
71
|
+
<% end %>
|
72
|
+
<% if @invalid_constraints.any? %>
|
73
|
+
<% if @invalid_indexes.any? %>and<% end %>
|
74
|
+
<%= pluralize(@invalid_constraints.size, "invalid constraint", "invalid constraints") %>
|
75
|
+
<% end %>
|
70
76
|
<% end %>
|
71
77
|
</div>
|
72
78
|
<% if @duplicate_indexes %>
|
@@ -332,6 +338,39 @@
|
|
332
338
|
</div>
|
333
339
|
<% end %>
|
334
340
|
|
341
|
+
<% if @invalid_constraints.any? %>
|
342
|
+
<div class="content">
|
343
|
+
<h1>Invalid Constraints</h1>
|
344
|
+
|
345
|
+
<p>These constraints are marked as <code>NOT VALID</code>. You should validate them.</p>
|
346
|
+
|
347
|
+
<table class="table">
|
348
|
+
<thead>
|
349
|
+
<tr>
|
350
|
+
<th>Name</th>
|
351
|
+
</tr>
|
352
|
+
</thead>
|
353
|
+
<tbody>
|
354
|
+
<% @invalid_constraints.each do |constraint| %>
|
355
|
+
<tr>
|
356
|
+
<td>
|
357
|
+
<%= constraint[:name] %>
|
358
|
+
<% if constraint[:schema] != "public" %>
|
359
|
+
<span class="text-muted"><%= constraint[:schema] %></span>
|
360
|
+
<% end %>
|
361
|
+
</td>
|
362
|
+
</tr>
|
363
|
+
<tr>
|
364
|
+
<td style="border-top: none; padding: 0;">
|
365
|
+
<pre><code>ALTER TABLE <%= pghero_pretty_ident(constraint[:table], schema: constraint[:schema]) %> VALIDATE CONSTRAINT <%= pghero_pretty_ident(constraint[:name]) %>;</code></pre>
|
366
|
+
</td>
|
367
|
+
</tr>
|
368
|
+
<% end %>
|
369
|
+
</tbody>
|
370
|
+
</table>
|
371
|
+
</div>
|
372
|
+
<% end %>
|
373
|
+
|
335
374
|
<% if @duplicate_indexes && @duplicate_indexes.any? %>
|
336
375
|
<div class="content">
|
337
376
|
<h1>Duplicate Indexes</h1>
|
@@ -345,10 +384,10 @@
|
|
345
384
|
</p>
|
346
385
|
|
347
386
|
<div id="migration2" style="display: none;">
|
348
|
-
<pre>rails
|
387
|
+
<pre>rails generate migration remove_unneeded_indexes</pre>
|
349
388
|
<p>And paste</p>
|
350
389
|
<pre style="overflow: scroll; white-space: pre; word-break: normal;"><% @duplicate_indexes.each do |query| %>
|
351
|
-
|
390
|
+
<%= pghero_remove_index(query[:unneeded_index]) %><% end %></pre>
|
352
391
|
</div>
|
353
392
|
|
354
393
|
<table class="table duplicate-indexes">
|
@@ -387,12 +426,12 @@ remove_index <%= query[:unneeded_index][:table].to_sym.inspect %>, name: <%= que
|
|
387
426
|
</p>
|
388
427
|
|
389
428
|
<div id="migration3" style="display: none;">
|
390
|
-
<pre>rails
|
429
|
+
<pre>rails generate migration add_suggested_indexes</pre>
|
391
430
|
<p>And paste</p>
|
392
431
|
<pre style="overflow: scroll; white-space: pre; word-break: normal;">commit_db_transaction
|
393
432
|
<% @suggested_indexes.each do |index| %>
|
394
433
|
<% if index[:using] && index[:using] != "btree" %>
|
395
|
-
|
434
|
+
add_index <%= index[:table].to_sym.inspect %>, <%= index[:columns].first.inspect %>, using: <%= index[:using].inspect %>, algorithm: :concurrently
|
396
435
|
<% else %>
|
397
436
|
add_index <%= index[:table].to_sym.inspect %>, [<%= index[:columns].map(&:to_sym).map(&:inspect).join(", ") %>], algorithm: :concurrently<% end %>
|
398
437
|
<% end %></pre>
|
@@ -449,10 +488,10 @@ pg_stat_statements.track = all</pre>
|
|
449
488
|
</p>
|
450
489
|
|
451
490
|
<div id="migration" style="display: none;">
|
452
|
-
<pre>rails
|
491
|
+
<pre>rails generate migration remove_unused_indexes</pre>
|
453
492
|
<p>And paste</p>
|
454
493
|
<pre style="overflow: scroll; white-space: pre; word-break: normal;"><% @unused_indexes.each do |query| %>
|
455
|
-
|
494
|
+
<%= pghero_remove_index(query)%><% end %></pre>
|
456
495
|
</div>
|
457
496
|
|
458
497
|
<table class="table">
|
@@ -7,6 +7,9 @@
|
|
7
7
|
<th>Table</th>
|
8
8
|
<th style="width: 20%;">Last Vacuum</th>
|
9
9
|
<th style="width: 20%;">Last Analyze</th>
|
10
|
+
<% if @show_dead_rows %>
|
11
|
+
<th style="width: 20%;">Dead Rows</th>
|
12
|
+
<% end %>
|
10
13
|
</tr>
|
11
14
|
</thead>
|
12
15
|
<tbody>
|
@@ -21,7 +24,7 @@
|
|
21
24
|
<td>
|
22
25
|
<% time = [table[:last_autovacuum], table[:last_vacuum]].compact.max %>
|
23
26
|
<% if time %>
|
24
|
-
<%= time.in_time_zone(@time_zone)
|
27
|
+
<%= l time.in_time_zone(@time_zone), format: :short %>
|
25
28
|
<% else %>
|
26
29
|
<span class="text-muted">Unknown</span>
|
27
30
|
<% end %>
|
@@ -29,11 +32,22 @@
|
|
29
32
|
<td>
|
30
33
|
<% time = [table[:last_autoanalyze], table[:last_analyze]].compact.max %>
|
31
34
|
<% if time %>
|
32
|
-
<%= time.in_time_zone(@time_zone)
|
35
|
+
<%= l time.in_time_zone(@time_zone), format: :short %>
|
33
36
|
<% else %>
|
34
37
|
<span class="text-muted">Unknown</span>
|
35
38
|
<% end %>
|
36
39
|
</td>
|
40
|
+
<% if @show_dead_rows %>
|
41
|
+
<td>
|
42
|
+
<% if table[:live_rows] != 0 %>
|
43
|
+
<%# use live rows only for denominator to make it easier to compare with autovacuum_vacuum_scale_factor %>
|
44
|
+
<%# it's not a true percentage, since it can go above 100% %>
|
45
|
+
<%= (100.0 * table[:dead_rows] / table[:live_rows]).round %>%
|
46
|
+
<% else %>
|
47
|
+
<span class="text-muted">Unknown</span>
|
48
|
+
<% end %>
|
49
|
+
</td>
|
50
|
+
<% end %>
|
37
51
|
</tr>
|
38
52
|
<% end %>
|
39
53
|
</tbody>
|
@@ -6,9 +6,9 @@
|
|
6
6
|
<% end %>
|
7
7
|
</h1>
|
8
8
|
|
9
|
-
<h1>Size
|
9
|
+
<h1>Size</h1>
|
10
10
|
<div id="chart-1" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
11
11
|
<script>
|
12
|
-
new Chartkick.LineChart("chart-1", <%= json_escape(@chart_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, min: null})
|
12
|
+
new Chartkick.LineChart("chart-1", <%= json_escape(@chart_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, min: null, bytes: true, library: {tooltips: {intersect: false, mode: "index"}}})
|
13
13
|
</script>
|
14
14
|
</div>
|
@@ -6,8 +6,7 @@
|
|
6
6
|
|
7
7
|
<% if @explainable_query %>
|
8
8
|
<p>
|
9
|
-
|
10
|
-
<%= button_to "Explain", button_path, button_options.merge(form: {target: "_blank"}, class: "btn btn-info") %>
|
9
|
+
<%= button_to "Explain", explain_path, params: {query: @explainable_query}, form: {target: "_blank"}, class: "btn btn-info" %>
|
11
10
|
</p>
|
12
11
|
<% end %>
|
13
12
|
|
@@ -50,19 +49,19 @@
|
|
50
49
|
<h1>Total Time <small>ms</small></h1>
|
51
50
|
<div id="chart-1" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
52
51
|
<script>
|
53
|
-
new Chartkick.LineChart("chart-1", <%= json_escape(@chart_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false})
|
52
|
+
new Chartkick.LineChart("chart-1", <%= json_escape(@chart_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, library: {tooltips: {intersect: false, mode: "index"}}})
|
54
53
|
</script>
|
55
54
|
|
56
55
|
<h1>Average Time <small>ms</small></h1>
|
57
56
|
<div id="chart-2" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
58
57
|
<script>
|
59
|
-
new Chartkick.LineChart("chart-2", <%= json_escape(@chart2_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false})
|
58
|
+
new Chartkick.LineChart("chart-2", <%= json_escape(@chart2_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, library: {tooltips: {intersect: false, mode: "index"}}})
|
60
59
|
</script>
|
61
60
|
|
62
61
|
<h1>Calls</h1>
|
63
62
|
<div id="chart-3" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
64
63
|
<script>
|
65
|
-
new Chartkick.LineChart("chart-3", <%= json_escape(@chart3_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false})
|
64
|
+
new Chartkick.LineChart("chart-3", <%= json_escape(@chart3_data.to_json).html_safe %>, {colors: ["#5bc0de"], legend: false, library: {tooltips: {intersect: false, mode: "index"}}})
|
66
65
|
</script>
|
67
66
|
<% else %>
|
68
67
|
<p>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<% if @system_stats_enabled %>
|
7
7
|
<div id="chart-1" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
8
8
|
<script>
|
9
|
-
new Chartkick.LineChart("chart-1", <%= json_escape(free_space_stats_path.to_json).html_safe %>, {colors: ["#5bc0de"]})
|
9
|
+
new Chartkick.LineChart("chart-1", <%= json_escape(free_space_stats_path.to_json).html_safe %>, {colors: ["#5bc0de"], bytes: true, library: {tooltips: {intersect: false, mode: "index"}}})
|
10
10
|
</script>
|
11
11
|
<% end %>
|
12
12
|
|
@@ -30,10 +30,10 @@
|
|
30
30
|
</p>
|
31
31
|
|
32
32
|
<div id="migration" style="display: none;">
|
33
|
-
<pre>rails
|
33
|
+
<pre>rails generate migration remove_unused_indexes</pre>
|
34
34
|
<p>And paste</p>
|
35
35
|
<pre style="overflow: scroll; white-space: pre; word-break: normal;"><% @unused_indexes.sort_by { |q| [-q[:size_bytes], q[:index]] }.each do |query| %>
|
36
|
-
|
36
|
+
<%= pghero_remove_index(query) %><% end %></pre>
|
37
37
|
</div>
|
38
38
|
<% end %>
|
39
39
|
|
@@ -9,26 +9,26 @@
|
|
9
9
|
<h1>CPU</h1>
|
10
10
|
<div id="chart-1" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
11
11
|
<script>
|
12
|
-
new Chartkick.LineChart("chart-1", <%= json_escape(cpu_usage_path(path_options).to_json).html_safe %>, {max: 100, colors: ["#5bc0de"]})
|
12
|
+
new Chartkick.LineChart("chart-1", <%= json_escape(cpu_usage_path(path_options).to_json).html_safe %>, {max: 100, colors: ["#5bc0de"], suffix: "%", library: {tooltips: {intersect: false, mode: "index"}}})
|
13
13
|
</script>
|
14
14
|
|
15
15
|
<h1>Load</h1>
|
16
16
|
<div id="chart-2" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
17
17
|
<script>
|
18
|
-
new Chartkick.LineChart("chart-2", <%= json_escape(load_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de", "#d9534f"]})
|
18
|
+
new Chartkick.LineChart("chart-2", <%= json_escape(load_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de", "#d9534f"], library: {tooltips: {intersect: false, mode: "nearest"}}})
|
19
19
|
</script>
|
20
20
|
|
21
21
|
<h1>Connections</h1>
|
22
22
|
<div id="chart-3" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
23
23
|
<script>
|
24
|
-
new Chartkick.LineChart("chart-3", <%= json_escape(connection_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de"]})
|
24
|
+
new Chartkick.LineChart("chart-3", <%= json_escape(connection_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de"], library: {tooltips: {intersect: false, mode: "index"}}})
|
25
25
|
</script>
|
26
26
|
|
27
27
|
<% if @database.replica? %>
|
28
28
|
<h1>Replication Lag</h1>
|
29
29
|
<div id="chart-4" class="chart" style="margin-bottom: 20px;">Loading...</div>
|
30
30
|
<script>
|
31
|
-
new Chartkick.LineChart("chart-4", <%= json_escape(replication_lag_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de"]})
|
31
|
+
new Chartkick.LineChart("chart-4", <%= json_escape(replication_lag_stats_path(path_options).to_json).html_safe %>, {colors: ["#5bc0de"], library: {tooltips: {intersect: false, mode: "index"}}})
|
32
32
|
</script>
|
33
33
|
<% end %>
|
34
34
|
</div>
|
@@ -18,7 +18,8 @@
|
|
18
18
|
</tbody>
|
19
19
|
</table>
|
20
20
|
|
21
|
-
|
21
|
+
<% version_parts = @database.server_version.split(" ").first.split(".") %>
|
22
|
+
<p>Check out <%= link_to "PgTune", "https://pgtune.leopard.in.ua/", target: "_blank" %> for recommendations. DB version is <%= version_parts[0].to_i >= 10 ? version_parts[0] : version_parts.first(2).join(".") %>.</p>
|
22
23
|
</div>
|
23
24
|
|
24
25
|
<% if @autovacuum_settings %>
|
@@ -3,7 +3,7 @@ require "rails/generators"
|
|
3
3
|
module Pghero
|
4
4
|
module Generators
|
5
5
|
class ConfigGenerator < Rails::Generators::Base
|
6
|
-
source_root File.
|
6
|
+
source_root File.join(__dir__, "templates")
|
7
7
|
|
8
8
|
def create_initializer
|
9
9
|
template "config.yml", "config/pghero.yml"
|
@@ -1,34 +1,17 @@
|
|
1
|
-
# taken from https://github.com/collectiveidea/audited/blob/master/lib/generators/audited/install_generator.rb
|
2
|
-
require "rails/generators"
|
3
|
-
require "rails/generators/migration"
|
4
|
-
require "active_record"
|
5
1
|
require "rails/generators/active_record"
|
6
2
|
|
7
3
|
module Pghero
|
8
4
|
module Generators
|
9
5
|
class QueryStatsGenerator < Rails::Generators::Base
|
10
|
-
include
|
11
|
-
|
12
|
-
source_root File.expand_path("../templates", __FILE__)
|
13
|
-
|
14
|
-
# Implement the required interface for Rails::Generators::Migration.
|
15
|
-
def self.next_migration_number(dirname) #:nodoc:
|
16
|
-
next_migration_number = current_migration_number(dirname) + 1
|
17
|
-
if ::ActiveRecord::Base.timestamped_migrations
|
18
|
-
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
19
|
-
else
|
20
|
-
"%.3d" % next_migration_number
|
21
|
-
end
|
22
|
-
end
|
6
|
+
include ActiveRecord::Generators::Migration
|
7
|
+
source_root File.join(__dir__, "templates")
|
23
8
|
|
24
9
|
def copy_migration
|
25
10
|
migration_template "query_stats.rb", "db/migrate/create_pghero_query_stats.rb", migration_version: migration_version
|
26
11
|
end
|
27
12
|
|
28
13
|
def migration_version
|
29
|
-
|
30
|
-
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
31
|
-
end
|
14
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
32
15
|
end
|
33
16
|
end
|
34
17
|
end
|
@@ -1,34 +1,17 @@
|
|
1
|
-
# taken from https://github.com/collectiveidea/audited/blob/master/lib/generators/audited/install_generator.rb
|
2
|
-
require "rails/generators"
|
3
|
-
require "rails/generators/migration"
|
4
|
-
require "active_record"
|
5
1
|
require "rails/generators/active_record"
|
6
2
|
|
7
3
|
module Pghero
|
8
4
|
module Generators
|
9
5
|
class SpaceStatsGenerator < Rails::Generators::Base
|
10
|
-
include
|
11
|
-
|
12
|
-
source_root File.expand_path("../templates", __FILE__)
|
13
|
-
|
14
|
-
# Implement the required interface for Rails::Generators::Migration.
|
15
|
-
def self.next_migration_number(dirname) #:nodoc:
|
16
|
-
next_migration_number = current_migration_number(dirname) + 1
|
17
|
-
if ::ActiveRecord::Base.timestamped_migrations
|
18
|
-
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
19
|
-
else
|
20
|
-
"%.3d" % next_migration_number
|
21
|
-
end
|
22
|
-
end
|
6
|
+
include ActiveRecord::Generators::Migration
|
7
|
+
source_root File.join(__dir__, "templates")
|
23
8
|
|
24
9
|
def copy_migration
|
25
10
|
migration_template "space_stats.rb", "db/migrate/create_pghero_space_stats.rb", migration_version: migration_version
|
26
11
|
end
|
27
12
|
|
28
13
|
def migration_version
|
29
|
-
|
30
|
-
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
31
|
-
end
|
14
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
32
15
|
end
|
33
16
|
end
|
34
17
|
end
|
@@ -1,8 +1,13 @@
|
|
1
1
|
databases:
|
2
|
-
|
2
|
+
primary:
|
3
3
|
# Database URL (defaults to app database)
|
4
4
|
# url: <%%= ENV["DATABASE_URL"] %>
|
5
5
|
|
6
|
+
# System stats
|
7
|
+
# aws_db_instance_identifier: my-instance
|
8
|
+
# gcp_database_id: my-project:my-instance
|
9
|
+
# azure_resource_id: my-resource-id
|
10
|
+
|
6
11
|
# Add more databases
|
7
12
|
# other:
|
8
13
|
# url: <%%= ENV["OTHER_DATABASE_URL"] %>
|
@@ -24,3 +29,18 @@ databases:
|
|
24
29
|
|
25
30
|
# Time zone (defaults to app time zone)
|
26
31
|
# time_zone: "Pacific Time (US & Canada)"
|
32
|
+
|
33
|
+
# Basic authentication
|
34
|
+
# username: admin
|
35
|
+
# password: <%%= ENV["PGHERO_PASSWORD"] %>
|
36
|
+
|
37
|
+
# Stats database URL (defaults to app database)
|
38
|
+
# stats_database_url: <%%= ENV["PGHERO_STATS_DATABASE_URL"] %>
|
39
|
+
|
40
|
+
# AWS configuration (defaults to app AWS config)
|
41
|
+
# aws_access_key_id: <%%= ENV["AWS_ACCESS_KEY_ID"] %>
|
42
|
+
# aws_secret_access_key: <%%= ENV["AWS_SECRET_ACCESS_KEY"] %>
|
43
|
+
# aws_region: us-east-1
|
44
|
+
|
45
|
+
# Filter data from queries (experimental)
|
46
|
+
# filter_data: true
|