airbrake-ruby 4.1.0 → 5.0.0
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 +5 -5
- data/lib/airbrake-ruby/async_sender.rb +22 -96
- data/lib/airbrake-ruby/backtrace.rb +8 -7
- data/lib/airbrake-ruby/benchmark.rb +39 -0
- data/lib/airbrake-ruby/code_hunk.rb +1 -1
- data/lib/airbrake-ruby/config/processor.rb +84 -0
- data/lib/airbrake-ruby/config/validator.rb +9 -3
- data/lib/airbrake-ruby/config.rb +76 -20
- data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
- data/lib/airbrake-ruby/file_cache.rb +6 -0
- data/lib/airbrake-ruby/filter_chain.rb +16 -1
- data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +2 -2
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +5 -5
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +3 -0
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +2 -0
- data/lib/airbrake-ruby/filters/{keys_whitelist.rb → keys_allowlist.rb} +3 -3
- data/lib/airbrake-ruby/filters/{keys_blacklist.rb → keys_blocklist.rb} +3 -3
- data/lib/airbrake-ruby/filters/keys_filter.rb +39 -20
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +30 -6
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +4 -2
- data/lib/airbrake-ruby/grouppable.rb +12 -0
- data/lib/airbrake-ruby/ignorable.rb +1 -0
- data/lib/airbrake-ruby/inspectable.rb +2 -2
- data/lib/airbrake-ruby/loggable.rb +2 -2
- data/lib/airbrake-ruby/mergeable.rb +12 -0
- data/lib/airbrake-ruby/monotonic_time.rb +48 -0
- data/lib/airbrake-ruby/notice.rb +10 -20
- data/lib/airbrake-ruby/notice_notifier.rb +23 -42
- data/lib/airbrake-ruby/performance_breakdown.rb +52 -0
- data/lib/airbrake-ruby/performance_notifier.rb +126 -49
- data/lib/airbrake-ruby/promise.rb +1 -0
- data/lib/airbrake-ruby/query.rb +26 -11
- data/lib/airbrake-ruby/queue.rb +65 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +120 -0
- data/lib/airbrake-ruby/remote_settings.rb +145 -0
- data/lib/airbrake-ruby/request.rb +20 -6
- data/lib/airbrake-ruby/stashable.rb +15 -0
- data/lib/airbrake-ruby/stat.rb +34 -24
- data/lib/airbrake-ruby/sync_sender.rb +3 -2
- data/lib/airbrake-ruby/tdigest.rb +43 -58
- data/lib/airbrake-ruby/thread_pool.rb +138 -0
- data/lib/airbrake-ruby/timed_trace.rb +58 -0
- data/lib/airbrake-ruby/truncator.rb +10 -4
- data/lib/airbrake-ruby/version.rb +11 -1
- data/lib/airbrake-ruby.rb +219 -53
- data/spec/airbrake_spec.rb +428 -9
- data/spec/async_sender_spec.rb +26 -110
- data/spec/backtrace_spec.rb +44 -44
- data/spec/benchmark_spec.rb +33 -0
- data/spec/code_hunk_spec.rb +11 -11
- data/spec/config/processor_spec.rb +209 -0
- data/spec/config/validator_spec.rb +23 -6
- data/spec/config_spec.rb +77 -7
- data/spec/deploy_notifier_spec.rb +2 -2
- data/spec/{file_cache.rb → file_cache_spec.rb} +2 -4
- data/spec/filter_chain_spec.rb +28 -1
- data/spec/filters/dependency_filter_spec.rb +1 -1
- data/spec/filters/gem_root_filter_spec.rb +9 -9
- data/spec/filters/git_last_checkout_filter_spec.rb +21 -4
- data/spec/filters/git_repository_filter.rb +1 -1
- data/spec/filters/git_revision_filter_spec.rb +13 -11
- data/spec/filters/{keys_whitelist_spec.rb → keys_allowlist_spec.rb} +29 -28
- data/spec/filters/{keys_blacklist_spec.rb → keys_blocklist_spec.rb} +39 -29
- data/spec/filters/root_directory_filter_spec.rb +9 -9
- data/spec/filters/sql_filter_spec.rb +110 -55
- data/spec/filters/system_exit_filter_spec.rb +1 -1
- data/spec/filters/thread_filter_spec.rb +33 -31
- data/spec/fixtures/project_root/code.rb +9 -9
- data/spec/loggable_spec.rb +17 -0
- data/spec/monotonic_time_spec.rb +23 -0
- data/spec/{notice_notifier_spec → notice_notifier}/options_spec.rb +19 -21
- data/spec/notice_notifier_spec.rb +20 -80
- data/spec/notice_spec.rb +9 -11
- data/spec/performance_breakdown_spec.rb +11 -0
- data/spec/performance_notifier_spec.rb +360 -85
- data/spec/query_spec.rb +11 -0
- data/spec/queue_spec.rb +18 -0
- data/spec/remote_settings/settings_data_spec.rb +365 -0
- data/spec/remote_settings_spec.rb +230 -0
- data/spec/request_spec.rb +9 -0
- data/spec/response_spec.rb +8 -8
- data/spec/spec_helper.rb +9 -13
- data/spec/stashable_spec.rb +23 -0
- data/spec/stat_spec.rb +17 -15
- data/spec/sync_sender_spec.rb +14 -12
- data/spec/tdigest_spec.rb +6 -6
- data/spec/thread_pool_spec.rb +187 -0
- data/spec/timed_trace_spec.rb +125 -0
- data/spec/truncator_spec.rb +12 -12
- metadata +55 -18
@@ -1,4 +1,4 @@
|
|
1
|
-
RSpec.describe Airbrake::Filters::
|
1
|
+
RSpec.describe Airbrake::Filters::KeysBlocklist do
|
2
2
|
subject { described_class.new(patterns) }
|
3
3
|
|
4
4
|
let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
|
@@ -19,8 +19,8 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
19
19
|
[/\Abon/],
|
20
20
|
[
|
21
21
|
{ bongo: 'bango' },
|
22
|
-
{ bongo: '[Filtered]' }
|
23
|
-
]
|
22
|
+
{ bongo: '[Filtered]' },
|
23
|
+
],
|
24
24
|
)
|
25
25
|
|
26
26
|
context "and when a key is a hash" do
|
@@ -40,8 +40,8 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
40
40
|
[:bingo],
|
41
41
|
[
|
42
42
|
{ bingo: 'bango' },
|
43
|
-
{ bingo: '[Filtered]' }
|
44
|
-
]
|
43
|
+
{ bingo: '[Filtered]' },
|
44
|
+
],
|
45
45
|
)
|
46
46
|
end
|
47
47
|
|
@@ -51,8 +51,8 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
51
51
|
['bingo'],
|
52
52
|
[
|
53
53
|
{ bingo: 'bango' },
|
54
|
-
{ bingo: '[Filtered]' }
|
55
|
-
]
|
54
|
+
{ bingo: '[Filtered]' },
|
55
|
+
],
|
56
56
|
)
|
57
57
|
end
|
58
58
|
|
@@ -62,8 +62,8 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
62
62
|
['bingo'],
|
63
63
|
[
|
64
64
|
{ array: [{ bingo: 'bango' }, []] },
|
65
|
-
{ array: [{ bingo: '[Filtered]' }, []] }
|
66
|
-
]
|
65
|
+
{ array: [{ bingo: '[Filtered]' }, []] },
|
66
|
+
],
|
67
67
|
)
|
68
68
|
end
|
69
69
|
|
@@ -74,8 +74,8 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
74
74
|
[proc { 'bongo' }, :bash],
|
75
75
|
[
|
76
76
|
{ bingo: 'bango', bongo: 'bish', bash: 'bosh' },
|
77
|
-
{ bingo: 'bango', bongo: '[Filtered]', bash: '[Filtered]' }
|
78
|
-
]
|
77
|
+
{ bingo: 'bango', bongo: '[Filtered]', bash: '[Filtered]' },
|
78
|
+
],
|
79
79
|
)
|
80
80
|
end
|
81
81
|
|
@@ -85,16 +85,16 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
85
85
|
[proc { Object.new }],
|
86
86
|
[
|
87
87
|
{ bingo: 'bango', bongo: 'bish' },
|
88
|
-
{ bingo: 'bango', bongo: 'bish' }
|
89
|
-
]
|
88
|
+
{ bingo: 'bango', bongo: 'bish' },
|
89
|
+
],
|
90
90
|
)
|
91
91
|
|
92
92
|
it "logs an error" do
|
93
93
|
expect(Airbrake::Loggable.instance).to receive(:error).with(
|
94
|
-
/
|
94
|
+
/KeysBlocklist is invalid.+patterns: \[#<Object:.+>\]/,
|
95
95
|
)
|
96
|
-
|
97
|
-
|
96
|
+
keys_blocklist = described_class.new(patterns)
|
97
|
+
keys_blocklist.call(notice)
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
@@ -104,10 +104,10 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
104
104
|
context "and when the filter is called once" do
|
105
105
|
it "logs an error" do
|
106
106
|
expect(Airbrake::Loggable.instance).to receive(:error).with(
|
107
|
-
/
|
107
|
+
/KeysBlocklist is invalid.+patterns: \[#<Proc:.+>\]/,
|
108
108
|
)
|
109
|
-
|
110
|
-
|
109
|
+
keys_blocklist = described_class.new(patterns)
|
110
|
+
keys_blocklist.call(notice)
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -127,16 +127,16 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
127
127
|
[Object.new],
|
128
128
|
[
|
129
129
|
{ bingo: 'bango', bongo: 'bish' },
|
130
|
-
{ bingo: 'bango', bongo: 'bish' }
|
131
|
-
]
|
130
|
+
{ bingo: 'bango', bongo: 'bish' },
|
131
|
+
],
|
132
132
|
)
|
133
133
|
|
134
134
|
it "logs an error" do
|
135
135
|
expect(Airbrake::Loggable.instance).to receive(:error).with(
|
136
|
-
/
|
136
|
+
/KeysBlocklist is invalid.+patterns: \[#<Object:.+>\]/,
|
137
137
|
)
|
138
|
-
|
139
|
-
|
138
|
+
keys_blocklist = described_class.new(patterns)
|
139
|
+
keys_blocklist.call(notice)
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
@@ -147,9 +147,19 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
147
147
|
['bish'],
|
148
148
|
[
|
149
149
|
{ bongo: { bish: 'bash' } },
|
150
|
-
{ bongo: { bish: '[Filtered]' } }
|
151
|
-
]
|
150
|
+
{ bongo: { bish: '[Filtered]' } },
|
151
|
+
],
|
152
152
|
)
|
153
|
+
|
154
|
+
it "doesn't mutate the original hash" do
|
155
|
+
params = { bongo: { bish: 'bash' } }
|
156
|
+
notice[:params] = params
|
157
|
+
|
158
|
+
blocklist = described_class.new([:bish])
|
159
|
+
blocklist.call(notice)
|
160
|
+
|
161
|
+
expect(params[:bongo][:bish]).to eq('bash')
|
162
|
+
end
|
153
163
|
end
|
154
164
|
|
155
165
|
context "and it is recursive" do
|
@@ -161,8 +171,8 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
161
171
|
['bango'],
|
162
172
|
[
|
163
173
|
bongo,
|
164
|
-
{ bingo: { bango: '[Filtered]' } }
|
165
|
-
]
|
174
|
+
{ bingo: { bango: '[Filtered]' } },
|
175
|
+
],
|
166
176
|
)
|
167
177
|
end
|
168
178
|
end
|
@@ -177,7 +187,7 @@ RSpec.describe Airbrake::Filters::KeysBlacklist do
|
|
177
187
|
|
178
188
|
subject.call(notice)
|
179
189
|
expect(notice[:context][:url]).to(
|
180
|
-
eq
|
190
|
+
eq('http://localhost:3000/crash?foo=bar&baz=bongo&bish=[Filtered]&color=%23FFAAFF'),
|
181
191
|
)
|
182
192
|
end
|
183
193
|
end
|
@@ -5,35 +5,35 @@ RSpec.describe Airbrake::Filters::RootDirectoryFilter do
|
|
5
5
|
let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
|
6
6
|
|
7
7
|
it "replaces root directory in the backtrace with a label" do
|
8
|
-
# rubocop:disable
|
8
|
+
# rubocop:disable Layout/LineLength
|
9
9
|
notice[:errors].first[:backtrace] = [
|
10
10
|
{ file: "/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb" },
|
11
11
|
{ file: "#{root_directory}/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb " },
|
12
12
|
{ file: "/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb" },
|
13
|
-
{ file: "#{root_directory}/gems/rspec-core-3.3.2/exe/rspec" }
|
13
|
+
{ file: "#{root_directory}/gems/rspec-core-3.3.2/exe/rspec" },
|
14
14
|
]
|
15
|
-
# rubocop:enable
|
15
|
+
# rubocop:enable Layout/LineLength
|
16
16
|
|
17
17
|
subject.call(notice)
|
18
18
|
|
19
|
-
# rubocop:disable
|
19
|
+
# rubocop:disable Layout/LineLength
|
20
20
|
expect(notice[:errors].first[:backtrace]).to(
|
21
21
|
eq(
|
22
22
|
[
|
23
23
|
{ file: "/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb" },
|
24
24
|
{ file: "/PROJECT_ROOT/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb " },
|
25
25
|
{ file: "/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb" },
|
26
|
-
{ file: "/PROJECT_ROOT/gems/rspec-core-3.3.2/exe/rspec" }
|
27
|
-
]
|
28
|
-
)
|
26
|
+
{ file: "/PROJECT_ROOT/gems/rspec-core-3.3.2/exe/rspec" },
|
27
|
+
],
|
28
|
+
),
|
29
29
|
)
|
30
|
-
# rubocop:enable
|
30
|
+
# rubocop:enable Layout/LineLength
|
31
31
|
end
|
32
32
|
|
33
33
|
it "does not filter file when it is nil" do
|
34
34
|
expect(notice[:errors].first[:file]).to be_nil
|
35
35
|
expect { subject.call(notice) }.not_to(
|
36
|
-
change { notice[:errors].first[:file] }
|
36
|
+
change { notice[:errors].first[:file] },
|
37
37
|
)
|
38
38
|
end
|
39
39
|
end
|
@@ -10,210 +10,265 @@ RSpec.describe Airbrake::Filters::SqlFilter do
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
shared_examples "query blocklisting" do |query, opts|
|
14
|
+
it "ignores '#{query}'" do
|
15
|
+
filter = described_class.new('postgres')
|
16
|
+
q = Airbrake::Query.new(query: query, method: 'GET', route: '/', timing: 1)
|
17
|
+
filter.call(q)
|
18
|
+
|
19
|
+
expect(q.ignored?).to eq(opts[:should_ignore])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
13
23
|
ALL_DIALECTS = %i[mysql postgres sqlite cassandra oracle].freeze
|
14
24
|
|
15
|
-
# rubocop:disable
|
25
|
+
# rubocop:disable Layout/LineLength
|
16
26
|
[
|
17
27
|
{
|
18
28
|
input: 'SELECT * FROM things;',
|
19
29
|
output: 'SELECT * FROM things;',
|
20
|
-
dialects: ALL_DIALECTS
|
30
|
+
dialects: ALL_DIALECTS,
|
21
31
|
}, {
|
22
32
|
input: "SELECT `t001`.`c2` FROM `t001` WHERE `t001`.`c2` = 'value' AND c3=\"othervalue\" LIMIT ?",
|
23
33
|
output: "SELECT `t001`.`c2` FROM `t001` WHERE `t001`.`c2` = ? AND c3=? LIMIT ?",
|
24
|
-
dialects: %i[mysql]
|
34
|
+
dialects: %i[mysql],
|
25
35
|
}, {
|
26
36
|
input: "SELECT * FROM t WHERE foo=\"bar/*\" AND baz=\"whatever */qux\"",
|
27
37
|
output: "SELECT * FROM t WHERE foo=? AND baz=?",
|
28
|
-
dialects: %i[mysql]
|
38
|
+
dialects: %i[mysql],
|
29
39
|
}, {
|
30
40
|
input: "SELECT * FROM t WHERE foo='bar/*' AND baz='whatever */qux'",
|
31
41
|
output: "SELECT * FROM t WHERE foo=? AND baz=?",
|
32
|
-
dialects: ALL_DIALECTS
|
42
|
+
dialects: ALL_DIALECTS,
|
33
43
|
}, {
|
34
44
|
input: "SELECT \"t001\".\"c2\" FROM \"t001\" WHERE \"t001\".\"c2\" = 'value' AND c3=1234 LIMIT 1",
|
35
45
|
output: "SELECT \"t001\".\"c2\" FROM \"t001\" WHERE \"t001\".\"c2\" = ? AND c3=? LIMIT ?",
|
36
|
-
dialects: %i[postgres oracle]
|
46
|
+
dialects: %i[postgres oracle],
|
37
47
|
}, {
|
38
48
|
input: "SELECT * FROM t WHERE foo=\"bar--\" AND\n baz=\"qux--\"",
|
39
49
|
output: "SELECT * FROM t WHERE foo=? AND\n baz=?",
|
40
|
-
dialects: %i[mysql]
|
50
|
+
dialects: %i[mysql],
|
41
51
|
}, {
|
42
52
|
input: "SELECT * FROM t WHERE foo='bar--' AND\n baz='qux--'",
|
43
53
|
output: "SELECT * FROM t WHERE foo=? AND\n baz=?",
|
44
|
-
dialects: ALL_DIALECTS
|
54
|
+
dialects: ALL_DIALECTS,
|
45
55
|
}, {
|
46
56
|
input: "SELECT * FROM foo WHERE bar='baz' /* Hide Me */",
|
47
57
|
output: "SELECT * FROM foo WHERE bar=? ?",
|
48
|
-
dialects: ALL_DIALECTS
|
58
|
+
dialects: ALL_DIALECTS,
|
49
59
|
}, {
|
50
60
|
input: "SELECT * FROM foobar WHERE password='hunter2'\n-- No peeking!",
|
51
61
|
output: "SELECT * FROM foobar WHERE password=?\n?",
|
52
|
-
dialects: ALL_DIALECTS
|
62
|
+
dialects: ALL_DIALECTS,
|
53
63
|
}, {
|
54
64
|
input: "SELECT foo, bar FROM baz WHERE password='hunter2' # Secret",
|
55
65
|
output: "SELECT foo, bar FROM baz WHERE password=? ?",
|
56
|
-
dialects: ALL_DIALECTS
|
66
|
+
dialects: ALL_DIALECTS,
|
57
67
|
}, {
|
58
68
|
input: "SELECT \"col1\", \"col2\" from \"table\" WHERE \"col3\"=E'foo\\'bar\\\\baz' AND country=e'foo\\'bar\\\\baz'",
|
59
69
|
output: "SELECT \"col1\", \"col2\" from \"table\" WHERE \"col3\"=E?",
|
60
|
-
dialects: %i[postgres]
|
70
|
+
dialects: %i[postgres],
|
61
71
|
}, {
|
62
72
|
input: "INSERT INTO `X` values(\"test\",0, 1 , 2, 'test')",
|
63
|
-
output: "INSERT INTO `X` values(
|
64
|
-
dialects: %i[mysql]
|
73
|
+
output: "INSERT INTO `X` values(?)",
|
74
|
+
dialects: %i[mysql],
|
75
|
+
}, {
|
76
|
+
input: "INSERT INTO `X` values(\"test\",0, 1 , 2, 'test')",
|
77
|
+
output: "INSERT INTO `X` values(?)",
|
78
|
+
dialects: %i[mysql],
|
65
79
|
}, {
|
66
80
|
input: "SELECT c11.col1, c22.col2 FROM table c11, table c22 WHERE value='nothing'",
|
67
81
|
output: "SELECT c11.col1, c22.col2 FROM table c11, table c22 WHERE value=?",
|
68
|
-
dialects: ALL_DIALECTS
|
82
|
+
dialects: ALL_DIALECTS,
|
69
83
|
}, {
|
70
84
|
input: "INSERT INTO X VALUES(1, 23456, 123.456, 99+100)",
|
71
|
-
output: "INSERT INTO X VALUES(
|
72
|
-
dialects: ALL_DIALECTS
|
85
|
+
output: "INSERT INTO X VALUES(?)",
|
86
|
+
dialects: ALL_DIALECTS,
|
73
87
|
}, {
|
74
88
|
input: "SELECT * FROM table WHERE name=\"foo\" AND value=\"don't\"",
|
75
89
|
output: "SELECT * FROM table WHERE name=? AND value=?",
|
76
|
-
dialects: %i[mysql]
|
90
|
+
dialects: %i[mysql],
|
77
91
|
}, {
|
78
92
|
input: "SELECT * FROM table WHERE name='foo' AND value = 'bar'",
|
79
93
|
output: "SELECT * FROM table WHERE name=? AND value = ?",
|
80
|
-
dialects: ALL_DIALECTS
|
94
|
+
dialects: ALL_DIALECTS,
|
81
95
|
}, {
|
82
96
|
input: "SELECT * FROM table WHERE col='foo\\''bar'",
|
83
97
|
output: "SELECT * FROM table WHERE col=?",
|
84
|
-
dialects: ALL_DIALECTS
|
98
|
+
dialects: ALL_DIALECTS,
|
85
99
|
}, {
|
86
100
|
input: "SELECT * FROM table WHERE col1='foo\"bar' AND col2='what\"ever'",
|
87
101
|
output: "SELECT * FROM table WHERE col1=? AND col2=?",
|
88
|
-
dialects: ALL_DIALECTS
|
102
|
+
dialects: ALL_DIALECTS,
|
89
103
|
}, {
|
90
104
|
input: "select * from accounts where accounts.name != 'dude\n newline' order by accounts.name",
|
91
105
|
output: "select * from accounts where accounts.name != ? order by accounts.name",
|
92
|
-
dialects: ALL_DIALECTS
|
106
|
+
dialects: ALL_DIALECTS,
|
93
107
|
}, {
|
94
108
|
input: "SELECT * FROM table WHERE col1=\"don't\" AND col2=\"won't\"",
|
95
109
|
output: "SELECT * FROM table WHERE col1=? AND col2=?",
|
96
|
-
dialects: %i[mysql]
|
110
|
+
dialects: %i[mysql],
|
97
111
|
}, {
|
98
112
|
input: "INSERT INTO X values('', 'jim''s ssn',0, 1 , 'jim''s son''s son', \"\"\"jim''s\"\" hat\", \"\\\"jim''s secret\\\"\")",
|
99
113
|
output: "INSERT INTO X values(?, ?,?, ? , ?, ?, ?",
|
100
|
-
dialects: %i[mysql]
|
114
|
+
dialects: %i[mysql],
|
101
115
|
}, {
|
102
116
|
input: "SELECT * FROM table WHERE name='foo\\' AND color='blue'",
|
103
117
|
output: "SELECT * FROM table WHERE name=?",
|
104
|
-
dialects: ALL_DIALECTS
|
118
|
+
dialects: ALL_DIALECTS,
|
105
119
|
}, {
|
106
120
|
input: "SELECT * FROM table WHERE foo=\"this string ends with a backslash\\\\\"",
|
107
121
|
output: "SELECT * FROM table WHERE foo=?",
|
108
|
-
dialects: %i[mysql]
|
122
|
+
dialects: %i[mysql],
|
109
123
|
}, {
|
110
124
|
input: "SELECT * FROM table WHERE foo='this string ends with a backslash\\\\'",
|
111
125
|
output: "SELECT * FROM table WHERE foo=?",
|
112
|
-
dialects: ALL_DIALECTS
|
126
|
+
dialects: ALL_DIALECTS,
|
113
127
|
}, {
|
114
128
|
# TODO: fix this example.
|
115
129
|
input: "SELECT * FROM table WHERE name='foo\'' AND color='blue'",
|
116
130
|
output: "Error: Airbrake::Query was not filtered",
|
117
|
-
dialects: ALL_DIALECTS
|
131
|
+
dialects: ALL_DIALECTS,
|
118
132
|
}, {
|
119
133
|
input: "INSERT INTO X values('', 'a''b c',0, 1 , 'd''e f''s h')",
|
120
|
-
output: "INSERT INTO X values(
|
121
|
-
dialects: ALL_DIALECTS
|
134
|
+
output: "INSERT INTO X values(?)",
|
135
|
+
dialects: ALL_DIALECTS,
|
122
136
|
}, {
|
123
137
|
input: "SELECT * FROM t WHERE -- '\n bar='baz' -- '",
|
124
138
|
output: "SELECT * FROM t WHERE ?\n bar=? ?",
|
125
|
-
dialects: ALL_DIALECTS
|
139
|
+
dialects: ALL_DIALECTS,
|
126
140
|
}, {
|
127
141
|
input: "SELECT * FROM t WHERE /* ' */\n bar='baz' -- '",
|
128
142
|
output: "SELECT * FROM t WHERE ?\n bar=? ?",
|
129
|
-
dialects: ALL_DIALECTS
|
143
|
+
dialects: ALL_DIALECTS,
|
130
144
|
}, {
|
131
145
|
input: "SELECT * FROM t WHERE -- '\n /* ' */ c2='xxx' /* ' */\n c='x\n xx' -- '",
|
132
146
|
output: "SELECT * FROM t WHERE ?\n ? c2=? ?\n c=? ?",
|
133
|
-
dialects: ALL_DIALECTS
|
147
|
+
dialects: ALL_DIALECTS,
|
134
148
|
}, {
|
135
149
|
input: "SELECT * FROM t WHERE -- '\n c='x\n xx' -- '",
|
136
150
|
output: "SELECT * FROM t WHERE ?\n c=? ?",
|
137
|
-
dialects: ALL_DIALECTS
|
151
|
+
dialects: ALL_DIALECTS,
|
138
152
|
}, {
|
139
153
|
input: "SELECT * FROM foo WHERE col='value1' AND /* don't */ col2='value1' /* won't */",
|
140
154
|
output: "SELECT * FROM foo WHERE col=? AND ? col2=? ?",
|
141
|
-
dialects: ALL_DIALECTS
|
155
|
+
dialects: ALL_DIALECTS,
|
142
156
|
}, {
|
143
157
|
input: "SELECT * FROM table WHERE foo='bar' AND baz=\"nothing to see here'",
|
144
158
|
output: "Error: Airbrake::Query was not filtered",
|
145
|
-
dialects: %i[mysql]
|
159
|
+
dialects: %i[mysql],
|
146
160
|
}, {
|
147
161
|
input: "SELECT * FROM table WHERE foo='bar' AND baz='nothing to see here",
|
148
162
|
output: "Error: Airbrake::Query was not filtered",
|
149
|
-
dialects: ALL_DIALECTS
|
163
|
+
dialects: ALL_DIALECTS,
|
150
164
|
}, {
|
151
165
|
input: "SELECT * FROM \"foo\" WHERE \"foo\" = $a$dollar quotes can be $b$nested$b$$a$ and bar = 'baz'",
|
152
166
|
output: "SELECT * FROM \"foo\" WHERE \"foo\" = ? and bar = ?",
|
153
|
-
dialects: %i[postgres]
|
167
|
+
dialects: %i[postgres],
|
154
168
|
}, {
|
155
169
|
input: "INSERT INTO \"foo\" (\"bar\", \"baz\", \"qux\") VALUES ($1, $2, $3) RETURNING \"id\"",
|
156
|
-
output: "INSERT INTO \"foo\" (
|
157
|
-
dialects: %i[postgres]
|
170
|
+
output: "INSERT INTO \"foo\" (?) RETURNING \"id\"",
|
171
|
+
dialects: %i[postgres],
|
158
172
|
}, {
|
159
173
|
input: "select * from foo where bar = 'some\\tthing' and baz = 10",
|
160
174
|
output: "select * from foo where bar = ? and baz = ?",
|
161
|
-
dialects: ALL_DIALECTS
|
175
|
+
dialects: ALL_DIALECTS,
|
162
176
|
}, {
|
163
177
|
input: "select * from users where user = 'user1\\' password = 'hunter 2' -- ->don't count this quote",
|
164
178
|
output: "select * from users where user = ?",
|
165
|
-
dialects: ALL_DIALECTS
|
179
|
+
dialects: ALL_DIALECTS,
|
166
180
|
}, {
|
167
181
|
input: "select * from foo where bar=q'[baz's]' and x=5",
|
168
182
|
output: "select * from foo where bar=? and x=?",
|
169
|
-
dialects: %i[oracle]
|
183
|
+
dialects: %i[oracle],
|
170
184
|
}, {
|
171
185
|
input: "select * from foo where bar=q'{baz's}' and x=5",
|
172
186
|
output: "select * from foo where bar=? and x=?",
|
173
|
-
dialects: %i[oracle]
|
187
|
+
dialects: %i[oracle],
|
174
188
|
}, {
|
175
189
|
input: "select * from foo where bar=q'<baz's>' and x=5",
|
176
190
|
output: "select * from foo where bar=? and x=?",
|
177
|
-
dialects: %i[oracle]
|
191
|
+
dialects: %i[oracle],
|
178
192
|
}, {
|
179
193
|
input: "select * from foo where bar=q'(baz's)' and x=5",
|
180
194
|
output: "select * from foo where bar=? and x=?",
|
181
|
-
dialects: %i[oracle]
|
195
|
+
dialects: %i[oracle],
|
182
196
|
}, {
|
183
197
|
input: "select * from foo where bar=0xabcdef123 and x=5",
|
184
198
|
output: "select * from foo where bar=? and x=?",
|
185
|
-
dialects: %i[cassandra sqlite]
|
199
|
+
dialects: %i[cassandra sqlite],
|
186
200
|
}, {
|
187
201
|
input: "select * from foo where bar=0x2F and x=5",
|
188
202
|
output: "select * from foo where bar=? and x=?",
|
189
|
-
dialects: %i[mysql cassandra sqlite]
|
203
|
+
dialects: %i[mysql cassandra sqlite],
|
190
204
|
}, {
|
191
205
|
input: "select * from foo where bar=1.234e-5 and x=5",
|
192
206
|
output: "select * from foo where bar=? and x=?",
|
193
|
-
dialects: ALL_DIALECTS
|
207
|
+
dialects: ALL_DIALECTS,
|
194
208
|
}, {
|
195
209
|
input: "select * from foo where bar=01234567-89ab-cdef-0123-456789abcdef and x=5",
|
196
210
|
output: "select * from foo where bar=? and x=?",
|
197
|
-
dialects: %i[postgres cassandra]
|
211
|
+
dialects: %i[postgres cassandra],
|
198
212
|
}, {
|
199
213
|
input: "select * from foo where bar={01234567-89ab-cdef-0123-456789abcdef} and x=5",
|
200
214
|
output: "select * from foo where bar=? and x=?",
|
201
|
-
dialects: %i[postgres]
|
215
|
+
dialects: %i[postgres],
|
202
216
|
}, {
|
203
217
|
input: "select * from foo where bar=0123456789abcdef0123456789abcdef and x=5",
|
204
218
|
output: "select * from foo where bar=? and x=?",
|
205
|
-
dialects: %i[postgtes]
|
219
|
+
dialects: %i[postgtes],
|
206
220
|
}, {
|
207
221
|
input: "select * from foo where bar={012-345678-9abc-def012345678-9abcdef} and x=5",
|
208
222
|
output: "select * from foo where bar=? and x=?",
|
209
|
-
dialects: %i[postgres]
|
223
|
+
dialects: %i[postgres],
|
210
224
|
}, {
|
211
225
|
input: "select * from foo where bar=true and x=FALSE",
|
212
226
|
output: "select * from foo where bar=? and x=?",
|
213
|
-
dialects: %i[mysql postgres cassandra sqlite]
|
227
|
+
dialects: %i[mysql postgres cassandra sqlite],
|
214
228
|
}
|
215
229
|
].each do |test|
|
216
230
|
include_examples 'query filtering', test
|
217
231
|
end
|
218
|
-
# rubocop:enable
|
232
|
+
# rubocop:enable Layout/LineLength
|
233
|
+
|
234
|
+
[
|
235
|
+
'COMMIT',
|
236
|
+
'commit',
|
237
|
+
'BEGIN',
|
238
|
+
'begin',
|
239
|
+
'SET time zone ?',
|
240
|
+
'set time zone ?',
|
241
|
+
'SHOW max_identifier_length',
|
242
|
+
'show max_identifier_length',
|
243
|
+
|
244
|
+
'WITH pk_constraint AS ( SELECT conrelid, unnest(conkey) AS connum ' \
|
245
|
+
'FROM pg_constraint WHERE contype = ? AND conrelid = ?::regclass ), ' \
|
246
|
+
'cons AS ( SELECT conrelid, connum, row_number() OVER() AS rownum FROM ' \
|
247
|
+
'pk_constraint ) SELECT attr.attname FROM pg_attribute attr INNER JOIN ' \
|
248
|
+
'cons ON attr.attrelid = cons.conrelid AND attr.attnum = cons.connum ' \
|
249
|
+
'ORDER BY cons.rownum',
|
250
|
+
|
251
|
+
'SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON ' \
|
252
|
+
'n.oid = c.relnamespace WHERE n.nspname = ANY (?)',
|
253
|
+
|
254
|
+
'SELECT a.attname FROM ( SELECT indrelid, indkey, generate_subscripts(?) ' \
|
255
|
+
'idx FROM pg_index WHERE indrelid = ?::regclass AND indisprimary ) i ' \
|
256
|
+
'JOIN pg_attribute a ON a.attrelid = i.indrelid AND ' \
|
257
|
+
'a.attnum = i.indkey[i.idx] ORDER BY i.idx',
|
258
|
+
|
259
|
+
'SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, ' \
|
260
|
+
't.typtype, t.typbasetype FROM pg_type as t LEFT JOIN pg_range as r ON ' \
|
261
|
+
'oid = rngtypid WHERE t.typname IN (?) OR t.typtype IN (?) OR t.typinput ' \
|
262
|
+
'= ?::regprocedure OR t.typelem != ?',
|
263
|
+
|
264
|
+
'SELECT t.oid, t.typname FROM pg_type as t WHERE t.typname IN (?)',
|
265
|
+
].each do |query|
|
266
|
+
include_examples 'query blocklisting', query, should_ignore: true
|
267
|
+
end
|
268
|
+
|
269
|
+
[
|
270
|
+
'UPDATE "users" SET "last_sign_in_at" = ? WHERE "users"."id" = ?',
|
271
|
+
].each do |query|
|
272
|
+
include_examples 'query blocklisting', query, should_ignore: false
|
273
|
+
end
|
219
274
|
end
|
@@ -2,7 +2,7 @@ RSpec.describe Airbrake::Filters::SystemExitFilter do
|
|
2
2
|
it "marks SystemExit exceptions as ignored" do
|
3
3
|
notice = Airbrake::Notice.new(SystemExit.new)
|
4
4
|
expect { subject.call(notice) }.to(
|
5
|
-
change { notice.ignored? }.from(false).to(true)
|
5
|
+
change { notice.ignored? }.from(false).to(true),
|
6
6
|
)
|
7
7
|
end
|
8
8
|
|
@@ -77,13 +77,13 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
|
|
77
77
|
{
|
78
78
|
bish: {
|
79
79
|
bash: 'foo',
|
80
|
-
bosh: Object.new
|
81
|
-
}
|
82
|
-
}
|
83
|
-
]
|
84
|
-
}
|
80
|
+
bosh: Object.new,
|
81
|
+
},
|
82
|
+
},
|
83
|
+
],
|
84
|
+
},
|
85
85
|
},
|
86
|
-
123
|
86
|
+
123,
|
87
87
|
]
|
88
88
|
end
|
89
89
|
|
@@ -103,15 +103,15 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
|
|
103
103
|
{
|
104
104
|
bish: {
|
105
105
|
bash: 'foo',
|
106
|
-
bosh: /\A#<Object:.+>\z
|
107
|
-
}
|
108
|
-
}
|
109
|
-
]
|
110
|
-
}
|
106
|
+
bosh: /\A#<Object:.+>\z/,
|
107
|
+
},
|
108
|
+
},
|
109
|
+
],
|
110
|
+
},
|
111
111
|
},
|
112
|
-
123
|
113
|
-
]
|
114
|
-
)
|
112
|
+
123,
|
113
|
+
],
|
114
|
+
),
|
115
115
|
)
|
116
116
|
end
|
117
117
|
end
|
@@ -194,13 +194,13 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
|
|
194
194
|
{
|
195
195
|
bish: {
|
196
196
|
bash: 'foo',
|
197
|
-
bosh: Object.new
|
198
|
-
}
|
199
|
-
}
|
200
|
-
]
|
201
|
-
}
|
197
|
+
bosh: Object.new,
|
198
|
+
},
|
199
|
+
},
|
200
|
+
],
|
201
|
+
},
|
202
202
|
},
|
203
|
-
123
|
203
|
+
123,
|
204
204
|
]
|
205
205
|
end
|
206
206
|
|
@@ -220,15 +220,15 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
|
|
220
220
|
{
|
221
221
|
bish: {
|
222
222
|
bash: 'foo',
|
223
|
-
bosh: /\A#<Object:.+>\z
|
224
|
-
}
|
225
|
-
}
|
226
|
-
]
|
227
|
-
}
|
223
|
+
bosh: /\A#<Object:.+>\z/,
|
224
|
+
},
|
225
|
+
},
|
226
|
+
],
|
227
|
+
},
|
228
228
|
},
|
229
|
-
123
|
230
|
-
]
|
231
|
-
)
|
229
|
+
123,
|
230
|
+
],
|
231
|
+
),
|
232
232
|
)
|
233
233
|
end
|
234
234
|
end
|
@@ -245,12 +245,12 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
|
|
245
245
|
|
246
246
|
it "appends thread inspect (self)" do
|
247
247
|
subject.call(notice)
|
248
|
-
expect(notice[:params][:thread][:self]).to match(/\A#<Thread
|
248
|
+
expect(notice[:params][:thread][:self]).to match(/\A#<Thread:.+>\z/)
|
249
249
|
end
|
250
250
|
|
251
251
|
it "appends thread group" do
|
252
252
|
subject.call(notice)
|
253
|
-
expect(notice[:params][:thread][:group][0]).to match(/\A#<Thread
|
253
|
+
expect(notice[:params][:thread][:group][0]).to match(/\A#<Thread:.+>\z/)
|
254
254
|
end
|
255
255
|
|
256
256
|
it "appends priority" do
|
@@ -258,7 +258,9 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
|
|
258
258
|
expect(notice[:params][:thread][:priority]).to eq(0)
|
259
259
|
end
|
260
260
|
|
261
|
-
it "appends safe_level", skip:
|
261
|
+
it "appends safe_level", skip: (
|
262
|
+
"Not supported on this version of Ruby." unless Airbrake::HAS_SAFE_LEVEL
|
263
|
+
) do
|
262
264
|
subject.call(notice)
|
263
265
|
expect(notice[:params][:thread][:safe_level]).to eq(0)
|
264
266
|
end
|