pgdexter 0.3.0 → 0.3.1

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
2
  SHA1:
3
- metadata.gz: 16f61626f5003a801ec12cda3f663390a57e69d8
4
- data.tar.gz: 238ee1b24dab3f473accc2ca9a5156fd31e8d19e
3
+ metadata.gz: 78c0747c456e498798accd4e4881a8041d246e07
4
+ data.tar.gz: c4c9cffe3e04d07675c36abf0532db3634e356ea
5
5
  SHA512:
6
- metadata.gz: ccae6266196fc84ea0fc69177b80144f8747996ff0693b6a7492e34d095b2cb400e9ce3299741326c50a5eb267ef48be368384a2ab27553002eb93ac7b6d0922
7
- data.tar.gz: 944bc27bb1ffff546c2f33aa10aa1b8371ba43ae2be889a6b9445c3d3a93ca36fee0cfd57487134a5ea807e37583f74b1e5e9de7714fa30364ab28f64a5679e8
6
+ metadata.gz: df826f95f34809bd94cb7450cc43d4bd6beed81606e6e7079842dd4a05e983d4041bf956645c09a290cf8fa37140917da1a12fe332d6268969da5310f688e148
7
+ data.tar.gz: f7015b408e7864bfe7e4e136cbb60acbe837cbbe640ec4f43dfb2d9631f2d4cb2b4c86826cb58051d68941bdfa6fd6625029babe7c1609e084db1a4f92a23652
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.3.1
2
+
3
+ - Added support for queries with bind variables
4
+ - Fixed error with streaming logs as csv format
5
+ - Handle malformed CSV gracefully
6
+
1
7
  ## 0.3.0
2
8
 
3
9
  - Added support for schemas
data/README.md CHANGED
@@ -130,7 +130,7 @@ Specify the format
130
130
  dexter --input-format csv
131
131
  ```
132
132
 
133
- When steaming logs, specify the time to wait between processing queries
133
+ When streaming logs, specify the time to wait between processing queries
134
134
 
135
135
  ```sh
136
136
  dexter --interval 60 # seconds
@@ -150,6 +150,14 @@ Homebrew on Mac
150
150
  tail -F -n +1 /usr/local/var/postgres/server.log | dexter dbname
151
151
  ```
152
152
 
153
+ ## Analyze
154
+
155
+ For best results, make sure your tables have been recently analyzed so statistics are up-to-date. You can ask Dexter to analyze tables it comes across that haven’t been analyzed in the past hour with:
156
+
157
+ ```sh
158
+ dexter --analyze
159
+ ```
160
+
153
161
  ## Tables
154
162
 
155
163
  You can exclude large or write-heavy tables from indexing with:
@@ -172,14 +180,6 @@ See how Dexter is processing queries with:
172
180
  dexter --log-sql --log-level debug2
173
181
  ```
174
182
 
175
- ## Analyze
176
-
177
- For best results, make sure your tables have been recently analyzed so statistics are up-to-date. You can ask Dexter to analyze tables it comes across that haven’t been analyzed in the past hour with:
178
-
179
- ```sh
180
- dexter --analyze
181
- ```
182
-
183
183
  ## Hosted Postgres
184
184
 
185
185
  Some hosted providers like Amazon RDS and Heroku do not support the HypoPG extension, which Dexter needs to run. See [how to use Dexter](guides/Hosted-Postgres.md) in these cases.
@@ -3,11 +3,15 @@ require "csv"
3
3
  module Dexter
4
4
  class CsvLogParser < LogParser
5
5
  def perform
6
- CSV.foreach(@logfile.file) do |row|
6
+ CSV.new(@logfile).each do |row|
7
7
  if (m = REGEX.match(row[13]))
8
- process_entry(m[3], m[1].to_f)
8
+ active_line = m[3]
9
+ add_parameters(active_line, row[14]) if row[14]
10
+ process_entry(active_line, m[1].to_f)
9
11
  end
10
12
  end
13
+ rescue CSV::MalformedCSVError => e
14
+ abort "ERROR: #{e.message}"
11
15
  end
12
16
  end
13
17
  end
@@ -130,18 +130,22 @@ module Dexter
130
130
 
131
131
  def calculate_plan(queries)
132
132
  queries.each do |query|
133
+ if @log_explain
134
+ puts "Explaining query"
135
+ puts
136
+ end
133
137
  begin
134
138
  query.plans << plan(query.statement)
135
139
  if @log_explain
136
- log "Explaining query"
137
- puts
138
140
  # Pass format to prevent ANALYZE
139
141
  puts execute("EXPLAIN (FORMAT TEXT) #{safe_statement(query.statement)}").map { |r| r["QUERY PLAN"] }.join("\n")
140
- puts
141
142
  end
142
- rescue PG::Error
143
- # do nothing
143
+ rescue PG::Error => e
144
+ if @log_explain
145
+ log e.message
146
+ end
144
147
  end
148
+ puts if @log_explain
145
149
  end
146
150
  end
147
151
 
@@ -1,7 +1,8 @@
1
1
  module Dexter
2
2
  class LogParser
3
- REGEX = /duration: (\d+\.\d+) ms (statement|execute <unnamed>|parse <unnamed>): (.+)/
3
+ REGEX = /duration: (\d+\.\d+) ms (statement|execute <unnamed>): (.+)/
4
4
  LINE_SEPERATOR = ": ".freeze
5
+ DETAIL_LINE = "DETAIL: ".freeze
5
6
 
6
7
  def initialize(logfile, collector)
7
8
  @logfile = logfile
@@ -14,7 +15,9 @@ module Dexter
14
15
 
15
16
  @logfile.each_line do |line|
16
17
  if active_line
17
- if line.include?(LINE_SEPERATOR)
18
+ if line.include?(DETAIL_LINE)
19
+ add_parameters(active_line, line.chomp.split(DETAIL_LINE)[1])
20
+ elsif line.include?(LINE_SEPERATOR)
18
21
  process_entry(active_line, duration)
19
22
  active_line = nil
20
23
  else
@@ -35,5 +38,18 @@ module Dexter
35
38
  def process_entry(query, duration)
36
39
  @collector.add(query, duration)
37
40
  end
41
+
42
+ def add_parameters(active_line, details)
43
+ if details.start_with?("parameters: ")
44
+ params = Hash[details[12..-1].split(", ").map { |s| s.split(" = ", 2) }]
45
+
46
+ # make sure parsing was successful
47
+ unless params.values.include?(nil)
48
+ params.each do |k, v|
49
+ active_line.sub!(k, v)
50
+ end
51
+ end
52
+ end
53
+ end
38
54
  end
39
55
  end
@@ -43,7 +43,7 @@ module Dexter
43
43
  begin
44
44
  @log_parser.perform
45
45
  rescue Errno::ENOENT => e
46
- abort e.message
46
+ abort "ERROR: #{e.message}"
47
47
  end
48
48
 
49
49
  process_queries
@@ -1,3 +1,3 @@
1
1
  module Dexter
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
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.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-23 00:00:00.000000000 Z
11
+ date: 2017-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: slop