pghero 2.4.1 → 2.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1eb28c7ae995ccdc8fcc30dec3c42f3abb1463981b89a85ed9a8b8b53dba4ce
4
- data.tar.gz: 0c0b1e34f2f12c46055a15c937b282048b99036ce6b535ac2445bd83b4d7ac67
3
+ metadata.gz: 33927c2c6b6d2c286f872adb99d7095f836108872c4f9af3ca180d6a70cb0b48
4
+ data.tar.gz: 8f2f7565269047b8a351bd712a931e26febc1b6bd96f21b3c1f81ece50807f8d
5
5
  SHA512:
6
- metadata.gz: fc924cde46b89d3d64649f8df7abbe81538892ba0839c4983ad0e67522c36ee4b0ee52673c3d79977cfac05413c846d821fb25d885ba33693e2d01c6de042f8b
7
- data.tar.gz: 790d0cc392a123ac30ae59868a80eb1239adbcf091a53c0edd9cbabb6426f0e86d11d25ac8fbc0c85619c90f766c46a67a49e439467b8c47f960482e8d04c10d
6
+ metadata.gz: 76dd17666d9842cad4a540c519df850cf784d97eeccd9792ff853d90a633628b5615459521bc2f5b382e75ffe35b52023e4cf8cfdbabc2924154a6feb7d8c94e
7
+ data.tar.gz: c0c5ba7f1823182241ca7c8365969a5f661f2abca55551832ee3e64d61eabb5432ad7dcb3e2b9f81b972c125d80bf22f5a55e2ef13a471889fe393b1976d1e10
@@ -1,3 +1,8 @@
1
+ ## 2.4.2 (2020-04-16)
2
+
3
+ - Added `connections` method
4
+ - Fixed deprecation warnings in Ruby 2.7
5
+
1
6
  ## 2.4.1 (2019-11-21)
2
7
 
3
8
  - Fixed file permissions on `highlight.pack.js`
data/README.md CHANGED
@@ -10,7 +10,7 @@ A performance dashboard for Postgres
10
10
 
11
11
  ---
12
12
 
13
- [![Screenshot](https://pghero.dokkuapp.com/assets/screenshot-5a368624ada55b32e7668c96926840f9.png)](https://pghero.dokkuapp.com/)
13
+ [![Screenshot](https://pghero.dokkuapp.com/assets/pghero-f8abe426e6bf54bb7dba87b425bb809740ebd386208bcd280a7e802b053a1023.png)](https://pghero.dokkuapp.com/)
14
14
 
15
15
  ## Installation
16
16
 
@@ -270,11 +270,41 @@ module PgHero
270
270
 
271
271
  def connections
272
272
  @title = "Connections"
273
- @connection_sources = @database.connection_sources
274
- @total_connections = @connection_sources.sum { |cs| cs[:total_connections] }
273
+ connections = @database.connections
274
+
275
+ @total_connections = connections.count
276
+ @connection_sources = group_connections(connections, [:database, :user, :source, :ip])
277
+ @connections_by_database = group_connections_by_key(connections, :database)
278
+ @connections_by_user = group_connections_by_key(connections, :user)
279
+
280
+ if params[:security] && @database.server_version_num >= 90500
281
+ connections.each do |connection|
282
+ connection[:ssl_status] =
283
+ if connection[:ssl]
284
+ # no way to tell if client used verify-full
285
+ # so connection may not be actually secure
286
+ "SSL"
287
+ else
288
+ # variety of reasons for no SSL
289
+ if !connection[:database].present?
290
+ "Internal Process"
291
+ elsif !connection[:ip]
292
+ if connection[:state]
293
+ "Socket"
294
+ else
295
+ # tcp or socket, don't have permission to tell
296
+ "No SSL"
297
+ end
298
+ else
299
+ # tcp
300
+ # could separate out localhost since this should be safe
301
+ "No SSL"
302
+ end
303
+ end
304
+ end
275
305
 
276
- @connections_by_database = group_connections(@connection_sources, :database)
277
- @connections_by_user = group_connections(@connection_sources, :user)
306
+ @connections_by_ssl_status = group_connections_by_key(connections, :ssl_status)
307
+ end
278
308
  end
279
309
 
280
310
  def maintenance
@@ -376,12 +406,15 @@ module PgHero
376
406
  @show_details = @historical_query_stats_enabled && @database.supports_query_hash?
377
407
  end
378
408
 
379
- def group_connections(connection_sources, key)
380
- top_connections = Hash.new(0)
381
- connection_sources.each do |source|
382
- top_connections[source[key]] += source[:total_connections]
383
- end
384
- top_connections.sort_by { |k, v| [-v, k] }
409
+ def group_connections(connections, keys)
410
+ connections
411
+ .group_by { |conn| conn.slice(*keys) }
412
+ .map { |k, v| k.merge(total_connections: v.count) }
413
+ .sort_by { |v| [-v[:total_connections]] + keys.map { |k| v[k].to_s } }
414
+ end
415
+
416
+ def group_connections_by_key(connections, key)
417
+ group_connections(connections, [key]).map { |v| [v[key], v[:total_connections]] }.to_h
385
418
  end
386
419
 
387
420
  def check_api
@@ -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
@@ -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>
@@ -387,7 +387,7 @@
387
387
  <pre>rails generate migration remove_unneeded_indexes</pre>
388
388
  <p>And paste</p>
389
389
  <pre style="overflow: scroll; white-space: pre; word-break: normal;"><% @duplicate_indexes.each do |query| %>
390
- remove_index <%= query[:unneeded_index][:table].to_sym.inspect %>, name: <%= query[:unneeded_index][:name].to_s.inspect %><% end %></pre>
390
+ <%= pghero_remove_index(query[:unneeded_index]) %><% end %></pre>
391
391
  </div>
392
392
 
393
393
  <table class="table duplicate-indexes">
@@ -491,7 +491,7 @@ pg_stat_statements.track = all</pre>
491
491
  <pre>rails generate migration remove_unused_indexes</pre>
492
492
  <p>And paste</p>
493
493
  <pre style="overflow: scroll; white-space: pre; word-break: normal;"><% @unused_indexes.each do |query| %>
494
- remove_index <%= query[:table].to_sym.inspect %>, name: <%= query[:index].to_s.inspect %><% end %></pre>
494
+ <%= pghero_remove_index(query)%><% end %></pre>
495
495
  </div>
496
496
 
497
497
  <table class="table">
@@ -33,7 +33,7 @@
33
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
- remove_index <%= query[:table].to_sym.inspect %>, name: <%= query[:index].to_s.inspect %><% end %></pre>
36
+ <%= pghero_remove_index(query) %><% end %></pre>
37
37
  </div>
38
38
  <% end %>
39
39
 
@@ -51,7 +51,7 @@ module PgHero
51
51
  class << self
52
52
  extend Forwardable
53
53
  def_delegators :primary_database, :access_key_id, :analyze, :analyze_tables, :autoindex, :autovacuum_danger,
54
- :best_index, :blocked_queries, :connection_sources, :connection_states, :connection_stats,
54
+ :best_index, :blocked_queries, :connections, :connection_sources, :connection_states, :connection_stats,
55
55
  :cpu_usage, :create_user, :database_size, :db_instance_identifier, :disable_query_stats, :drop_user,
56
56
  :duplicate_indexes, :enable_query_stats, :explain, :historical_query_stats_enabled?, :index_caching,
57
57
  :index_hit_rate, :index_usage, :indexes, :invalid_constraints, :invalid_indexes, :kill, :kill_all, :kill_long_running_queries,
@@ -1,6 +1,41 @@
1
1
  module PgHero
2
2
  module Methods
3
3
  module Connections
4
+ def connections
5
+ if server_version_num >= 90500
6
+ select_all <<-SQL
7
+ SELECT
8
+ pg_stat_activity.pid,
9
+ datname AS database,
10
+ usename AS user,
11
+ application_name AS source,
12
+ client_addr AS ip,
13
+ state,
14
+ ssl
15
+ FROM
16
+ pg_stat_activity
17
+ LEFT JOIN
18
+ pg_stat_ssl ON pg_stat_activity.pid = pg_stat_ssl.pid
19
+ ORDER BY
20
+ pg_stat_activity.pid
21
+ SQL
22
+ else
23
+ select_all <<-SQL
24
+ SELECT
25
+ pid,
26
+ datname AS database,
27
+ usename AS user,
28
+ application_name AS source,
29
+ client_addr AS ip,
30
+ state
31
+ FROM
32
+ pg_stat_activity
33
+ ORDER BY
34
+ pid
35
+ SQL
36
+ end
37
+ end
38
+
4
39
  def total_connections
5
40
  select_one("SELECT COUNT(*) FROM pg_stat_activity")
6
41
  end
@@ -2,7 +2,7 @@ module PgHero
2
2
  module Methods
3
3
  module QueryStats
4
4
  def query_stats(historical: false, start_at: nil, end_at: nil, min_average_time: nil, min_calls: nil, **options)
5
- current_query_stats = historical && end_at && end_at < Time.now ? [] : current_query_stats(options)
5
+ current_query_stats = historical && end_at && end_at < Time.now ? [] : current_query_stats(**options)
6
6
  historical_query_stats = historical && historical_query_stats_enabled? ? historical_query_stats(start_at: start_at, end_at: end_at, **options) : []
7
7
 
8
8
  query_stats = combine_query_stats((current_query_stats + historical_query_stats).group_by { |q| [q[:query_hash], q[:user]] })
@@ -48,7 +48,7 @@ module PgHero
48
48
  def suggested_indexes(suggested_indexes_by_query: nil, **options)
49
49
  indexes = []
50
50
 
51
- (suggested_indexes_by_query || self.suggested_indexes_by_query(options)).select { |_s, i| i[:found] && !i[:covering_index] }.group_by { |_s, i| i[:index] }.each do |index, group|
51
+ (suggested_indexes_by_query || self.suggested_indexes_by_query(**options)).select { |_s, i| i[:found] && !i[:covering_index] }.group_by { |_s, i| i[:index] }.each do |index, group|
52
52
  details = {}
53
53
  group.map(&:second).each do |g|
54
54
  details = details.except(:index).deep_merge(g)
@@ -1,3 +1,3 @@
1
1
  module PgHero
2
- VERSION = "2.4.1"
2
+ VERSION = "2.4.2"
3
3
  end
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: 2.4.1
4
+ version: 2.4.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: 2019-11-21 00:00:00.000000000 Z
11
+ date: 2020-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -200,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
200
  - !ruby/object:Gem::Version
201
201
  version: '0'
202
202
  requirements: []
203
- rubygems_version: 3.0.6
203
+ rubygems_version: 3.1.2
204
204
  signing_key:
205
205
  specification_version: 4
206
206
  summary: A performance dashboard for Postgres