active_record-sql_analyzer 0.0.5

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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +15 -0
  5. data/CONTRIBUTING.md +9 -0
  6. data/Gemfile +12 -0
  7. data/LICENSE.md +202 -0
  8. data/README.md +119 -0
  9. data/Rakefile +6 -0
  10. data/active_record-sql_analyzer.gemspec +21 -0
  11. data/bin/ar-log-analyzer +10 -0
  12. data/lib/active_record/sql_analyzer.rb +40 -0
  13. data/lib/active_record/sql_analyzer/analyzer.rb +45 -0
  14. data/lib/active_record/sql_analyzer/background_processor.rb +54 -0
  15. data/lib/active_record/sql_analyzer/backtrace_filter.rb +38 -0
  16. data/lib/active_record/sql_analyzer/cli.rb +74 -0
  17. data/lib/active_record/sql_analyzer/cli_processor.rb +122 -0
  18. data/lib/active_record/sql_analyzer/compact_logger.rb +31 -0
  19. data/lib/active_record/sql_analyzer/configuration.rb +174 -0
  20. data/lib/active_record/sql_analyzer/logger.rb +29 -0
  21. data/lib/active_record/sql_analyzer/monkeypatches/query.rb +35 -0
  22. data/lib/active_record/sql_analyzer/monkeypatches/tagger.rb +24 -0
  23. data/lib/active_record/sql_analyzer/redacted_logger.rb +22 -0
  24. data/lib/active_record/sql_analyzer/redactor.rb +5 -0
  25. data/lib/active_record/sql_analyzer/version.rb +5 -0
  26. data/spec/active_record/sql_analyzer/analyzer_spec.rb +33 -0
  27. data/spec/active_record/sql_analyzer/background_processor_spec.rb +44 -0
  28. data/spec/active_record/sql_analyzer/backtrace_filter_spec.rb +28 -0
  29. data/spec/active_record/sql_analyzer/cli_processor_spec.rb +120 -0
  30. data/spec/active_record/sql_analyzer/cli_spec.rb +66 -0
  31. data/spec/active_record/sql_analyzer/end_to_end_spec.rb +121 -0
  32. data/spec/active_record/sql_analyzer/redacted_logger_spec.rb +67 -0
  33. data/spec/spec_helper.rb +34 -0
  34. data/spec/support/db_connection.rb +65 -0
  35. data/spec/support/stub_logger.rb +9 -0
  36. data/spec/support/stub_rails.rb +9 -0
  37. data/spec/support/wait_for_pop.rb +13 -0
  38. metadata +129 -0
@@ -0,0 +1,67 @@
1
+ RSpec.describe ActiveRecord::SqlAnalyzer::RedactedLogger do
2
+ let(:tmp_dir) { Dir.mktmpdir }
3
+ after { FileUtils.remove_entry(tmp_dir) }
4
+
5
+ context "#filter_event" do
6
+ let(:event) { {} }
7
+
8
+ subject(:filter_event) do
9
+ instance = described_class.new(tmp_dir, "foo")
10
+ instance.filter_event(event)
11
+ event
12
+ end
13
+
14
+ before do
15
+ ActiveRecord::SqlAnalyzer.configure do |c|
16
+ c.add_backtrace_redactors [
17
+ [/erb_erb_[0-9]+_[0-9]+/, ""]
18
+ ]
19
+ end
20
+ end
21
+
22
+ context "ambiguous backtraces" do
23
+ let(:event) do
24
+ {
25
+ caller: %w(ambiguous foo bar),
26
+ sql: ""
27
+ }
28
+ end
29
+
30
+ before do
31
+ ActiveRecord::SqlAnalyzer.configure do |c|
32
+ c.add_ambiguous_tracers [/ambiguous/]
33
+ end
34
+ end
35
+
36
+ it "switches to ambiguous backtrace logging" do
37
+ expect(filter_event[:caller]).to eq("ambiguous, foo, bar")
38
+ end
39
+ end
40
+
41
+ context "backtrace" do
42
+ let(:event) do
43
+ {
44
+ caller: %w(foo-bar-erb_erb_1_5),
45
+ sql: ""
46
+ }
47
+ end
48
+
49
+ it "redacts" do
50
+ expect(filter_event[:caller]).to eq("foo-bar-")
51
+ end
52
+ end
53
+
54
+ context "sql" do
55
+ let(:event) do
56
+ {
57
+ caller: [""],
58
+ sql: "SELECT * FROM foo WHERE id = 1234"
59
+ }
60
+ end
61
+
62
+ it "redacts" do
63
+ expect(filter_event[:sql]).to eq("SELECT * FROM foo WHERE id = [REDACTED]")
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,34 @@
1
+ require "rspec"
2
+ require "active_record"
3
+ require "timecop"
4
+ require "tmpdir"
5
+ require "support/db_connection"
6
+ require "support/stub_rails"
7
+ require "support/wait_for_pop"
8
+ require "active_record/sql_analyzer.rb"
9
+
10
+ DBConnection.setup_db
11
+ ActiveRecord::SqlAnalyzer.install!
12
+
13
+ RSpec.configure do |c|
14
+ c.disable_monkey_patching!
15
+
16
+ c.before :each do
17
+ DBConnection.reset
18
+ end
19
+
20
+ c.after :each do
21
+ # Try and reset our state to something a bit fresher
22
+ if ActiveRecord::SqlAnalyzer.config
23
+ thread = ActiveRecord::SqlAnalyzer.background_processor.instance_variable_get(:@thread)
24
+ thread.terminate if thread
25
+
26
+ ActiveRecord::SqlAnalyzer.config[:analyzers].each do |analyzer|
27
+ analyzer[:logger_instance].close
28
+ end
29
+
30
+ ActiveRecord::SqlAnalyzer.instance_variable_set(:@background_processor, nil)
31
+ ActiveRecord::SqlAnalyzer.instance_variable_set(:@config, nil)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,65 @@
1
+ class DBConnection
2
+ def self.db
3
+ @db ||= ActiveRecord::Base.establish_connection(
4
+ configuration.merge(database: 'ar_sql_analyzer_test')
5
+ )
6
+ end
7
+
8
+ def self.connection
9
+ db.connection
10
+ end
11
+
12
+ def self.configuration
13
+ {
14
+ adapter: 'mysql2',
15
+ host: 'localhost',
16
+ encoding: 'utf8',
17
+ usernamme: ENV["TRAVIS"] ? "travis" : "root"
18
+ }
19
+ end
20
+
21
+ def self.setup_db
22
+ conn = ActiveRecord::Base.establish_connection(configuration)
23
+ conn.connection.execute <<-SQL
24
+ CREATE DATABASE IF NOT EXISTS ar_sql_analyzer_test
25
+ SQL
26
+ end
27
+
28
+ def self.reset
29
+ connection.execute <<-SQL
30
+ DROP TABLE IF EXISTS matching_table
31
+ SQL
32
+
33
+ connection.execute <<-SQL
34
+ CREATE TABLE `matching_table` (
35
+ `id` int(11) NOT NULL AUTO_INCREMENT,
36
+ `test_string` varchar(255) DEFAULT NULL,
37
+ PRIMARY KEY (`id`)
38
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
39
+ SQL
40
+
41
+ connection.execute <<-SQL
42
+ DROP TABLE IF EXISTS second_matching_table
43
+ SQL
44
+
45
+ connection.execute <<-SQL
46
+ CREATE TABLE `second_matching_table` (
47
+ `id` int(11) NOT NULL AUTO_INCREMENT,
48
+ `test_string` varchar(255) DEFAULT NULL,
49
+ PRIMARY KEY (`id`)
50
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
51
+ SQL
52
+
53
+ connection.execute <<-SQL
54
+ DROP TABLE IF EXISTS nonmatching_table
55
+ SQL
56
+
57
+ connection.execute <<-SQL
58
+ CREATE TABLE `nonmatching_table` (
59
+ `id` int(11) NOT NULL AUTO_INCREMENT,
60
+ `test_string` varchar(255) DEFAULT NULL,
61
+ PRIMARY KEY (`id`)
62
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8
63
+ SQL
64
+ end
65
+ end
@@ -0,0 +1,9 @@
1
+ class Rails
2
+ def self.root
3
+ @root ||= Pathname.new(File.expand_path('../../', __FILE__)).freeze
4
+ end
5
+
6
+ def self.logger
7
+ @logger ||= Logger.new(STDOUT)
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Rails
2
+ def self.root
3
+ @root ||= Pathname.new(File.expand_path('../../', __FILE__)).freeze
4
+ end
5
+
6
+ def self.logger
7
+ @logger ||= Logger.new(STDOUT)
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module WaitForPop
2
+ # This is trying to work around race conditions in a semi-sane manner
3
+ def wait_for_pop
4
+ queue = ActiveRecord::SqlAnalyzer.background_processor.instance_variable_get(:@queue)
5
+
6
+ 4.times do
7
+ return sleep 0.1 if queue.empty?
8
+ sleep 0.05
9
+ end
10
+
11
+ raise "Queue failed to drain in 0.2 seconds"
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_record-sql_analyzer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Zachary Anker
8
+ - Gabriel Gilder
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-01-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '4.0'
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 4.0.0
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '4.0'
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 4.0.0
34
+ - !ruby/object:Gem::Dependency
35
+ name: bundler
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ type: :development
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ description: ActiveRecord query logger and analyzer
49
+ email:
50
+ - zanker@squareup.com
51
+ - gabriel@squareup.com
52
+ executables:
53
+ - ar-log-analyzer
54
+ extensions: []
55
+ extra_rdoc_files: []
56
+ files:
57
+ - ".gitignore"
58
+ - ".rspec"
59
+ - ".travis.yml"
60
+ - CONTRIBUTING.md
61
+ - Gemfile
62
+ - LICENSE.md
63
+ - README.md
64
+ - Rakefile
65
+ - active_record-sql_analyzer.gemspec
66
+ - bin/ar-log-analyzer
67
+ - lib/active_record/sql_analyzer.rb
68
+ - lib/active_record/sql_analyzer/analyzer.rb
69
+ - lib/active_record/sql_analyzer/background_processor.rb
70
+ - lib/active_record/sql_analyzer/backtrace_filter.rb
71
+ - lib/active_record/sql_analyzer/cli.rb
72
+ - lib/active_record/sql_analyzer/cli_processor.rb
73
+ - lib/active_record/sql_analyzer/compact_logger.rb
74
+ - lib/active_record/sql_analyzer/configuration.rb
75
+ - lib/active_record/sql_analyzer/logger.rb
76
+ - lib/active_record/sql_analyzer/monkeypatches/query.rb
77
+ - lib/active_record/sql_analyzer/monkeypatches/tagger.rb
78
+ - lib/active_record/sql_analyzer/redacted_logger.rb
79
+ - lib/active_record/sql_analyzer/redactor.rb
80
+ - lib/active_record/sql_analyzer/version.rb
81
+ - spec/active_record/sql_analyzer/analyzer_spec.rb
82
+ - spec/active_record/sql_analyzer/background_processor_spec.rb
83
+ - spec/active_record/sql_analyzer/backtrace_filter_spec.rb
84
+ - spec/active_record/sql_analyzer/cli_processor_spec.rb
85
+ - spec/active_record/sql_analyzer/cli_spec.rb
86
+ - spec/active_record/sql_analyzer/end_to_end_spec.rb
87
+ - spec/active_record/sql_analyzer/redacted_logger_spec.rb
88
+ - spec/spec_helper.rb
89
+ - spec/support/db_connection.rb
90
+ - spec/support/stub_logger.rb
91
+ - spec/support/stub_rails.rb
92
+ - spec/support/wait_for_pop.rb
93
+ homepage: https://github.com/square/active_record-sql_analyzer
94
+ licenses:
95
+ - Apache License 2.0
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.4.5.1
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Logs a subset of ActiveRecord queries and dumps them for analyses.
117
+ test_files:
118
+ - spec/active_record/sql_analyzer/analyzer_spec.rb
119
+ - spec/active_record/sql_analyzer/background_processor_spec.rb
120
+ - spec/active_record/sql_analyzer/backtrace_filter_spec.rb
121
+ - spec/active_record/sql_analyzer/cli_processor_spec.rb
122
+ - spec/active_record/sql_analyzer/cli_spec.rb
123
+ - spec/active_record/sql_analyzer/end_to_end_spec.rb
124
+ - spec/active_record/sql_analyzer/redacted_logger_spec.rb
125
+ - spec/spec_helper.rb
126
+ - spec/support/db_connection.rb
127
+ - spec/support/stub_logger.rb
128
+ - spec/support/stub_rails.rb
129
+ - spec/support/wait_for_pop.rb