sentry-ruby 6.7.0 → 7.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 +4 -4
- data/gemfiles/ruby-2.7_rack-2_redis-4.gemfile.lock +7 -7
- data/gemfiles/ruby-2.7_rack-3.1_redis-4.gemfile.lock +7 -7
- data/gemfiles/ruby-2.7_rack-3_redis-4.gemfile.lock +7 -7
- data/gemfiles/ruby-3.0_rack-2_redis-4.gemfile.lock +8 -8
- data/gemfiles/ruby-3.0_rack-3.1_redis-4.gemfile.lock +8 -8
- data/gemfiles/ruby-3.0_rack-3_redis-4.gemfile.lock +8 -8
- data/gemfiles/ruby-3.1_rack-2_redis-4.gemfile.lock +16 -16
- data/gemfiles/ruby-3.1_rack-3.1_redis-4.gemfile.lock +16 -16
- data/gemfiles/ruby-3.1_rack-3_redis-4.gemfile.lock +16 -16
- data/gemfiles/ruby-3.2_rack-0_redis-5.gemfile.lock +16 -16
- data/gemfiles/ruby-3.2_rack-2_redis-4.gemfile.lock +18 -18
- data/gemfiles/ruby-3.2_rack-2_redis-5.gemfile.lock +18 -18
- data/gemfiles/ruby-3.2_rack-3.1_redis-4.gemfile.lock +18 -18
- data/gemfiles/ruby-3.2_rack-3_redis-4.gemfile.lock +18 -18
- data/gemfiles/ruby-3.2_rack-3_redis-5.gemfile.lock +18 -18
- data/gemfiles/ruby-3.3_rack-2_redis-4.gemfile.lock +22 -22
- data/gemfiles/ruby-3.3_rack-3.1_redis-4.gemfile.lock +22 -22
- data/gemfiles/ruby-3.3_rack-3.1_redis-5.3.gemfile.lock +22 -22
- data/gemfiles/ruby-3.3_rack-3_redis-4.gemfile.lock +22 -22
- data/gemfiles/ruby-3.4_rack-2_redis-4.gemfile.lock +22 -22
- data/gemfiles/ruby-3.4_rack-3.1_redis-4.gemfile.lock +22 -22
- data/gemfiles/ruby-3.4_rack-3.1_redis-5.3.gemfile.lock +22 -22
- data/gemfiles/ruby-3.4_rack-3_redis-4.gemfile.lock +22 -22
- data/gemfiles/ruby-4.0_rack-2_redis-4.gemfile.lock +22 -22
- data/gemfiles/ruby-4.0_rack-3.1_redis-4.gemfile.lock +22 -22
- data/gemfiles/ruby-4.0_rack-3_redis-4.gemfile.lock +22 -22
- data/gemfiles/ruby-jruby-9.4.14.0_rack-2_redis-4.gemfile.lock +14 -14
- data/gemfiles/ruby-jruby-9.4.14.0_rack-3.1_redis-4.gemfile.lock +14 -14
- data/gemfiles/ruby-jruby-9.4.14.0_rack-3_redis-4.gemfile.lock +14 -14
- data/lib/sentry/client.rb +2 -6
- data/lib/sentry/configuration.rb +34 -12
- data/lib/sentry/data_collection/key_value_collection.rb +136 -0
- data/lib/sentry/data_collection.rb +203 -0
- data/lib/sentry/debug_structured_logger.rb +2 -15
- data/lib/sentry/error_event.rb +6 -1
- data/lib/sentry/event.rb +8 -4
- data/lib/sentry/excon/middleware.rb +3 -8
- data/lib/sentry/faraday.rb +3 -4
- data/lib/sentry/hub.rb +2 -2
- data/lib/sentry/interfaces/exception.rb +8 -2
- data/lib/sentry/interfaces/request.rb +42 -46
- data/lib/sentry/interfaces/single_exception.rb +2 -2
- data/lib/sentry/net/http.rb +3 -4
- data/lib/sentry/redis.rb +1 -1
- data/lib/sentry/std_lib_logger.rb +2 -6
- data/lib/sentry/test_helper.rb +2 -4
- data/lib/sentry/utils/http_tracing.rb +42 -26
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +4 -18
- metadata +8 -6
|
@@ -6,7 +6,7 @@ GIT
|
|
|
6
6
|
PATH
|
|
7
7
|
remote: ..
|
|
8
8
|
specs:
|
|
9
|
-
sentry-ruby (6.
|
|
9
|
+
sentry-ruby (6.7.0)
|
|
10
10
|
bigdecimal
|
|
11
11
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
12
12
|
logger
|
|
@@ -70,14 +70,14 @@ GEM
|
|
|
70
70
|
faraday-net_http (3.4.4)
|
|
71
71
|
net-http (~> 0.5)
|
|
72
72
|
fiber-storage (1.0.1)
|
|
73
|
-
graphql (2.6.
|
|
73
|
+
graphql (2.6.9)
|
|
74
74
|
base64
|
|
75
75
|
fiber-storage
|
|
76
76
|
logger
|
|
77
77
|
hashdiff (1.2.1)
|
|
78
78
|
i18n (1.15.2)
|
|
79
79
|
concurrent-ruby (~> 1.0)
|
|
80
|
-
io-console (0.
|
|
80
|
+
io-console (0.9.2-java)
|
|
81
81
|
irb (1.18.0)
|
|
82
82
|
pp (>= 0.6.0)
|
|
83
83
|
prism (>= 1.3.0)
|
|
@@ -97,20 +97,20 @@ GEM
|
|
|
97
97
|
prettyprint
|
|
98
98
|
prettyprint (0.2.0)
|
|
99
99
|
prism (1.9.0)
|
|
100
|
-
psych (5.
|
|
100
|
+
psych (5.5.0-java)
|
|
101
101
|
date
|
|
102
102
|
jar-dependencies (>= 0.1.7)
|
|
103
103
|
public_suffix (6.0.2)
|
|
104
104
|
puma (8.0.2-java)
|
|
105
105
|
nio4r (~> 2.0)
|
|
106
|
-
rack (3.2.
|
|
106
|
+
rack (3.2.7)
|
|
107
107
|
rake (12.3.3)
|
|
108
108
|
rdoc (7.2.0)
|
|
109
109
|
erb
|
|
110
110
|
psych (>= 4.0.0)
|
|
111
111
|
tsort
|
|
112
112
|
redis (4.8.1)
|
|
113
|
-
reline (0.
|
|
113
|
+
reline (0.7.0)
|
|
114
114
|
io-console (~> 0.5)
|
|
115
115
|
rexml (3.4.1)
|
|
116
116
|
rspec (3.13.2)
|
|
@@ -146,7 +146,7 @@ GEM
|
|
|
146
146
|
tzinfo (2.0.6)
|
|
147
147
|
concurrent-ruby (~> 1.0)
|
|
148
148
|
uri (1.1.1)
|
|
149
|
-
webmock (3.26.
|
|
149
|
+
webmock (3.26.3)
|
|
150
150
|
addressable (>= 2.8.0)
|
|
151
151
|
crack (>= 0.3.2)
|
|
152
152
|
hashdiff (>= 0.4.0, < 2.0.0)
|
|
@@ -214,10 +214,10 @@ CHECKSUMS
|
|
|
214
214
|
faraday (2.14.3) sha256=1882247e6766615c8220b4392bf1d27f6ebb63d8e28267587cef1fb0bf37f278
|
|
215
215
|
faraday-net_http (3.4.4) sha256=0e78af151747ed1b00f33e25973b4bc220d7f16c00c39676817c8b12331eb588
|
|
216
216
|
fiber-storage (1.0.1) sha256=f48e5b6d8b0be96dac486332b55cee82240057065dc761c1ea692b2e719240e1
|
|
217
|
-
graphql (2.6.
|
|
217
|
+
graphql (2.6.9) sha256=afe7bc03164f1a61abc66a415744ffd315c5aca116c9f3438c57391a431e4fe5
|
|
218
218
|
hashdiff (1.2.1) sha256=9c079dbc513dfc8833ab59c0c2d8f230fa28499cc5efb4b8dd276cf931457cd1
|
|
219
219
|
i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5
|
|
220
|
-
io-console (0.
|
|
220
|
+
io-console (0.9.2-java) sha256=929c09163ad227cda17f5dc57861b995dbecf69c7ca2ce7b0c5f941f1f3da7d3
|
|
221
221
|
irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3
|
|
222
222
|
jar-dependencies (0.5.7) sha256=013ce5f4639414ac8cf1169cdbe763da164b81e2d2c983d11042b5ff7bfcce80
|
|
223
223
|
jdbc-mysql (8.4.0.1) sha256=429cb7999d11c4f46a7153a382b6ac07935a4c10ddc52dd98e2d52b22c17fa13
|
|
@@ -231,14 +231,14 @@ CHECKSUMS
|
|
|
231
231
|
pp (0.6.4) sha256=dfcb0fce700c41456265922884f9fe195d7fbb0674a3578e6c0f69588e82b570
|
|
232
232
|
prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
|
|
233
233
|
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
|
|
234
|
-
psych (5.
|
|
234
|
+
psych (5.5.0-java) sha256=3b7cf3684c44d049c3dee87ec4118ec9cd6ac714cbdcfba386997f96dbbd36ab
|
|
235
235
|
public_suffix (6.0.2) sha256=bfa7cd5108066f8c9602e0d6d4114999a5df5839a63149d3e8b0f9c1d3558394
|
|
236
236
|
puma (8.0.2-java) sha256=37392e0dbd01e2a157748b92b818bfacf801bb32628e41680e9ab1171dea2b3d
|
|
237
|
-
rack (3.2.
|
|
237
|
+
rack (3.2.7) sha256=93e13e1c24f93556671d85d2d79fa228c3485815c50d7e2f265b5330c6528fb7
|
|
238
238
|
rake (12.3.3) sha256=f7694adb4fe638da35452300cee6c545e9c377a0e3190018ac04d590b3c26ab3
|
|
239
239
|
rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192
|
|
240
240
|
redis (4.8.1) sha256=387ee086694fffc9632aaeb1efe4a7b1627ca783bf373320346a8a20cd93333a
|
|
241
|
-
reline (0.
|
|
241
|
+
reline (0.7.0) sha256=5b012d8e55dbf9d450f12bde2cf7d15ff546ae80b3f8f3b30e570d431815583d
|
|
242
242
|
rexml (3.4.1) sha256=c74527a9a0a04b4ec31dbe0dc4ed6004b960af943d8db42e539edde3a871abca
|
|
243
243
|
rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
|
|
244
244
|
rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
|
|
@@ -247,7 +247,7 @@ CHECKSUMS
|
|
|
247
247
|
rspec-retry (0.6.2) sha256=6101ba23a38809811ae3484acde4ab481c54d846ac66d5037ccb40131a60d858
|
|
248
248
|
rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
|
|
249
249
|
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
|
|
250
|
-
sentry-ruby (6.
|
|
250
|
+
sentry-ruby (6.7.0)
|
|
251
251
|
sequel (5.107.0) sha256=019629313205295b007f6df2c5eab19ddc40710d549fd445ac300f2853a370db
|
|
252
252
|
simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
|
|
253
253
|
simplecov-cobertura (3.2.0) sha256=70d702658677fcb20e5aceb6915ccf8bc62ff2ccd38b62b3ad5c9db5c0888740
|
|
@@ -258,7 +258,7 @@ CHECKSUMS
|
|
|
258
258
|
tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
|
|
259
259
|
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
|
|
260
260
|
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
|
|
261
|
-
webmock (3.26.
|
|
261
|
+
webmock (3.26.3) sha256=77c612816bdcb2fc43db0e42fd98b19be7d4770fd708816fdde65a006664ddec
|
|
262
262
|
webrick (1.9.2) sha256=beb4a15fc474defed24a3bda4ffd88a490d517c9e4e6118c3edce59e45864131
|
|
263
263
|
yard (0.9.45) sha256=52e211493f7cb8a3ebf7e104a25a1e73937a3103092545d34cb88fafebb3dc51
|
|
264
264
|
|
data/lib/sentry/client.rb
CHANGED
|
@@ -48,13 +48,9 @@ module Sentry
|
|
|
48
48
|
|
|
49
49
|
@spotlight_transport = SpotlightTransport.new(configuration) if configuration.spotlight
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
@log_event_buffer = LogEventBuffer.new(configuration, self)
|
|
53
|
-
end
|
|
51
|
+
@log_event_buffer = LogEventBuffer.new(configuration, self)
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
@metric_event_buffer = MetricEventBuffer.new(configuration, self)
|
|
57
|
-
end
|
|
53
|
+
@metric_event_buffer = MetricEventBuffer.new(configuration, self)
|
|
58
54
|
end
|
|
59
55
|
|
|
60
56
|
# Applies the given scope's data to the event and sends it to Sentry.
|
data/lib/sentry/configuration.rb
CHANGED
|
@@ -16,6 +16,7 @@ require "sentry/logger"
|
|
|
16
16
|
require "sentry/structured_logger"
|
|
17
17
|
require "sentry/log_event_buffer"
|
|
18
18
|
require "sentry/metric_event_buffer"
|
|
19
|
+
require "sentry/data_collection"
|
|
19
20
|
|
|
20
21
|
module Sentry
|
|
21
22
|
class Configuration
|
|
@@ -132,6 +133,7 @@ module Sentry
|
|
|
132
133
|
attr_accessor :max_breadcrumbs
|
|
133
134
|
|
|
134
135
|
# Number of lines of code context to capture, or nil for none
|
|
136
|
+
# @deprecated Use {#data_collection} and `frame_context_lines` instead.
|
|
135
137
|
# @return [Integer, nil]
|
|
136
138
|
attr_accessor :context_lines
|
|
137
139
|
|
|
@@ -167,8 +169,14 @@ module Sentry
|
|
|
167
169
|
alias inspect_exception_causes_for_exclusion? inspect_exception_causes_for_exclusion
|
|
168
170
|
|
|
169
171
|
# Whether to capture local variables from the raised exception's frame. Default is false.
|
|
172
|
+
# @deprecated Use {#data_collection} and `stack_frame_variables` instead.
|
|
170
173
|
# @return [Boolean]
|
|
171
|
-
|
|
174
|
+
attr_reader :include_local_variables
|
|
175
|
+
|
|
176
|
+
def include_local_variables=(value)
|
|
177
|
+
@include_local_variables = value
|
|
178
|
+
@data_collection.backfill_stack_frame_variables(self)
|
|
179
|
+
end
|
|
172
180
|
|
|
173
181
|
# Whether to capture events and traces into Spotlight. Default is false.
|
|
174
182
|
# If you set this to true, Sentry will send events and traces to the local
|
|
@@ -209,6 +217,7 @@ module Sentry
|
|
|
209
217
|
attr_accessor :propagate_traces
|
|
210
218
|
|
|
211
219
|
# Array of rack env parameters to be included in the event sent to sentry.
|
|
220
|
+
# @deprecated Use `data_collection.http_headers.request` to control request data collection instead.
|
|
212
221
|
# @return [Array<String>]
|
|
213
222
|
attr_accessor :rack_env_whitelist
|
|
214
223
|
|
|
@@ -232,8 +241,14 @@ module Sentry
|
|
|
232
241
|
# - request body
|
|
233
242
|
# - query string
|
|
234
243
|
# will not be sent to Sentry.
|
|
244
|
+
# @deprecated Use {#data_collection} instead.
|
|
235
245
|
# @return [Boolean]
|
|
236
|
-
|
|
246
|
+
attr_reader :send_default_pii
|
|
247
|
+
|
|
248
|
+
# Controls which categories of data may be collected.
|
|
249
|
+
# Replacement for send_default_pii.
|
|
250
|
+
# @return [DataCollection]
|
|
251
|
+
attr_accessor :data_collection
|
|
237
252
|
|
|
238
253
|
# Capture queue time from X-Request-Start header set by reverse proxies.
|
|
239
254
|
# Works with any Rack app behind Nginx, HAProxy, Heroku router, etc.
|
|
@@ -273,10 +288,6 @@ module Sentry
|
|
|
273
288
|
# @return [Proc]
|
|
274
289
|
attr_accessor :traces_sampler
|
|
275
290
|
|
|
276
|
-
# Enable Structured Logging
|
|
277
|
-
# @return [Boolean]
|
|
278
|
-
attr_accessor :enable_logs
|
|
279
|
-
|
|
280
291
|
# Structured logging configuration.
|
|
281
292
|
# @return [StructuredLoggingConfiguration]
|
|
282
293
|
attr_reader :structured_logging
|
|
@@ -345,10 +356,6 @@ module Sentry
|
|
|
345
356
|
# @return [Integer]
|
|
346
357
|
attr_accessor :max_log_events
|
|
347
358
|
|
|
348
|
-
# Enable metrics collection, defaults to true
|
|
349
|
-
# @return [Boolean]
|
|
350
|
-
attr_accessor :enable_metrics
|
|
351
|
-
|
|
352
359
|
# Maximum number of metric events to buffer before sending
|
|
353
360
|
# @return [Integer]
|
|
354
361
|
attr_accessor :max_metric_events
|
|
@@ -527,6 +534,7 @@ module Sentry
|
|
|
527
534
|
def initialize
|
|
528
535
|
run_callbacks(:before, :initialize)
|
|
529
536
|
|
|
537
|
+
self.data_collection = DataCollection.new
|
|
530
538
|
self.app_dirs_pattern = APP_DIRS_PATTERN
|
|
531
539
|
self.debug = Sentry::Utils::EnvHelper.env_to_bool(ENV["SENTRY_DEBUG"])
|
|
532
540
|
self.background_worker_threads = (processor_count / 2.0).ceil
|
|
@@ -537,6 +545,7 @@ module Sentry
|
|
|
537
545
|
self.breadcrumbs_logger = []
|
|
538
546
|
self.context_lines = 3
|
|
539
547
|
self.include_local_variables = false
|
|
548
|
+
|
|
540
549
|
self.environment = environment_from_env
|
|
541
550
|
self.enabled_environments = nil
|
|
542
551
|
self.exclude_loggers = []
|
|
@@ -578,8 +587,6 @@ module Sentry
|
|
|
578
587
|
self.std_lib_logger_filter = nil
|
|
579
588
|
self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
|
|
580
589
|
self.traces_sampler = nil
|
|
581
|
-
self.enable_logs = false
|
|
582
|
-
self.enable_metrics = true
|
|
583
590
|
|
|
584
591
|
self.profiler_class = Sentry::Profiler
|
|
585
592
|
self.profiles_sample_interval = DEFAULT_PROFILES_SAMPLE_INTERVAL
|
|
@@ -596,6 +603,8 @@ module Sentry
|
|
|
596
603
|
|
|
597
604
|
yield(self) if block_given?
|
|
598
605
|
|
|
606
|
+
log_deprecations
|
|
607
|
+
|
|
599
608
|
run_callbacks(:after, :configured)
|
|
600
609
|
end
|
|
601
610
|
|
|
@@ -621,6 +630,11 @@ module Sentry
|
|
|
621
630
|
@dsn = init_dsn(value)
|
|
622
631
|
end
|
|
623
632
|
|
|
633
|
+
def send_default_pii=(value)
|
|
634
|
+
@send_default_pii = value
|
|
635
|
+
self.data_collection = DataCollection.backfill(self)
|
|
636
|
+
end
|
|
637
|
+
|
|
624
638
|
alias server= dsn=
|
|
625
639
|
|
|
626
640
|
def release=(value)
|
|
@@ -804,6 +818,14 @@ module Sentry
|
|
|
804
818
|
end
|
|
805
819
|
end
|
|
806
820
|
|
|
821
|
+
# @api private
|
|
822
|
+
def log_deprecations
|
|
823
|
+
log_warn("`send_default_pii` is deprecated; use `data_collection` instead.") if self.send_default_pii
|
|
824
|
+
log_warn("`include_local_variables` is deprecated; use `data_collection.stack_frame_variables` instead.") if include_local_variables
|
|
825
|
+
log_warn("`context_lines` is deprecated; use `data_collection.frame_context_lines` instead.") if context_lines != 3
|
|
826
|
+
log_warn("`rack_env_whitelist` is deprecated; use `data_collection.http_headers.request` to control request data collection instead.") if rack_env_whitelist != RACK_ENV_WHITELIST_DEFAULT
|
|
827
|
+
end
|
|
828
|
+
|
|
807
829
|
# @api private
|
|
808
830
|
def stacktrace_builder
|
|
809
831
|
@stacktrace_builder ||= StacktraceBuilder.new(
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sentry
|
|
4
|
+
class DataCollection
|
|
5
|
+
# Configuration for key-value data collection.
|
|
6
|
+
class KeyValueCollection
|
|
7
|
+
FILTERED_VALUE = "[Filtered]"
|
|
8
|
+
|
|
9
|
+
# Keys from this list are ALWAYS filtered, regardless of :mode
|
|
10
|
+
SENSITIVE_DENY_LIST = %w[
|
|
11
|
+
auth
|
|
12
|
+
token
|
|
13
|
+
secret
|
|
14
|
+
session
|
|
15
|
+
password
|
|
16
|
+
passwd
|
|
17
|
+
pwd
|
|
18
|
+
key
|
|
19
|
+
jwt
|
|
20
|
+
bearer
|
|
21
|
+
sso
|
|
22
|
+
saml
|
|
23
|
+
csrf
|
|
24
|
+
xsrf
|
|
25
|
+
credentials
|
|
26
|
+
sid
|
|
27
|
+
identity
|
|
28
|
+
cookie
|
|
29
|
+
set-cookie
|
|
30
|
+
].freeze
|
|
31
|
+
|
|
32
|
+
# Additional terms applied to cookie names only. These cover common
|
|
33
|
+
# opaque session, identity-provider, and load-balancer cookies without
|
|
34
|
+
# making the general header denylist overly broad.
|
|
35
|
+
SENSITIVE_COOKIE_NAME_DENY_LIST = %w[
|
|
36
|
+
.sid
|
|
37
|
+
sessid
|
|
38
|
+
remember
|
|
39
|
+
oidc
|
|
40
|
+
pkce
|
|
41
|
+
nonce
|
|
42
|
+
__secure-
|
|
43
|
+
__host-
|
|
44
|
+
awsalb
|
|
45
|
+
awselb
|
|
46
|
+
akamai
|
|
47
|
+
__stripe
|
|
48
|
+
cognito
|
|
49
|
+
firebase
|
|
50
|
+
supabase
|
|
51
|
+
sb-
|
|
52
|
+
mfa
|
|
53
|
+
2fa
|
|
54
|
+
].freeze
|
|
55
|
+
|
|
56
|
+
# `mode` controls whether values are collected:
|
|
57
|
+
# - `:off` disables collection.
|
|
58
|
+
# - `:deny_list` collects values except those matching `terms`.
|
|
59
|
+
# - `:allow_list` collects only values matching `terms`.
|
|
60
|
+
# Boolean values are accepted as shorthand for `:deny_list` and `:off`.
|
|
61
|
+
# @return [:off, :deny_list, :allow_list]
|
|
62
|
+
attr_reader :mode
|
|
63
|
+
|
|
64
|
+
# `terms` contains the keys or patterns used by the selected mode.
|
|
65
|
+
# @return [Array<String, Regexp>, nil]
|
|
66
|
+
attr_reader :terms
|
|
67
|
+
|
|
68
|
+
def initialize(mode:, terms:)
|
|
69
|
+
self.mode = mode
|
|
70
|
+
self.terms = terms
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def mode=(mode)
|
|
74
|
+
@mode = case mode
|
|
75
|
+
when true then :deny_list
|
|
76
|
+
when false, nil then :off
|
|
77
|
+
else mode
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Converts the boolean shorthand into a collection configuration.
|
|
82
|
+
def self.from(value)
|
|
83
|
+
return new(mode: value, terms: nil) if value.equal?(true) || value.equal?(false) || value.nil?
|
|
84
|
+
|
|
85
|
+
value
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def terms=(terms)
|
|
89
|
+
@terms = terms&.map { |term| term.is_a?(Regexp) ? term : term.to_s.downcase }
|
|
90
|
+
&.reject { |term| !term.is_a?(Regexp) && term.strip.empty? }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Applies this collection configuration without changing the input hash.
|
|
94
|
+
# Keys are retained whenever the category is collected; values that are not
|
|
95
|
+
# safe to send are replaced with FILTERED_VALUE.
|
|
96
|
+
#
|
|
97
|
+
# @param values [Hash] key-value data to filter
|
|
98
|
+
# @return [Hash] a new filtered hash, or an empty hash when collection is off
|
|
99
|
+
def filter(values, cookie: false)
|
|
100
|
+
return {} if mode == :off
|
|
101
|
+
|
|
102
|
+
values.each_with_object({}) do |(key, value), filtered|
|
|
103
|
+
filtered[key] = safe_value?(key, cookie: cookie) ? value : FILTERED_VALUE
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
def safe_value?(key, cookie: false)
|
|
110
|
+
key_string = key.to_s
|
|
111
|
+
key_downcase = key_string.downcase
|
|
112
|
+
return false if sensitive?(key_downcase, cookie: cookie)
|
|
113
|
+
|
|
114
|
+
case mode
|
|
115
|
+
when :deny_list
|
|
116
|
+
!matches_any_term?(key_string, key_downcase)
|
|
117
|
+
when :allow_list
|
|
118
|
+
matches_any_term?(key_string, key_downcase)
|
|
119
|
+
else
|
|
120
|
+
false
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def sensitive?(key, cookie: false)
|
|
125
|
+
SENSITIVE_DENY_LIST.any? { |term| key.include?(term) } ||
|
|
126
|
+
(cookie && SENSITIVE_COOKIE_NAME_DENY_LIST.any? { |term| key.include?(term) })
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def matches_any_term?(key, key_downcase)
|
|
130
|
+
@terms&.any? do |term|
|
|
131
|
+
term.is_a?(Regexp) ? term.match?(key) : key_downcase.include?(term)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "sentry/data_collection/key_value_collection"
|
|
4
|
+
|
|
5
|
+
module Sentry
|
|
6
|
+
class DataCollection
|
|
7
|
+
# Configuration for the categories of data collected by the SDK.
|
|
8
|
+
# Replacement for send_default_pii.
|
|
9
|
+
# Spec: https://develop.sentry.dev/sdk/foundations/client/data-collection/
|
|
10
|
+
#
|
|
11
|
+
# @example Configure data collection
|
|
12
|
+
# Sentry.init do |config|
|
|
13
|
+
# data_collection = config.data_collection
|
|
14
|
+
# data_collection.user_info = true
|
|
15
|
+
# data_collection.cookies.mode = :deny_list
|
|
16
|
+
# data_collection.cookies.terms = ["session", "token"]
|
|
17
|
+
# data_collection.http_headers.request.mode = :deny_list
|
|
18
|
+
# data_collection.http_headers.request.terms = nil
|
|
19
|
+
# data_collection.http_headers.response.mode = :allow_list
|
|
20
|
+
# data_collection.http_headers.response.terms = ["my_special_header"]
|
|
21
|
+
# data_collection.http_bodies = [:incoming_request]
|
|
22
|
+
# data_collection.url_query_params.mode = :allow_list
|
|
23
|
+
# data_collection.url_query_params.terms = ["page", "limit"]
|
|
24
|
+
# data_collection.graphql.document = true
|
|
25
|
+
# data_collection.graphql.variables = true
|
|
26
|
+
# data_collection.database_query_data = true
|
|
27
|
+
# data_collection.queues = true
|
|
28
|
+
# data_collection.stack_frame_variables = true
|
|
29
|
+
# data_collection.frame_context_lines = 5
|
|
30
|
+
# end
|
|
31
|
+
|
|
32
|
+
MODES = %i[off deny_list allow_list].freeze
|
|
33
|
+
|
|
34
|
+
PII_HEADER_SNIPPETS = %w[forwarded -ip _ip remote via _user -user].freeze
|
|
35
|
+
|
|
36
|
+
BODY_TYPES = %i[
|
|
37
|
+
incoming_request
|
|
38
|
+
outgoing_request
|
|
39
|
+
incoming_response
|
|
40
|
+
outgoing_response
|
|
41
|
+
].freeze
|
|
42
|
+
|
|
43
|
+
class HttpHeaders
|
|
44
|
+
# @return [KeyValueCollection]
|
|
45
|
+
attr_reader :request
|
|
46
|
+
|
|
47
|
+
# @return [KeyValueCollection]
|
|
48
|
+
attr_reader :response
|
|
49
|
+
|
|
50
|
+
def initialize(request:, response:)
|
|
51
|
+
self.request = request
|
|
52
|
+
self.response = response
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def request=(value)
|
|
56
|
+
@request = KeyValueCollection.from(value)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def response=(value)
|
|
60
|
+
@response = KeyValueCollection.from(value)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class GraphQL
|
|
65
|
+
# @return [Boolean]
|
|
66
|
+
attr_accessor :document
|
|
67
|
+
|
|
68
|
+
# @return [Boolean]
|
|
69
|
+
attr_accessor :variables
|
|
70
|
+
|
|
71
|
+
def initialize(document:, variables:)
|
|
72
|
+
@document = document
|
|
73
|
+
@variables = variables
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# @return [Boolean]
|
|
78
|
+
# @default `true`
|
|
79
|
+
attr_accessor :user_info
|
|
80
|
+
|
|
81
|
+
# @return [Boolean, KeyValueCollection]
|
|
82
|
+
# A boolean is shorthand for `mode: :deny_list` (`true`) or `mode: :off` (`false`).
|
|
83
|
+
# @default `mode: :deny_list, terms: nil`
|
|
84
|
+
attr_reader :cookies
|
|
85
|
+
|
|
86
|
+
# @return [HttpHeaders]
|
|
87
|
+
# @default request and response use `mode: :deny_list, terms: nil`
|
|
88
|
+
attr_accessor :http_headers
|
|
89
|
+
|
|
90
|
+
# @return [Array<Symbol>] containing values from BODY_TYPES
|
|
91
|
+
# @default `nil` (all valid body types)
|
|
92
|
+
attr_accessor :http_bodies
|
|
93
|
+
|
|
94
|
+
# @return [Boolean, KeyValueCollection]
|
|
95
|
+
# A boolean is shorthand for `mode: :deny_list` (`true`) or `mode: :off` (`false`).
|
|
96
|
+
# @default `mode: :deny_list, terms: nil`
|
|
97
|
+
attr_reader :url_query_params
|
|
98
|
+
|
|
99
|
+
# @return [Boolean]
|
|
100
|
+
# @default `true`
|
|
101
|
+
attr_accessor :database_query_data
|
|
102
|
+
|
|
103
|
+
# @return [GraphQL]
|
|
104
|
+
# @default `document: true, variables: true`
|
|
105
|
+
attr_accessor :graphql
|
|
106
|
+
|
|
107
|
+
# @return [Boolean]
|
|
108
|
+
# @default `true`
|
|
109
|
+
attr_accessor :queues
|
|
110
|
+
|
|
111
|
+
# @return [Boolean, KeyValueCollection]
|
|
112
|
+
# A boolean is shorthand for `mode: :deny_list` (`true`) or `mode: :off` (`false`).
|
|
113
|
+
# @default `false` (Ruby-specific to avoid TracePoint overhead)
|
|
114
|
+
attr_reader :stack_frame_variables
|
|
115
|
+
|
|
116
|
+
# @return [Integer]
|
|
117
|
+
# @default `3`
|
|
118
|
+
attr_accessor :frame_context_lines
|
|
119
|
+
|
|
120
|
+
# Filters key-value data using the default sensitive denylist.
|
|
121
|
+
def self.filter(values)
|
|
122
|
+
default_filter.filter(values, cookie: false)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def self.default_filter
|
|
126
|
+
@default_filter ||= KeyValueCollection.new(mode: :deny_list, terms: nil)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Builds data collection settings compatible with the legacy send_default_pii
|
|
130
|
+
# configuration.
|
|
131
|
+
def self.backfill(configuration)
|
|
132
|
+
data_collection = new
|
|
133
|
+
data_collection.backfill_stack_frame_variables(configuration)
|
|
134
|
+
return data_collection if configuration.send_default_pii
|
|
135
|
+
|
|
136
|
+
# TODO-neel-data map to exact ruby behaviour for backwards compat behavior
|
|
137
|
+
data_collection.user_info = false
|
|
138
|
+
data_collection.cookies.mode = :off
|
|
139
|
+
data_collection.http_headers.request.mode = :deny_list
|
|
140
|
+
data_collection.http_headers.request.terms = PII_HEADER_SNIPPETS
|
|
141
|
+
data_collection.http_headers.response.mode = :deny_list
|
|
142
|
+
data_collection.http_headers.response.terms = PII_HEADER_SNIPPETS
|
|
143
|
+
data_collection.http_bodies = []
|
|
144
|
+
data_collection.url_query_params.mode = :off
|
|
145
|
+
data_collection.graphql.document = false
|
|
146
|
+
data_collection.graphql.variables = false
|
|
147
|
+
data_collection.database_query_data = false
|
|
148
|
+
data_collection.queues = false
|
|
149
|
+
data_collection.frame_context_lines = configuration.context_lines
|
|
150
|
+
data_collection
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def initialize
|
|
154
|
+
@user_info = true
|
|
155
|
+
self.cookies = KeyValueCollection.new(mode: :deny_list, terms: nil)
|
|
156
|
+
@http_headers = HttpHeaders.new(
|
|
157
|
+
request: KeyValueCollection.new(mode: :deny_list, terms: nil),
|
|
158
|
+
response: KeyValueCollection.new(mode: :deny_list, terms: nil)
|
|
159
|
+
)
|
|
160
|
+
@http_bodies = BODY_TYPES.dup
|
|
161
|
+
self.url_query_params = KeyValueCollection.new(mode: :deny_list, terms: nil)
|
|
162
|
+
@database_query_data = true
|
|
163
|
+
@graphql = GraphQL.new(document: true, variables: true)
|
|
164
|
+
@queues = true
|
|
165
|
+
self.stack_frame_variables = false
|
|
166
|
+
@frame_context_lines = 3
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Copies the legacy stack frame variable configuration.
|
|
170
|
+
def backfill_stack_frame_variables(configuration)
|
|
171
|
+
self.stack_frame_variables = configuration.include_local_variables
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Returns whether stack frame local variables should be captured.
|
|
175
|
+
def collect_stack_frame_variables?
|
|
176
|
+
stack_frame_variables.mode != :off
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def stack_frame_variables=(value)
|
|
180
|
+
@stack_frame_variables = KeyValueCollection.from(value)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def cookies=(value)
|
|
184
|
+
@cookies = KeyValueCollection.from(value)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def url_query_params=(value)
|
|
188
|
+
@url_query_params = KeyValueCollection.from(value)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Returns whether incoming HTTP request bodies should be collected.
|
|
192
|
+
# nil implies all BODY_TYPES according to spec
|
|
193
|
+
def collect_incoming_http_body?
|
|
194
|
+
http_bodies.nil? || http_bodies.include?(:incoming_request)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Returns whether outgoing HTTP request bodies should be collected.
|
|
198
|
+
# nil implies all BODY_TYPES according to spec
|
|
199
|
+
def collect_outgoing_http_body?
|
|
200
|
+
http_bodies.nil? || http_bodies.include?(:outgoing_request)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
@@ -8,8 +8,7 @@ require "delegate"
|
|
|
8
8
|
module Sentry
|
|
9
9
|
# DebugStructuredLogger is a logger that captures structured log events to a file for debugging purposes.
|
|
10
10
|
#
|
|
11
|
-
# It
|
|
12
|
-
# is enabled.
|
|
11
|
+
# It also sends log events to Sentry via the normal structured logger.
|
|
13
12
|
class DebugStructuredLogger < SimpleDelegator
|
|
14
13
|
DEFAULT_LOG_FILE_PATH = File.join("log", "sentry_debug_logs.log")
|
|
15
14
|
|
|
@@ -68,12 +67,7 @@ module Sentry
|
|
|
68
67
|
private
|
|
69
68
|
|
|
70
69
|
def initialize_backend(configuration)
|
|
71
|
-
|
|
72
|
-
StructuredLogger.new(configuration)
|
|
73
|
-
else
|
|
74
|
-
# Create a no-op logger if logging is disabled
|
|
75
|
-
NoOpLogger.new
|
|
76
|
-
end
|
|
70
|
+
StructuredLogger.new(configuration)
|
|
77
71
|
end
|
|
78
72
|
|
|
79
73
|
def initialize_log_file(log_file_path)
|
|
@@ -83,12 +77,5 @@ module Sentry
|
|
|
83
77
|
|
|
84
78
|
log_file
|
|
85
79
|
end
|
|
86
|
-
|
|
87
|
-
# No-op logger for when structured logging is disabled
|
|
88
|
-
class NoOpLogger
|
|
89
|
-
%i[trace debug info warn error fatal log].each do |method|
|
|
90
|
-
define_method(method) { |*args, **kwargs| nil }
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
80
|
end
|
|
94
81
|
end
|
data/lib/sentry/error_event.rb
CHANGED
|
@@ -32,7 +32,12 @@ module Sentry
|
|
|
32
32
|
@extra.merge!(exception.sentry_context)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
@exception = Sentry::ExceptionInterface.build(
|
|
35
|
+
@exception = Sentry::ExceptionInterface.build(
|
|
36
|
+
exception: exception,
|
|
37
|
+
stacktrace_builder: @stacktrace_builder,
|
|
38
|
+
mechanism: mechanism,
|
|
39
|
+
data_collection: @data_collection
|
|
40
|
+
)
|
|
36
41
|
end
|
|
37
42
|
end
|
|
38
43
|
end
|
data/lib/sentry/event.rb
CHANGED
|
@@ -28,7 +28,7 @@ module Sentry
|
|
|
28
28
|
|
|
29
29
|
MAX_MESSAGE_SIZE_IN_BYTES = 1024 * 8
|
|
30
30
|
|
|
31
|
-
SKIP_INSPECTION_ATTRIBUTES = [:@modules, :@stacktrace_builder, :@
|
|
31
|
+
SKIP_INSPECTION_ATTRIBUTES = [:@modules, :@stacktrace_builder, :@data_collection, :@trusted_proxies, :@rack_env_whitelist]
|
|
32
32
|
|
|
33
33
|
include CustomInspection
|
|
34
34
|
|
|
@@ -73,7 +73,7 @@ module Sentry
|
|
|
73
73
|
@modules = configuration.gem_specs if configuration.send_modules
|
|
74
74
|
|
|
75
75
|
# configuration options to help events process data
|
|
76
|
-
@
|
|
76
|
+
@data_collection = configuration.data_collection
|
|
77
77
|
@trusted_proxies = configuration.trusted_proxies
|
|
78
78
|
@stacktrace_builder = configuration.stacktrace_builder
|
|
79
79
|
@rack_env_whitelist = configuration.rack_env_whitelist
|
|
@@ -103,7 +103,7 @@ module Sentry
|
|
|
103
103
|
unless request || env.empty?
|
|
104
104
|
add_request_interface(env)
|
|
105
105
|
|
|
106
|
-
user[:ip_address] ||= calculate_real_ip_from_rack(env) if @
|
|
106
|
+
user[:ip_address] ||= calculate_real_ip_from_rack(env) if @data_collection.user_info
|
|
107
107
|
|
|
108
108
|
if request_id = Utils::RequestId.read_from(env)
|
|
109
109
|
tags[:request_id] = request_id
|
|
@@ -127,7 +127,11 @@ module Sentry
|
|
|
127
127
|
private
|
|
128
128
|
|
|
129
129
|
def add_request_interface(env)
|
|
130
|
-
@request = Sentry::RequestInterface.new(
|
|
130
|
+
@request = Sentry::RequestInterface.new(
|
|
131
|
+
env: env,
|
|
132
|
+
data_collection: @data_collection,
|
|
133
|
+
rack_env_whitelist: @rack_env_whitelist
|
|
134
|
+
)
|
|
131
135
|
end
|
|
132
136
|
|
|
133
137
|
def serialize_attributes
|