active_record-sql_analyzer 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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