pgdexter 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 14bc122b136301535793c29b19336a2d0614f640
4
- data.tar.gz: 624c8c6ae5aabd8a5e2150887aa83efe6e67f9b4
2
+ SHA256:
3
+ metadata.gz: e51c5c9ce5c31760d773177a3b224674752b19de8cc9fa0978e1da2adff9a490
4
+ data.tar.gz: ce9b2e89d2524aafda39bd5a91bb53abde5d0819e0c8751281a5ff7ad10766c2
5
5
  SHA512:
6
- metadata.gz: 44224c687d8590c0441d587b432fde3b85cef77728980059d497ade992cd953e8f8445747de61c984d559f55d74461ac284c6c8423c0f1f8b08e439e361c141d
7
- data.tar.gz: 42ec40ec7527dfc3093853ec013c5b30bacbaee5cbe8d27a1530649bfbdc16c639d9d93d65e72b062d53b33bff1d0a1bec67e971d283f5d5a2e6fea7d884fccd
6
+ metadata.gz: 63cdf589a11ab232f45e26ff8b6a713ef757ce3bc3baf3fecbc51217fb4c3a4bdda0ded52bc631bbb8aaa5fe7ca28d356ab99e200c5af22a3bd1bac9e5efc17b
7
+ data.tar.gz: fcbb680a98f5907a62216ee142fa91b8538965c1fd59c1de48645ee1b5e3525950245d010a128f52b28fda665d0f6fcbf95fa343184b559150646819049f173a
@@ -6,8 +6,9 @@ addons:
6
6
  postgresql: "9.6"
7
7
  before_script:
8
8
  - sudo apt-get install postgresql-server-dev-9.6
9
- - git clone https://github.com/dalibo/hypopg.git
9
+ - git clone https://github.com/HypoPG/hypopg.git
10
10
  - cd hypopg
11
+ - git checkout 1.1.1
11
12
  - make
12
13
  - sudo make install
13
14
  - psql -c 'create database dexter_test;' -U postgres
@@ -1,3 +1,9 @@
1
+ ## 0.3.4
2
+
3
+ - Fixed `--username` option
4
+ - Fixed `JSON::NestingError`
5
+ - Added `--pg-stat-activity` option
6
+
1
7
  ## 0.3.3
2
8
 
3
9
  - Added support for views and materialized views
data/README.md CHANGED
@@ -8,12 +8,12 @@ The automatic indexer for Postgres
8
8
 
9
9
  ## Installation
10
10
 
11
- First, install [HypoPG](https://github.com/dalibo/hypopg) on your database server. This doesn’t require a restart.
11
+ First, install [HypoPG](https://github.com/HypoPG/hypopg) on your database server. This doesn’t require a restart.
12
12
 
13
13
  ```sh
14
14
  cd /tmp
15
- curl -L https://github.com/dalibo/hypopg/archive/1.1.0.tar.gz | tar xz
16
- cd hypopg-1.1.0
15
+ curl -L https://github.com/HypoPG/hypopg/archive/1.1.1.tar.gz | tar xz
16
+ cd hypopg-1.1.1
17
17
  make
18
18
  make install # may need sudo
19
19
  ```
@@ -104,13 +104,19 @@ or pass files:
104
104
  dexter <connection-options> <file1> <file2>
105
105
  ```
106
106
 
107
+ or collect running queries with: [master]
108
+
109
+ ```sh
110
+ dexter <connection-options> --pg-stat-activity
111
+ ```
112
+
107
113
  or use the [pg_stat_statements](https://www.postgresql.org/docs/current/static/pgstatstatements.html) extension:
108
114
 
109
115
  ```sh
110
116
  dexter <connection-options> --pg-stat-statements
111
117
  ```
112
118
 
113
- > Note: Logs are highly preferred over pg_stat_statements, as pg_stat_statements often doesn’t store enough information to optimize queries.
119
+ > Note: Logs or running queries are highly preferred over pg_stat_statements, as pg_stat_statements often doesn’t store enough information to optimize queries.
114
120
 
115
121
  ### Collection Options
116
122
 
@@ -32,6 +32,7 @@ sudo apt-get install dexter
32
32
  ### Debian 9 (Stretch)
33
33
 
34
34
  ```sh
35
+ sudo apt-get -y install apt-transport-https
35
36
  wget -qO- https://dl.packager.io/srv/pghero/dexter/key | sudo apt-key add -
36
37
  sudo wget -O /etc/apt/sources.list.d/dexter.list \
37
38
  https://dl.packager.io/srv/pghero/dexter/master/installer/debian/9.repo
@@ -42,6 +43,7 @@ sudo apt-get install dexter
42
43
  ### Debian 8 (Jesse)
43
44
 
44
45
  ```sh
46
+ sudo apt-get -y install apt-transport-https
45
47
  wget -qO- https://dl.packager.io/srv/pghero/dexter/key | sudo apt-key add -
46
48
  sudo wget -O /etc/apt/sources.list.d/dexter.list \
47
49
  https://dl.packager.io/srv/pghero/dexter/master/installer/debian/8.repo
@@ -11,6 +11,7 @@ require "dexter/collector"
11
11
  require "dexter/indexer"
12
12
  require "dexter/log_parser"
13
13
  require "dexter/csv_log_parser"
14
+ require "dexter/pg_stat_activity_parser"
14
15
  require "dexter/processor"
15
16
  require "dexter/query"
16
17
 
@@ -18,6 +18,8 @@ module Dexter
18
18
  elsif options[:pg_stat_statements]
19
19
  # TODO support streaming option
20
20
  Indexer.new(options).process_stat_statements
21
+ elsif options[:pg_stat_activity]
22
+ Processor.new(:pg_stat_activity, options).perform
21
23
  elsif arguments.any?
22
24
  ARGV.replace(arguments)
23
25
  Processor.new(ARGF, options).perform
@@ -44,6 +46,7 @@ Options:)
44
46
  o.float "--min-calls", "only process queries that have been called a certain number of times", default: 0
45
47
  o.float "--min-time", "only process queries that have consumed a certain amount of DB time, in minutes", default: 0
46
48
  o.integer "--min-cost-savings-pct", default: 50, help: false
49
+ o.boolean "--pg-stat-activity", "use pg_stat_activity", default: false, help: false
47
50
  o.boolean "--pg-stat-statements", "use pg_stat_statements", default: false, help: false
48
51
  o.string "-s", "--statement", "process a single statement"
49
52
  # separator must go here to show up correctly - slop bug?
@@ -25,6 +25,23 @@ module Dexter
25
25
  process_queries(queries)
26
26
  end
27
27
 
28
+ def stat_activity
29
+ execute <<-SQL
30
+ SELECT
31
+ pid || ':' || COALESCE(query_start, xact_start) AS id,
32
+ query,
33
+ EXTRACT(EPOCH FROM NOW() - COALESCE(query_start, xact_start)) * 1000.0 AS duration_ms
34
+ FROM
35
+ pg_stat_activity
36
+ WHERE
37
+ datname = current_database()
38
+ AND state = 'active'
39
+ AND pid != pg_backend_pid()
40
+ ORDER BY
41
+ 1
42
+ SQL
43
+ end
44
+
28
45
  def process_queries(queries)
29
46
  # reset hypothetical indexes
30
47
  reset_hypothetical_indexes
@@ -166,7 +183,7 @@ module Dexter
166
183
  # Pass format to prevent ANALYZE
167
184
  puts execute("EXPLAIN (FORMAT TEXT) #{safe_statement(query.statement)}").map { |r| r["QUERY PLAN"] }.join("\n")
168
185
  end
169
- rescue PG::Error => e
186
+ rescue PG::Error, JSON::NestingError => e
170
187
  if @log_explain
171
188
  log e.message
172
189
  end
@@ -479,6 +496,9 @@ module Dexter
479
496
 
480
497
  def conn
481
498
  @conn ||= begin
499
+ # set connect timeout if none set
500
+ ENV["PGCONNECT_TIMEOUT"] ||= "2"
501
+
482
502
  if @options[:dbname] =~ /\Apostgres(ql)?:\/\//
483
503
  config = @options[:dbname]
484
504
  else
@@ -486,7 +506,7 @@ module Dexter
486
506
  host: @options[:host],
487
507
  port: @options[:port],
488
508
  dbname: @options[:dbname],
489
- user: @options[:user]
509
+ user: @options[:username]
490
510
  }.reject { |_, value| value.to_s.empty? }
491
511
  config = config[:dbname] if config.keys == [:dbname] && config[:dbname].include?("=")
492
512
  end
@@ -511,7 +531,7 @@ module Dexter
511
531
 
512
532
  def plan(query)
513
533
  # strip semi-colons as another measure of defense
514
- JSON.parse(execute("EXPLAIN (FORMAT JSON) #{safe_statement(query)}").first["QUERY PLAN"]).first["Plan"]
534
+ JSON.parse(execute("EXPLAIN (FORMAT JSON) #{safe_statement(query)}").first["QUERY PLAN"], max_nesting: 1000).first["Plan"]
515
535
  end
516
536
 
517
537
  # TODO for multicolumn indexes, use ordering
@@ -0,0 +1,25 @@
1
+ module Dexter
2
+ class PgStatActivityParser < LogParser
3
+ def perform
4
+ queries = {}
5
+
6
+ loop do
7
+ new_queries = {}
8
+ @logfile.stat_activity.each do |row|
9
+ new_queries[row["id"]] = row
10
+ end
11
+
12
+ # store queries after they complete
13
+ queries.each do |id, row|
14
+ unless new_queries[id]
15
+ process_entry(row["query"], row["duration_ms"].to_f)
16
+ end
17
+ end
18
+
19
+ queries = new_queries
20
+
21
+ sleep(5)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -6,15 +6,17 @@ module Dexter
6
6
  @logfile = logfile
7
7
 
8
8
  @collector = Collector.new(min_time: options[:min_time], min_calls: options[:min_calls])
9
+ @indexer = Indexer.new(options)
10
+
9
11
  @log_parser =
10
- if options[:input_format] == "csv"
12
+ if @logfile == :pg_stat_activity
13
+ PgStatActivityParser.new(@indexer, @collector)
14
+ elsif options[:input_format] == "csv"
11
15
  CsvLogParser.new(logfile, @collector)
12
16
  else
13
17
  LogParser.new(logfile, @collector)
14
18
  end
15
19
 
16
- @indexer = Indexer.new(options)
17
-
18
20
  @starting_interval = 3
19
21
  @interval = options[:interval]
20
22
 
@@ -25,7 +27,7 @@ module Dexter
25
27
  end
26
28
 
27
29
  def perform
28
- if @logfile == STDIN
30
+ if [STDIN, :pg_stat_activity].include?(@logfile)
29
31
  Thread.abort_on_exception = true
30
32
  Thread.new do
31
33
  sleep(@starting_interval)
@@ -1,3 +1,3 @@
1
1
  module Dexter
2
- VERSION = "0.3.3"
2
+ VERSION = "0.3.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgdexter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-23 00:00:00.000000000 Z
11
+ date: 2018-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: slop
@@ -119,6 +119,7 @@ files:
119
119
  - lib/dexter/indexer.rb
120
120
  - lib/dexter/log_parser.rb
121
121
  - lib/dexter/logging.rb
122
+ - lib/dexter/pg_stat_activity_parser.rb
122
123
  - lib/dexter/processor.rb
123
124
  - lib/dexter/query.rb
124
125
  - lib/dexter/version.rb
@@ -142,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
143
  version: '0'
143
144
  requirements: []
144
145
  rubyforge_project:
145
- rubygems_version: 2.6.13
146
+ rubygems_version: 2.7.6
146
147
  signing_key:
147
148
  specification_version: 4
148
149
  summary: The automatic indexer for Postgres