sentry-raven 3.0.1 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.craft.yml +2 -1
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  4. data/.github/pull_request_template.md +16 -0
  5. data/.github/workflows/test.yml +41 -26
  6. data/.github/workflows/zeus_upload.yml +32 -0
  7. data/.gitignore +1 -0
  8. data/.rubocop.yml +6 -3
  9. data/{changelog.md → CHANGELOG.md} +157 -7
  10. data/CONTRIBUTING.md +71 -0
  11. data/Gemfile +5 -2
  12. data/README.md +29 -14
  13. data/lib/raven/backtrace.rb +2 -0
  14. data/lib/raven/base.rb +2 -0
  15. data/lib/raven/breadcrumbs/active_support_logger.rb +25 -0
  16. data/lib/raven/breadcrumbs/logger.rb +2 -92
  17. data/lib/raven/breadcrumbs/sentry_logger.rb +73 -0
  18. data/lib/raven/cli.rb +8 -19
  19. data/lib/raven/client.rb +1 -1
  20. data/lib/raven/configuration.rb +81 -5
  21. data/lib/raven/context.rb +13 -8
  22. data/lib/raven/core_ext/object/deep_dup.rb +57 -0
  23. data/lib/raven/core_ext/object/duplicable.rb +153 -0
  24. data/lib/raven/event.rb +23 -13
  25. data/lib/raven/helpers/deprecation_helper.rb +17 -0
  26. data/lib/raven/instance.rb +10 -1
  27. data/lib/raven/integrations/delayed_job.rb +2 -1
  28. data/lib/raven/integrations/rack-timeout.rb +5 -1
  29. data/lib/raven/integrations/rack.rb +15 -2
  30. data/lib/raven/integrations/rails.rb +12 -3
  31. data/lib/raven/integrations/rails/active_job.rb +2 -1
  32. data/lib/raven/integrations/rails/backtrace_cleaner.rb +29 -0
  33. data/lib/raven/integrations/sidekiq.rb +4 -78
  34. data/lib/raven/integrations/sidekiq/cleanup_middleware.rb +13 -0
  35. data/lib/raven/integrations/sidekiq/error_handler.rb +38 -0
  36. data/lib/raven/processor/cookies.rb +1 -1
  37. data/lib/raven/processor/removecircularreferences.rb +2 -1
  38. data/lib/raven/transports/http.rb +0 -2
  39. data/lib/raven/utils/context_filter.rb +42 -0
  40. data/lib/raven/version.rb +1 -1
  41. data/lib/sentry-raven-without-integrations.rb +6 -1
  42. data/lib/sentry_raven_without_integrations.rb +1 -0
  43. data/sentry-ruby/.gitignore +11 -0
  44. data/sentry-ruby/.rspec +3 -0
  45. data/sentry-ruby/.travis.yml +6 -0
  46. data/sentry-ruby/CODE_OF_CONDUCT.md +74 -0
  47. data/sentry-ruby/Gemfile +9 -0
  48. data/sentry-ruby/LICENSE.txt +21 -0
  49. data/sentry-ruby/README.md +44 -0
  50. data/sentry-ruby/Rakefile +6 -0
  51. data/sentry-ruby/bin/console +14 -0
  52. data/sentry-ruby/bin/setup +8 -0
  53. data/sentry-ruby/examples/rails-6.0/.browserslistrc +1 -0
  54. data/sentry-ruby/examples/rails-6.0/.gitignore +35 -0
  55. data/sentry-ruby/examples/rails-6.0/Gemfile +58 -0
  56. data/sentry-ruby/examples/rails-6.0/README.md +23 -0
  57. data/sentry-ruby/examples/rails-6.0/Rakefile +6 -0
  58. data/sentry-ruby/examples/rails-6.0/app/assets/config/manifest.js +2 -0
  59. data/sentry-ruby/examples/rails-6.0/app/assets/images/.keep +0 -0
  60. data/sentry-ruby/examples/rails-6.0/app/assets/stylesheets/application.css +15 -0
  61. data/sentry-ruby/examples/rails-6.0/app/channels/application_cable/channel.rb +4 -0
  62. data/sentry-ruby/examples/rails-6.0/app/channels/application_cable/connection.rb +4 -0
  63. data/sentry-ruby/examples/rails-6.0/app/controllers/application_controller.rb +2 -0
  64. data/sentry-ruby/examples/rails-6.0/app/controllers/concerns/.keep +0 -0
  65. data/sentry-ruby/examples/rails-6.0/app/controllers/welcome_controller.rb +23 -0
  66. data/sentry-ruby/examples/rails-6.0/app/helpers/application_helper.rb +2 -0
  67. data/sentry-ruby/examples/rails-6.0/app/javascript/channels/consumer.js +6 -0
  68. data/sentry-ruby/examples/rails-6.0/app/javascript/channels/index.js +5 -0
  69. data/sentry-ruby/examples/rails-6.0/app/javascript/packs/application.js +17 -0
  70. data/sentry-ruby/examples/rails-6.0/app/jobs/application_job.rb +7 -0
  71. data/sentry-ruby/examples/rails-6.0/app/mailers/application_mailer.rb +4 -0
  72. data/sentry-ruby/examples/rails-6.0/app/models/application_record.rb +3 -0
  73. data/sentry-ruby/examples/rails-6.0/app/models/concerns/.keep +0 -0
  74. data/sentry-ruby/examples/rails-6.0/app/views/layouts/application.html.erb +15 -0
  75. data/sentry-ruby/examples/rails-6.0/app/views/layouts/mailer.html.erb +13 -0
  76. data/sentry-ruby/examples/rails-6.0/app/views/layouts/mailer.text.erb +1 -0
  77. data/sentry-ruby/examples/rails-6.0/app/views/welcome/report_demo.html.erb +22 -0
  78. data/sentry-ruby/examples/rails-6.0/app/views/welcome/view_error.html.erb +1 -0
  79. data/sentry-ruby/examples/rails-6.0/app/workers/error_worker.rb +7 -0
  80. data/sentry-ruby/examples/rails-6.0/babel.config.js +72 -0
  81. data/sentry-ruby/examples/rails-6.0/bin/bundle +114 -0
  82. data/sentry-ruby/examples/rails-6.0/bin/rails +9 -0
  83. data/sentry-ruby/examples/rails-6.0/bin/rake +9 -0
  84. data/sentry-ruby/examples/rails-6.0/bin/setup +36 -0
  85. data/sentry-ruby/examples/rails-6.0/bin/spring +17 -0
  86. data/sentry-ruby/examples/rails-6.0/bin/webpack +18 -0
  87. data/sentry-ruby/examples/rails-6.0/bin/webpack-dev-server +18 -0
  88. data/sentry-ruby/examples/rails-6.0/bin/yarn +11 -0
  89. data/sentry-ruby/examples/rails-6.0/config.ru +5 -0
  90. data/sentry-ruby/examples/rails-6.0/config/application.rb +28 -0
  91. data/sentry-ruby/examples/rails-6.0/config/boot.rb +4 -0
  92. data/sentry-ruby/examples/rails-6.0/config/cable.yml +10 -0
  93. data/sentry-ruby/examples/rails-6.0/config/credentials.yml.enc +1 -0
  94. data/sentry-ruby/examples/rails-6.0/config/database.yml +25 -0
  95. data/sentry-ruby/examples/rails-6.0/config/environment.rb +5 -0
  96. data/sentry-ruby/examples/rails-6.0/config/environments/development.rb +62 -0
  97. data/sentry-ruby/examples/rails-6.0/config/environments/production.rb +112 -0
  98. data/sentry-ruby/examples/rails-6.0/config/environments/test.rb +48 -0
  99. data/sentry-ruby/examples/rails-6.0/config/initializers/application_controller_renderer.rb +8 -0
  100. data/sentry-ruby/examples/rails-6.0/config/initializers/assets.rb +14 -0
  101. data/sentry-ruby/examples/rails-6.0/config/initializers/backtrace_silencers.rb +7 -0
  102. data/sentry-ruby/examples/rails-6.0/config/initializers/content_security_policy.rb +30 -0
  103. data/sentry-ruby/examples/rails-6.0/config/initializers/cookies_serializer.rb +5 -0
  104. data/sentry-ruby/examples/rails-6.0/config/initializers/filter_parameter_logging.rb +4 -0
  105. data/sentry-ruby/examples/rails-6.0/config/initializers/inflections.rb +16 -0
  106. data/sentry-ruby/examples/rails-6.0/config/initializers/mime_types.rb +4 -0
  107. data/sentry-ruby/examples/rails-6.0/config/initializers/wrap_parameters.rb +14 -0
  108. data/sentry-ruby/examples/rails-6.0/config/locales/en.yml +33 -0
  109. data/sentry-ruby/examples/rails-6.0/config/puma.rb +38 -0
  110. data/sentry-ruby/examples/rails-6.0/config/routes.rb +10 -0
  111. data/sentry-ruby/examples/rails-6.0/config/spring.rb +6 -0
  112. data/sentry-ruby/examples/rails-6.0/config/storage.yml +34 -0
  113. data/sentry-ruby/examples/rails-6.0/config/webpack/development.js +5 -0
  114. data/sentry-ruby/examples/rails-6.0/config/webpack/environment.js +3 -0
  115. data/sentry-ruby/examples/rails-6.0/config/webpack/production.js +5 -0
  116. data/sentry-ruby/examples/rails-6.0/config/webpack/test.js +5 -0
  117. data/sentry-ruby/examples/rails-6.0/config/webpacker.yml +96 -0
  118. data/sentry-ruby/examples/rails-6.0/db/seeds.rb +7 -0
  119. data/sentry-ruby/examples/rails-6.0/lib/assets/.keep +0 -0
  120. data/sentry-ruby/examples/rails-6.0/lib/tasks/.keep +0 -0
  121. data/sentry-ruby/examples/rails-6.0/package.json +15 -0
  122. data/sentry-ruby/examples/rails-6.0/postcss.config.js +12 -0
  123. data/sentry-ruby/examples/rails-6.0/public/404.html +67 -0
  124. data/sentry-ruby/examples/rails-6.0/public/422.html +67 -0
  125. data/sentry-ruby/examples/rails-6.0/public/500.html +66 -0
  126. data/sentry-ruby/examples/rails-6.0/public/apple-touch-icon-precomposed.png +0 -0
  127. data/sentry-ruby/examples/rails-6.0/public/apple-touch-icon.png +0 -0
  128. data/sentry-ruby/examples/rails-6.0/public/favicon.ico +0 -0
  129. data/sentry-ruby/examples/rails-6.0/public/robots.txt +1 -0
  130. data/sentry-ruby/examples/rails-6.0/storage/.keep +0 -0
  131. data/sentry-ruby/examples/rails-6.0/test/application_system_test_case.rb +5 -0
  132. data/sentry-ruby/examples/rails-6.0/test/channels/application_cable/connection_test.rb +11 -0
  133. data/sentry-ruby/examples/rails-6.0/test/controllers/.keep +0 -0
  134. data/sentry-ruby/examples/rails-6.0/test/fixtures/.keep +0 -0
  135. data/sentry-ruby/examples/rails-6.0/test/fixtures/files/.keep +0 -0
  136. data/sentry-ruby/examples/rails-6.0/test/helpers/.keep +0 -0
  137. data/sentry-ruby/examples/rails-6.0/test/integration/.keep +0 -0
  138. data/sentry-ruby/examples/rails-6.0/test/mailers/.keep +0 -0
  139. data/sentry-ruby/examples/rails-6.0/test/models/.keep +0 -0
  140. data/sentry-ruby/examples/rails-6.0/test/system/.keep +0 -0
  141. data/sentry-ruby/examples/rails-6.0/test/test_helper.rb +13 -0
  142. data/sentry-ruby/examples/rails-6.0/vendor/.keep +0 -0
  143. data/sentry-ruby/examples/rails-6.0/yarn.lock +7508 -0
  144. data/sentry-ruby/lib/sentry.rb +16 -0
  145. data/sentry-ruby/lib/sentry/backtrace.rb +128 -0
  146. data/sentry-ruby/lib/sentry/client.rb +162 -0
  147. data/sentry-ruby/lib/sentry/client/state.rb +40 -0
  148. data/sentry-ruby/lib/sentry/configuration.rb +533 -0
  149. data/sentry-ruby/lib/sentry/event.rb +209 -0
  150. data/sentry-ruby/lib/sentry/interface.rb +31 -0
  151. data/sentry-ruby/lib/sentry/interfaces/exception.rb +15 -0
  152. data/sentry-ruby/lib/sentry/interfaces/http.rb +16 -0
  153. data/sentry-ruby/lib/sentry/interfaces/message.rb +18 -0
  154. data/sentry-ruby/lib/sentry/interfaces/single_exception.rb +14 -0
  155. data/sentry-ruby/lib/sentry/interfaces/stack_trace.rb +69 -0
  156. data/sentry-ruby/lib/sentry/linecache.rb +44 -0
  157. data/sentry-ruby/lib/sentry/logger.rb +20 -0
  158. data/sentry-ruby/lib/sentry/transports.rb +19 -0
  159. data/sentry-ruby/lib/sentry/transports/dummy.rb +16 -0
  160. data/sentry-ruby/lib/sentry/transports/http.rb +66 -0
  161. data/sentry-ruby/lib/sentry/transports/stdout.rb +20 -0
  162. data/sentry-ruby/lib/sentry/utils/deep_merge.rb +22 -0
  163. data/sentry-ruby/lib/sentry/utils/exception_cause_chain.rb +20 -0
  164. data/sentry-ruby/lib/sentry/version.rb +3 -0
  165. data/sentry-ruby/sentry-ruby.gemspec +26 -0
  166. data/sentry-ruby/spec/sentry/backtrace_spec.rb +38 -0
  167. data/sentry-ruby/spec/sentry/client_spec.rb +443 -0
  168. data/sentry-ruby/spec/sentry/configuration_spec.rb +400 -0
  169. data/sentry-ruby/spec/sentry/event_spec.rb +238 -0
  170. data/sentry-ruby/spec/sentry/interface_spec.rb +38 -0
  171. data/sentry-ruby/spec/sentry/interfaces/stack_trace_spec.rb +11 -0
  172. data/sentry-ruby/spec/sentry/linecache_spec.rb +40 -0
  173. data/sentry-ruby/spec/sentry/transports/http_spec.rb +57 -0
  174. data/sentry-ruby/spec/sentry/transports/stdout_spec.rb +11 -0
  175. data/sentry-ruby/spec/sentry_spec.rb +9 -0
  176. data/sentry-ruby/spec/spec_helper.rb +49 -0
  177. data/sentry-ruby/spec/support/linecache.txt +6 -0
  178. metadata +152 -4
  179. data/lib/raven/breadcrumbs/activesupport.rb +0 -19
@@ -0,0 +1,400 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Sentry::Configuration do
4
+ before do
5
+ # Make sure we reset the env in case something leaks in
6
+ ENV.delete('SENTRY_DSN')
7
+ ENV.delete('SENTRY_CURRENT_ENV')
8
+ ENV.delete('SENTRY_ENVIRONMENT')
9
+ ENV.delete('SENTRY_RELEASE')
10
+ ENV.delete('RAILS_ENV')
11
+ ENV.delete('RACK_ENV')
12
+ end
13
+
14
+ it "should set some attributes when server is set" do
15
+ subject.server = "http://12345:67890@sentry.localdomain:3000/sentry/42"
16
+
17
+ expect(subject.project_id).to eq("42")
18
+ expect(subject.public_key).to eq("12345")
19
+ expect(subject.secret_key).to eq("67890")
20
+
21
+ expect(subject.scheme).to eq("http")
22
+ expect(subject.host).to eq("sentry.localdomain")
23
+ expect(subject.port).to eq(3000)
24
+ expect(subject.path).to eq("/sentry")
25
+
26
+ expect(subject.server).to eq("http://sentry.localdomain:3000/sentry")
27
+ end
28
+
29
+ describe "#breadcrumbs_logger=" do
30
+ it "raises error when given an invalid option" do
31
+ expect { subject.breadcrumbs_logger = :foo }.to raise_error(
32
+ Sentry::Error,
33
+ 'Unsupported breadcrumbs logger. Supported loggers: [:sentry_logger, :active_support_logger]'
34
+ )
35
+ end
36
+ end
37
+
38
+ it "doesnt accept invalid encodings" do
39
+ expect { subject.encoding = "apple" }.to raise_error(Sentry::Error, 'Unsupported encoding')
40
+ end
41
+
42
+ it "has hashlike attribute accessors" do
43
+ expect(subject.encoding).to eq("gzip")
44
+ expect(subject[:encoding]).to eq("gzip")
45
+ end
46
+
47
+ context 'configuring for async' do
48
+ it 'should be configurable to send events async' do
49
+ subject.async = ->(_e) { :ok }
50
+ expect(subject.async.call('event')).to eq(:ok)
51
+ end
52
+
53
+ it 'should raise when setting async to anything other than callable or false' do
54
+ subject.transport_failure_callback = -> {}
55
+ subject.transport_failure_callback = false
56
+ expect { subject.async = true }.to raise_error(ArgumentError)
57
+ end
58
+ end
59
+
60
+ it 'should raise when setting transport_failure_callback to anything other than callable or false' do
61
+ subject.transport_failure_callback = -> {}
62
+ subject.transport_failure_callback = false
63
+ expect { subject.transport_failure_callback = true }.to raise_error(ArgumentError)
64
+ end
65
+
66
+ it 'should raise when setting should_capture to anything other than callable or false' do
67
+ subject.should_capture = -> {}
68
+ subject.should_capture = false
69
+ expect { subject.should_capture = true }.to raise_error(ArgumentError)
70
+ end
71
+
72
+ it 'should raise when setting before_send to anything other than callable or false' do
73
+ subject.before_send = -> {}
74
+ subject.before_send = false
75
+ expect { subject.before_send = true }.to raise_error(ArgumentError)
76
+ end
77
+
78
+ context 'being initialized with a current environment' do
79
+ before(:each) do
80
+ subject.current_environment = 'test'
81
+ subject.server = 'http://12345:67890@sentry.localdomain:3000/sentry/42'
82
+ end
83
+
84
+ it 'should send events if test is whitelisted' do
85
+ subject.environments = %w(test)
86
+ subject.capture_allowed?
87
+ puts subject.errors
88
+ expect(subject.capture_allowed?).to eq(true)
89
+ end
90
+
91
+ it 'should not send events if test is not whitelisted' do
92
+ subject.environments = %w(not_test)
93
+ expect(subject.capture_allowed?).to eq(false)
94
+ expect(subject.errors).to eq(["Not configured to send/capture in environment 'test'"])
95
+ end
96
+ end
97
+
98
+ context 'being initialized without a current environment' do
99
+ after do
100
+ ENV.delete('SENTRY_CURRENT_ENV')
101
+ ENV.delete('SENTRY_ENVIRONMENT')
102
+ ENV.delete('RAILS_ENV')
103
+ ENV.delete('RACK_ENV')
104
+ end
105
+
106
+ it 'defaults to "default"' do
107
+ expect(subject.current_environment).to eq('default')
108
+ end
109
+
110
+ it 'uses `SENTRY_CURRENT_ENV` env variable' do
111
+ ENV['SENTRY_CURRENT_ENV'] = 'set-with-sentry-current-env'
112
+ ENV['SENTRY_ENVIRONMENT'] = 'set-with-sentry-environment'
113
+ ENV['RAILS_ENV'] = 'set-with-rails-env'
114
+ ENV['RACK_ENV'] = 'set-with-rack-env'
115
+
116
+ expect(subject.current_environment).to eq('set-with-sentry-current-env')
117
+ end
118
+
119
+ it 'uses `SENTRY_ENVIRONMENT` env variable' do
120
+ ENV['SENTRY_ENVIRONMENT'] = 'set-with-sentry-environment'
121
+ ENV['RAILS_ENV'] = 'set-with-rails-env'
122
+ ENV['RACK_ENV'] = 'set-with-rack-env'
123
+
124
+ expect(subject.current_environment).to eq('set-with-sentry-environment')
125
+ end
126
+
127
+ it 'uses `RAILS_ENV` env variable' do
128
+ ENV['SENTRY_CURRENT_ENV'] = nil
129
+ ENV['RAILS_ENV'] = 'set-with-rails-env'
130
+ ENV['RACK_ENV'] = 'set-with-rack-env'
131
+
132
+ expect(subject.current_environment).to eq('set-with-rails-env')
133
+ end
134
+
135
+ it 'uses `RACK_ENV` env variable' do
136
+ ENV['SENTRY_CURRENT_ENV'] = nil
137
+ ENV['RAILS_ENV'] = nil
138
+ ENV['RACK_ENV'] = 'set-with-rack-env'
139
+
140
+ expect(subject.current_environment).to eq('set-with-rack-env')
141
+ end
142
+ end
143
+
144
+ context 'being initialized without a release' do
145
+ let(:fake_root) { "/tmp/sentry/" }
146
+
147
+ before do
148
+ allow(File).to receive(:directory?).and_return(false)
149
+ allow_any_instance_of(described_class).to receive(:project_root).and_return(fake_root)
150
+ end
151
+
152
+ it 'defaults to nil' do
153
+ expect(subject.release).to eq(nil)
154
+ end
155
+
156
+ it 'uses `SENTRY_RELEASE` env variable' do
157
+ ENV['SENTRY_RELEASE'] = 'v1'
158
+
159
+ expect(subject.release).to eq('v1')
160
+
161
+ ENV.delete('SENTRY_CURRENT_ENV')
162
+ end
163
+
164
+ context "when git is available" do
165
+ before do
166
+ allow(File).to receive(:directory?).and_return(false)
167
+ allow(File).to receive(:directory?).with(".git").and_return(true)
168
+ end
169
+ it 'gets release from git' do
170
+ allow(Sentry).to receive(:`).with("git rev-parse --short HEAD 2>&1").and_return("COMMIT_SHA")
171
+
172
+ expect(subject.release).to eq('COMMIT_SHA')
173
+ end
174
+ end
175
+
176
+ context "when Capistrano is available" do
177
+ let(:revision) { "2019010101000" }
178
+
179
+ before do
180
+ Dir.mkdir(fake_root) unless Dir.exist?(fake_root)
181
+ File.write(filename, file_content)
182
+ end
183
+
184
+ after do
185
+ File.delete(filename)
186
+ Dir.delete(fake_root)
187
+ end
188
+
189
+ context "when the REVISION file is present" do
190
+ let(:filename) do
191
+ File.join(fake_root, "REVISION")
192
+ end
193
+ let(:file_content) { revision }
194
+
195
+ it "gets release from the REVISION file" do
196
+ expect(subject.release).to eq(revision)
197
+ end
198
+ end
199
+
200
+ context "when the revisions.log file is present" do
201
+ let(:filename) do
202
+ File.join(fake_root, "..", "revisions.log")
203
+ end
204
+ let(:file_content) do
205
+ "Branch master (at COMMIT_SHA) deployed as release #{revision} by alice"
206
+ end
207
+
208
+ it "gets release from the REVISION file" do
209
+ expect(subject.release).to eq(revision)
210
+ end
211
+ end
212
+ end
213
+
214
+ context "when running on heroku" do
215
+ before do
216
+ allow(File).to receive(:directory?).and_return(false)
217
+ allow(File).to receive(:directory?).with("/etc/heroku").and_return(true)
218
+ end
219
+
220
+ context "when it's on heroku ci" do
221
+ it "returns nil" do
222
+ begin
223
+ original_ci_val = ENV["CI"]
224
+ ENV["CI"] = "true"
225
+
226
+ expect(subject.release).to eq(nil)
227
+ ensure
228
+ ENV["CI"] = original_ci_val
229
+ end
230
+ end
231
+ end
232
+
233
+ context "when it's not on heroku ci" do
234
+ around do |example|
235
+ begin
236
+ original_ci_val = ENV["CI"]
237
+ ENV["CI"] = nil
238
+
239
+ example.run
240
+ ensure
241
+ ENV["CI"] = original_ci_val
242
+ end
243
+ end
244
+
245
+ it "returns nil + logs an warning if HEROKU_SLUG_COMMIT is not set" do
246
+ logger = double("logger")
247
+ expect(::Sentry::Logger).to receive(:new).and_return(logger)
248
+ expect(logger).to receive(:warn).with(described_class::HEROKU_DYNO_METADATA_MESSAGE)
249
+
250
+ expect(described_class.new.release).to eq(nil)
251
+ end
252
+
253
+ it "returns HEROKU_SLUG_COMMIT" do
254
+ begin
255
+ ENV["HEROKU_SLUG_COMMIT"] = "REVISION"
256
+
257
+ expect(subject.release).to eq("REVISION")
258
+ ensure
259
+ ENV["HEROKU_SLUG_COMMIT"] = nil
260
+ end
261
+ end
262
+ end
263
+ end
264
+ end
265
+
266
+ describe "config: backtrace_cleanup_callback" do
267
+ it "defaults to nil" do
268
+ expect(subject.backtrace_cleanup_callback).to eq(nil)
269
+ end
270
+
271
+ it "takes a proc and store it" do
272
+ subject.backtrace_cleanup_callback = proc {}
273
+
274
+ expect(subject.backtrace_cleanup_callback).to be_a(Proc)
275
+ end
276
+ end
277
+
278
+ context 'with a should_capture callback configured' do
279
+ before(:each) do
280
+ subject.should_capture = ->(exc_or_msg) { exc_or_msg != "dont send me" }
281
+ subject.server = 'http://12345:67890@sentry.localdomain:3000/sentry/42'
282
+ end
283
+
284
+ it 'should not send events if should_capture returns false' do
285
+ expect(subject.capture_allowed?("dont send me")).to eq(false)
286
+ expect(subject.errors).to eq(["should_capture returned false"])
287
+ expect(subject.capture_allowed?("send me")).to eq(true)
288
+ end
289
+ end
290
+
291
+ context "with an invalid server" do
292
+ before(:each) do
293
+ subject.server = 'dummy://trololo'
294
+ end
295
+
296
+ it 'captured_allowed returns false' do
297
+ expect(subject.capture_allowed?).to eq(false)
298
+ expect(subject.errors).to eq(["No public_key specified", "No project_id specified"])
299
+ end
300
+ end
301
+
302
+ context "with the new Sentry 9 DSN format" do
303
+ # Basically the same as before, without a secret
304
+ before(:each) do
305
+ subject.server = "https://66260460f09b5940498e24bb7ce093a0@sentry.io/42"
306
+ end
307
+
308
+ it 'captured_allowed is true' do
309
+ expect(subject.capture_allowed?).to eq(true)
310
+ end
311
+
312
+ it "sets the DSN in the way we expect" do
313
+ expect(subject.dsn).to eq("https://66260460f09b5940498e24bb7ce093a0@sentry.io/42")
314
+ expect(subject.server).to eq("https://sentry.io")
315
+ expect(subject.project_id).to eq("42")
316
+ expect(subject.public_key).to eq("66260460f09b5940498e24bb7ce093a0")
317
+ expect(subject.secret_key).to be_nil
318
+ end
319
+ end
320
+
321
+ context "with a sample rate" do
322
+ before(:each) do
323
+ subject.server = 'http://12345:67890@sentry.localdomain:3000/sentry/42'
324
+ subject.sample_rate = 0.75
325
+ end
326
+
327
+ it 'captured_allowed false when sampled' do
328
+ allow(Random::DEFAULT).to receive(:rand).and_return(0.76)
329
+ expect(subject.capture_allowed?).to eq(false)
330
+ expect(subject.errors).to eq(["Excluded by random sample"])
331
+ end
332
+
333
+ it 'captured_allowed true when not sampled' do
334
+ allow(Random::DEFAULT).to receive(:rand).and_return(0.74)
335
+ expect(subject.capture_allowed?).to eq(true)
336
+ end
337
+ end
338
+
339
+ describe '#exception_class_allowed?' do
340
+ class MyTestException < RuntimeError; end
341
+
342
+ context 'with custom excluded_exceptions' do
343
+ before do
344
+ subject.excluded_exceptions = ['MyTestException']
345
+ end
346
+
347
+ context 'when the raised exception is a Sentry::Error' do
348
+ let(:incoming_exception) { Sentry::Error.new }
349
+ it 'returns false' do
350
+ expect(subject.exception_class_allowed?(incoming_exception)).to eq false
351
+ end
352
+ end
353
+
354
+ context 'when the raised exception is not in excluded_exceptions' do
355
+ let(:incoming_exception) { RuntimeError.new }
356
+ it 'returns true' do
357
+ expect(subject.exception_class_allowed?(incoming_exception)).to eq true
358
+ end
359
+ end
360
+
361
+ context 'when the raised exception has a cause that is in excluded_exceptions' do
362
+ let(:incoming_exception) { build_exception_with_cause(MyTestException.new) }
363
+ context 'when inspect_exception_causes_for_exclusion is false' do
364
+ it 'returns true' do
365
+ expect(subject.exception_class_allowed?(incoming_exception)).to eq true
366
+ end
367
+ end
368
+
369
+ # Only check causes when they're supported by the ruby version
370
+ context 'when inspect_exception_causes_for_exclusion is true' do
371
+ before do
372
+ subject.inspect_exception_causes_for_exclusion = true
373
+ end
374
+
375
+ if Exception.new.respond_to? :cause
376
+ context 'when the language version supports exception causes' do
377
+ it 'returns false' do
378
+ expect(subject.exception_class_allowed?(incoming_exception)).to eq false
379
+ end
380
+ end
381
+ else
382
+ context 'when the language version does not support exception causes' do
383
+ it 'returns true' do
384
+ expect(subject.exception_class_allowed?(incoming_exception)).to eq true
385
+ end
386
+ end
387
+ end
388
+ end
389
+ end
390
+
391
+ context 'when the raised exception is in excluded_exceptions' do
392
+ let(:incoming_exception) { MyTestException.new }
393
+
394
+ it 'returns false' do
395
+ expect(subject.exception_class_allowed?(incoming_exception)).to eq false
396
+ end
397
+ end
398
+ end
399
+ end
400
+ end
@@ -0,0 +1,238 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Sentry::Event do
4
+ let(:configuration) { Sentry::Configuration.new }
5
+ let(:essential_options) do
6
+ {
7
+ configuration: configuration
8
+ }
9
+ end
10
+
11
+ describe "#initialize" do
12
+ it "initializes a Event when all required keys are provided" do
13
+ expect(described_class.new(essential_options)).to be_a(described_class)
14
+ end
15
+ end
16
+
17
+ context 'a fully implemented event' do
18
+ let(:hash) do
19
+ Sentry::Event.new(
20
+ configuration: configuration,
21
+ message: 'test',
22
+ level: 'warn',
23
+ tags: {
24
+ 'foo' => 'bar'
25
+ },
26
+ extra: {
27
+ 'my_custom_variable' => 'value'
28
+ },
29
+ server_name: 'foo.local',
30
+ release: '721e41770371db95eee98ca2707686226b993eda',
31
+ environment: 'production'
32
+ ).to_hash
33
+ end
34
+
35
+ it 'has message' do
36
+ expect(hash[:message]).to eq('test')
37
+ end
38
+
39
+ it 'has level' do
40
+ expect(hash[:level]).to eq(:warning)
41
+ end
42
+
43
+ it 'has server name' do
44
+ expect(hash[:server_name]).to eq('foo.local')
45
+ end
46
+
47
+ it 'has release' do
48
+ expect(hash[:release]).to eq('721e41770371db95eee98ca2707686226b993eda')
49
+ end
50
+
51
+ it 'has environment' do
52
+ expect(hash[:environment]).to eq('production')
53
+ end
54
+
55
+ it 'has tag data' do
56
+ expect(hash[:tags]).to eq('foo' => 'bar')
57
+ end
58
+
59
+ it 'has extra data' do
60
+ expect(hash[:extra]["my_custom_variable"]).to eq('value')
61
+ end
62
+
63
+ it 'has platform' do
64
+ expect(hash[:platform]).to eq(:ruby)
65
+ end
66
+
67
+ it 'has SDK' do
68
+ expect(hash[:sdk]).to eq("name" => "sentry-ruby", "version" => Sentry::VERSION)
69
+ end
70
+
71
+ it 'has server os' do
72
+ expect(hash[:extra][:server][:os].keys).to eq([:name, :version, :build, :kernel_version])
73
+ end
74
+
75
+ it 'has runtime' do
76
+ expect(hash[:extra][:server][:runtime][:version]).to match(/ruby/)
77
+ end
78
+ end
79
+
80
+ context 'parameter entries are nil' do
81
+ let(:hash) do
82
+ Sentry::Event.new(
83
+ message: 'test',
84
+ level: 'warn',
85
+ tags: nil,
86
+ extra: nil,
87
+ user: nil,
88
+ server_name: 'foo.local',
89
+ release: '721e41770371db95eee98ca2707686226b993eda',
90
+ environment: 'production',
91
+ configuration: configuration
92
+ ).to_hash
93
+ end
94
+
95
+ it "skips nil values" do
96
+ expect(hash[:extra]).to eq({})
97
+ expect(hash[:user]).to eq({})
98
+ expect(hash[:tags]).to eq({})
99
+ end
100
+ end
101
+
102
+ context 'configuration tags specified' do
103
+ let(:hash) do
104
+ config = Sentry::Configuration.new
105
+ config.tags = { 'key' => 'value' }
106
+ config.release = "custom"
107
+ config.current_environment = "custom"
108
+
109
+ Sentry::Event.new(
110
+ level: 'warning',
111
+ tags: {
112
+ 'foo' => 'bar'
113
+ },
114
+ server_name: 'foo.local',
115
+ configuration: config,
116
+ ).to_hash
117
+ end
118
+
119
+ it 'merges tags data' do
120
+ expect(hash[:tags]).to eq('key' => 'value',
121
+ 'foo' => 'bar')
122
+ expect(hash[:release]).to eq("custom")
123
+ expect(hash[:environment]).to eq("custom")
124
+ end
125
+
126
+ it 'does not persist tags between unrelated events' do
127
+ config = Sentry::Configuration.new
128
+ config.logger = Logger.new(nil)
129
+
130
+ Sentry::Event.new(
131
+ level: 'warning',
132
+ tags: {
133
+ 'foo' => 'bar'
134
+ },
135
+ server_name: 'foo.local',
136
+ configuration: config
137
+ )
138
+
139
+ hash = Sentry::Event.new(
140
+ level: 'warning',
141
+ server_name: 'foo.local',
142
+ configuration: config
143
+ ).to_hash
144
+
145
+ expect(hash[:tags]).to eq({})
146
+ end
147
+ end
148
+
149
+ # context 'tags hierarchy respected' do
150
+ # let(:hash) do
151
+ # config = Sentry::Configuration.new
152
+ # config.logger = Logger.new(nil)
153
+ # config.tags = {
154
+ # 'configuration_context_event_key' => 'configuration_value',
155
+ # 'configuration_context_key' => 'configuration_value',
156
+ # 'configuration_event_key' => 'configuration_value',
157
+ # 'configuration_key' => 'configuration_value'
158
+ # }
159
+
160
+ # Sentry.tags_context('configuration_context_event_key' => 'context_value',
161
+ # 'configuration_context_key' => 'context_value',
162
+ # 'context_event_key' => 'context_value',
163
+ # 'context_key' => 'context_value')
164
+
165
+ # Sentry::Event.new(
166
+ # level: 'warning',
167
+ # logger: 'foo',
168
+ # tags: {
169
+ # 'configuration_context_event_key' => 'event_value',
170
+ # 'configuration_event_key' => 'event_value',
171
+ # 'context_event_key' => 'event_value',
172
+ # 'event_key' => 'event_value'
173
+ # },
174
+ # server_name: 'foo.local',
175
+ # configuration: config
176
+ # ).to_hash
177
+ # end
178
+
179
+ # it 'merges tags data' do
180
+ # expect(hash[:tags]).to eq('configuration_context_event_key' => 'event_value',
181
+ # 'configuration_context_key' => 'context_value',
182
+ # 'configuration_event_key' => 'event_value',
183
+ # 'context_event_key' => 'event_value',
184
+ # 'configuration_key' => 'configuration_value',
185
+ # 'context_key' => 'context_value',
186
+ # 'event_key' => 'event_value')
187
+ # end
188
+ # end
189
+
190
+ describe '#to_json_compatible' do
191
+ subject do
192
+ Sentry::Event.new(
193
+ extra: {
194
+ 'my_custom_variable' => 'value',
195
+ 'date' => Time.utc(0),
196
+ 'anonymous_module' => Class.new
197
+ },
198
+ configuration: configuration
199
+ )
200
+ end
201
+
202
+ it "should coerce non-JSON-compatible types" do
203
+ json = subject.to_json_compatible
204
+
205
+ expect(json["extra"]['my_custom_variable']).to eq('value')
206
+ expect(json["extra"]['date']).to be_a(String)
207
+ expect(json["extra"]['anonymous_module']).not_to be_a(Class)
208
+ end
209
+
210
+ # context "with bad data" do
211
+ # subject do
212
+ # data = {}
213
+ # data['data'] = data
214
+ # data['ary'] = []
215
+ # data['ary'].push('x' => data['ary'])
216
+ # data['ary2'] = data['ary']
217
+
218
+ # Sentry::Event.new(extra: {
219
+ # invalid: "invalid\255".dup.force_encoding('UTF-8'),
220
+ # circular: data
221
+ # },
222
+ # configuration: configuration)
223
+ # end
224
+
225
+ # it "should remove bad UTF-8" do
226
+ # json = subject.to_json_compatible
227
+
228
+ # expect(json["extra"]["invalid"]).to eq("invalid")
229
+ # end
230
+
231
+ # it "should remove circular references" do
232
+ # json = subject.to_json_compatible
233
+
234
+ # expect(json["extra"]["circular"]["ary2"]).to eq("(...)")
235
+ # end
236
+ # end
237
+ end
238
+ end