pghero 1.3.0 → 1.3.1

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
  SHA1:
3
- metadata.gz: 5de5f457151a5d2e77e515b117225033f2f5153b
4
- data.tar.gz: fa0a4eea1887464cc49e376aa5675610819f92fb
3
+ metadata.gz: 33902e779edd42795e8f3c48d51a8f0abf4edf6c
4
+ data.tar.gz: b16a37597ad809d2aefe83fd0ff6f6478319c655
5
5
  SHA512:
6
- metadata.gz: af9c72a1eaf428e6c2b7b43a5df732f848633e5f1fa4835c697ff801384fd3b8920d43516a7a5fef9f212b46ee70b9f33ef81e7557fa78b1d086d7e180321aab
7
- data.tar.gz: 2a687404ad19e82ee2bd7517cd7a81837fe9ea469110028f2fe656b82849977ad139c5407b52168678dfd006e547a316ebc886f953e7db034ea8daae99eb79b4
6
+ metadata.gz: 65850829e7cd4071748b03b453f1ee91e0739048001802d5d8ecc290bb0f3e137d7c08bfa2f51cb0bc76ced94087865c6e8d276ed98b5b86c88916fea56e52a6
7
+ data.tar.gz: 1cf67bd24d6e2780b63b44466f8e964ea10be8ef6bfbf4286e636a3b0f7baee16e20ab5e25bf3092ece33095ea22e7688596e7227b19c1093ea1243c41612b1d
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
- rvm: 2.2
2
+ rvm: 2.2.4
3
3
  cache: bundler
4
4
  sudo: false
5
5
  script: TRAVIS_CI=1 bundle exec rake test
@@ -1,3 +1,8 @@
1
+ ## 1.3.1
2
+
3
+ - Improved grouping of query stats
4
+ - Added `blocked_queries` method
5
+
1
6
  ## 1.3.0
2
7
 
3
8
  - Added query hash for better query stats grouping
data/README.md CHANGED
@@ -31,3 +31,5 @@ A big thanks to [Craig Kerstiens](http://www.craigkerstiens.com/2013/01/10/more-
31
31
  Know a bit about PostgreSQL? [Suggestions](https://github.com/ankane/pghero/issues) are greatly appreciated.
32
32
 
33
33
  :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
34
+
35
+ [![Build Status](https://travis-ci.org/ankane/pghero.svg?branch=master)](https://travis-ci.org/ankane/pghero)
@@ -95,6 +95,8 @@ module PgHero
95
95
 
96
96
  set_suggested_indexes
97
97
 
98
+ # fix back button issue with caching
99
+ response.headers["Cache-Control"] = "must-revalidate, no-store, no-cache, private"
98
100
  if request.xhr?
99
101
  render layout: false, partial: "queries_table", locals: {queries: @query_stats, xhr: true}
100
102
  end
@@ -153,7 +153,13 @@
153
153
  $(this).attr("href", queriesPath(p));
154
154
  });
155
155
 
156
- $("#queries").html('<tr><td colspan="3"><p class="queries-info text-muted">...</p></td></tr>').load(path);
156
+
157
+ var callback = function (response, status, xhr) {
158
+ if (status === "error" ) {
159
+ $(".queries-info").css("color", "red").html(xhr.status + " " + xhr.statusText);
160
+ }
161
+ };
162
+ $("#queries").html('<tr><td colspan="3"><p class="queries-info text-muted">...</p></td></tr>').load(path, callback);
157
163
 
158
164
  if (push && history.pushState) {
159
165
  history.pushState(null, null, path);
@@ -158,13 +158,14 @@
158
158
  <% if @sequence_danger.any? %>
159
159
  <div class="content">
160
160
  <h2>Columns Near Overflow</h2>
161
- <p>Consider changing the column type to support a larger range of values.</p>
161
+ <p>Consider changing columns to bigint to support a larger range of values.</p>
162
162
  <table class="table">
163
163
  <thead>
164
164
  <tr>
165
165
  <th>Column</th>
166
166
  <th style="width: 20%;">Type</th>
167
167
  <th style="width: 20%;">Values Left</th>
168
+ <th style="width: 10%;">% Left</th>
168
169
  </tr>
169
170
  </thead>
170
171
  <tbody>
@@ -174,11 +175,14 @@
174
175
  <%= query["table"] %>.<%= query["column"] %>
175
176
  </td>
176
177
  <td>
177
- <span class="text-muted"><%= query["column_type"] %></span>
178
+ <%= query["column_type"] %>
178
179
  </td>
179
180
  <td>
180
181
  <%= number_with_delimiter(query["max_value"].to_i - query["last_value"].to_i) %>
181
182
  </td>
183
+ <td>
184
+ <%= number_to_percentage((query["max_value"].to_i - query["last_value"].to_i) * 100.0 / query["max_value"].to_i, precision: 2, significant: true) %>
185
+ </td>
182
186
  </tr>
183
187
  <% end %>
184
188
  </tbody>
@@ -73,6 +73,34 @@ module PgHero
73
73
  query_start
74
74
  SQL
75
75
  end
76
+
77
+ # from https://wiki.postgresql.org/wiki/Lock_Monitoring
78
+ def blocked_queries
79
+ select_all <<-SQL
80
+ SELECT
81
+ bl.pid AS blocked_pid,
82
+ a.usename AS blocked_user,
83
+ ka.query AS current_or_recent_query_in_blocking_process,
84
+ ka.state AS state_of_blocking_process,
85
+ age(now(), ka.query_start) AS blocking_duration,
86
+ kl.pid AS blocking_pid,
87
+ ka.usename AS blocking_user,
88
+ a.query AS blocked_query,
89
+ age(now(), a.query_start) AS blocked_duration
90
+ FROM
91
+ pg_catalog.pg_locks bl
92
+ JOIN
93
+ pg_catalog.pg_stat_activity a ON a.pid = bl.pid
94
+ JOIN
95
+ pg_catalog.pg_locks kl ON kl.transactionid = bl.transactionid AND kl.pid != bl.pid
96
+ JOIN
97
+ pg_catalog.pg_stat_activity ka ON ka.pid = kl.pid
98
+ WHERE
99
+ NOT bl.GRANTED
100
+ ORDER BY
101
+ blocked_duration DESC
102
+ SQL
103
+ end
76
104
  end
77
105
  end
78
106
  end
@@ -2,23 +2,19 @@ module PgHero
2
2
  module Methods
3
3
  module QueryStats
4
4
  def query_stats(options = {})
5
- current_query_stats = (options[:historical] && options[:end_at] && options[:end_at] < Time.now ? [] : current_query_stats(options)).index_by { |q| q["query_hash"] }
6
- historical_query_stats = (options[:historical] ? historical_query_stats(options) : []).index_by { |q| q["query_hash"] }
7
- current_query_stats.default = {}
8
- historical_query_stats.default = {}
5
+ current_query_stats = options[:historical] && options[:end_at] && options[:end_at] < Time.now ? [] : current_query_stats(options)
6
+ historical_query_stats = options[:historical] ? historical_query_stats(options) : []
9
7
 
10
- query_stats = []
11
- (current_query_stats.keys + historical_query_stats.keys).uniq.each do |query_hash|
12
- value = {
13
- "query" => current_query_stats[query_hash]["query"] || historical_query_stats[query_hash]["query"],
14
- "query_hash" => query_hash,
15
- "total_minutes" => current_query_stats[query_hash]["total_minutes"].to_f + historical_query_stats[query_hash]["total_minutes"].to_f,
16
- "calls" => current_query_stats[query_hash]["calls"].to_i + historical_query_stats[query_hash]["calls"].to_i
17
- }
18
- value["average_time"] = value["total_minutes"] * 1000 * 60 / value["calls"]
19
- value["total_percent"] = value["total_minutes"] * 100.0 / (current_query_stats[query_hash]["all_queries_total_minutes"].to_f + historical_query_stats[query_hash]["all_queries_total_minutes"].to_f)
20
- query_stats << value
8
+ query_stats = combine_query_stats((current_query_stats + historical_query_stats).group_by { |q| q["query_hash"] })
9
+ query_stats = combine_query_stats(query_stats.group_by { |q| normalize_query(q["query"]) })
10
+
11
+ # add percentages
12
+ all_queries_total_minutes = [current_query_stats, historical_query_stats].sum { |s| (s.first || {})["all_queries_total_minutes"].to_f }
13
+ query_stats.each do |query|
14
+ query["average_time"] = query["total_minutes"] * 1000 * 60 / query["calls"]
15
+ query["total_percent"] = query["total_minutes"] * 100.0 / all_queries_total_minutes
21
16
  end
17
+
22
18
  sort = options[:sort] || "total_minutes"
23
19
  query_stats = query_stats.sort_by { |q| -q[sort] }.first(100)
24
20
  if options[:min_average_time]
@@ -235,6 +231,30 @@ module PgHero
235
231
  @server_version ||= {}
236
232
  @server_version[current_database] ||= select_all("SHOW server_version_num").first["server_version_num"].to_i
237
233
  end
234
+
235
+ private
236
+
237
+ def combine_query_stats(grouped_stats)
238
+ query_stats = []
239
+ grouped_stats.each do |_, stats2|
240
+ value = {
241
+ "query" => (stats2.find { |s| s["query"] } || {})["query"],
242
+ "query_hash" => (stats2.find { |s| s["query"] } || {})["query_hash"],
243
+ "total_minutes" => stats2.sum { |s| s["total_minutes"].to_f },
244
+ "calls" => stats2.sum { |s| s["calls"].to_i },
245
+ "all_queries_total_minutes" => stats2.sum { |s| s["all_queries_total_minutes"].to_f }
246
+ }
247
+ value["total_percent"] = value["total_minutes"] * 100.0 / value["all_queries_total_minutes"]
248
+ query_stats << value
249
+ end
250
+ query_stats
251
+ end
252
+
253
+ # removes comments
254
+ # combines ?, ?, ? => ?
255
+ def normalize_query(query)
256
+ squish(query.to_s.gsub(/\?(, ?\?)+/, "?").gsub(/\/\*.+?\*\//, ""))
257
+ end
238
258
  end
239
259
  end
240
260
  end
@@ -1,3 +1,3 @@
1
1
  module PgHero
2
- VERSION = "1.3.0"
2
+ VERSION = "1.3.1"
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: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-28 00:00:00.000000000 Z
11
+ date: 2016-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord