sentry-ruby 5.26.0 → 6.5.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/Gemfile +27 -5
- data/README.md +3 -3
- data/lib/sentry/background_worker.rb +1 -4
- data/lib/sentry/backtrace/line.rb +99 -0
- data/lib/sentry/backtrace.rb +44 -76
- data/lib/sentry/baggage.rb +2 -2
- data/lib/sentry/breadcrumb.rb +1 -1
- data/lib/sentry/breadcrumb_buffer.rb +2 -2
- data/lib/sentry/check_in_event.rb +2 -2
- data/lib/sentry/client.rb +59 -136
- data/lib/sentry/configuration.rb +206 -78
- data/lib/sentry/cron/monitor_check_ins.rb +3 -3
- data/lib/sentry/cron/monitor_config.rb +2 -2
- data/lib/sentry/cron/monitor_schedule.rb +2 -2
- data/lib/sentry/debug_structured_logger.rb +94 -0
- data/lib/sentry/dsn.rb +65 -1
- data/lib/sentry/envelope/item.rb +3 -3
- data/lib/sentry/error_event.rb +3 -3
- data/lib/sentry/event.rb +4 -10
- data/lib/sentry/exceptions.rb +3 -0
- data/lib/sentry/graphql.rb +1 -1
- data/lib/sentry/hub.rb +29 -5
- data/lib/sentry/interface.rb +1 -1
- data/lib/sentry/interfaces/exception.rb +2 -2
- data/lib/sentry/interfaces/request.rb +2 -0
- data/lib/sentry/interfaces/single_exception.rb +4 -4
- data/lib/sentry/interfaces/stacktrace.rb +3 -3
- data/lib/sentry/interfaces/stacktrace_builder.rb +0 -8
- data/lib/sentry/interfaces/threads.rb +2 -2
- data/lib/sentry/log_event.rb +33 -138
- data/lib/sentry/log_event_buffer.rb +13 -60
- data/lib/sentry/metric_event.rb +49 -0
- data/lib/sentry/metric_event_buffer.rb +28 -0
- data/lib/sentry/metrics.rb +47 -42
- data/lib/sentry/profiler.rb +4 -5
- data/lib/sentry/propagation_context.rb +101 -24
- data/lib/sentry/rack/capture_exceptions.rb +90 -2
- data/lib/sentry/release_detector.rb +1 -1
- data/lib/sentry/rspec.rb +1 -1
- data/lib/sentry/scope.rb +51 -18
- data/lib/sentry/sequel.rb +35 -0
- data/lib/sentry/span.rb +5 -17
- data/lib/sentry/std_lib_logger.rb +10 -1
- data/lib/sentry/telemetry_event_buffer.rb +130 -0
- data/lib/sentry/test_helper.rb +30 -0
- data/lib/sentry/transaction.rb +73 -95
- data/lib/sentry/transaction_event.rb +4 -9
- data/lib/sentry/transport/debug_transport.rb +70 -0
- data/lib/sentry/transport/dummy_transport.rb +1 -0
- data/lib/sentry/transport/http_transport.rb +16 -16
- data/lib/sentry/transport.rb +10 -7
- data/lib/sentry/utils/encoding_helper.rb +6 -0
- data/lib/sentry/utils/logging_helper.rb +25 -9
- data/lib/sentry/utils/sample_rand.rb +97 -0
- data/lib/sentry/utils/telemetry_attributes.rb +30 -0
- data/lib/sentry/vernier/profiler.rb +4 -3
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +57 -30
- data/sentry-ruby-core.gemspec +1 -1
- data/sentry-ruby.gemspec +2 -1
- metadata +31 -17
- data/lib/sentry/metrics/aggregator.rb +0 -248
- data/lib/sentry/metrics/configuration.rb +0 -47
- data/lib/sentry/metrics/counter_metric.rb +0 -25
- data/lib/sentry/metrics/distribution_metric.rb +0 -25
- data/lib/sentry/metrics/gauge_metric.rb +0 -35
- data/lib/sentry/metrics/local_aggregator.rb +0 -53
- data/lib/sentry/metrics/metric.rb +0 -19
- data/lib/sentry/metrics/set_metric.rb +0 -28
- data/lib/sentry/metrics/timing.rb +0 -51
data/lib/sentry/configuration.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "cgi/escape"
|
|
3
4
|
require "concurrent/utility/processor_counter"
|
|
4
5
|
|
|
5
6
|
require "sentry/utils/exception_cause_chain"
|
|
@@ -9,11 +10,12 @@ require "sentry/dsn"
|
|
|
9
10
|
require "sentry/release_detector"
|
|
10
11
|
require "sentry/transport/configuration"
|
|
11
12
|
require "sentry/cron/configuration"
|
|
12
|
-
require "sentry/metrics/configuration"
|
|
13
13
|
require "sentry/linecache"
|
|
14
14
|
require "sentry/interfaces/stacktrace_builder"
|
|
15
15
|
require "sentry/logger"
|
|
16
|
+
require "sentry/structured_logger"
|
|
16
17
|
require "sentry/log_event_buffer"
|
|
18
|
+
require "sentry/metric_event_buffer"
|
|
17
19
|
|
|
18
20
|
module Sentry
|
|
19
21
|
class Configuration
|
|
@@ -30,13 +32,6 @@ module Sentry
|
|
|
30
32
|
# @return [Regexp, nil]
|
|
31
33
|
attr_accessor :app_dirs_pattern
|
|
32
34
|
|
|
33
|
-
# Provide an object that responds to `call` to send events asynchronously.
|
|
34
|
-
# E.g.: lambda { |event| Thread.new { Sentry.send_event(event) } }
|
|
35
|
-
#
|
|
36
|
-
# @deprecated It will be removed in the next major release. Please read https://github.com/getsentry/sentry-ruby/issues/1522 for more information
|
|
37
|
-
# @return [Proc, nil]
|
|
38
|
-
attr_reader :async
|
|
39
|
-
|
|
40
35
|
# to send events in a non-blocking way, sentry-ruby has its own background worker
|
|
41
36
|
# by default, the worker holds a thread pool that has [the number of processors] threads
|
|
42
37
|
# but you can configure it with this configuration option
|
|
@@ -74,11 +69,10 @@ module Sentry
|
|
|
74
69
|
# @return [Proc]
|
|
75
70
|
attr_reader :before_breadcrumb
|
|
76
71
|
|
|
77
|
-
# Optional Proc, called before sending an event to the server
|
|
72
|
+
# Optional Proc, called before sending an error event to the server
|
|
78
73
|
# @example
|
|
79
74
|
# config.before_send = lambda do |event, hint|
|
|
80
75
|
# # skip ZeroDivisionError exceptions
|
|
81
|
-
# # note: hint[:exception] would be a String if you use async callback
|
|
82
76
|
# if hint[:exception].is_a?(ZeroDivisionError)
|
|
83
77
|
# nil
|
|
84
78
|
# else
|
|
@@ -88,7 +82,7 @@ module Sentry
|
|
|
88
82
|
# @return [Proc]
|
|
89
83
|
attr_reader :before_send
|
|
90
84
|
|
|
91
|
-
# Optional Proc, called before sending
|
|
85
|
+
# Optional Proc, called before sending a transaction event to the server
|
|
92
86
|
# @example
|
|
93
87
|
# config.before_send_transaction = lambda do |event, hint|
|
|
94
88
|
# # skip unimportant transactions or strip sensitive data
|
|
@@ -101,6 +95,18 @@ module Sentry
|
|
|
101
95
|
# @return [Proc]
|
|
102
96
|
attr_reader :before_send_transaction
|
|
103
97
|
|
|
98
|
+
# Optional Proc, called before sending a check-in event to the server
|
|
99
|
+
# @example
|
|
100
|
+
# config.before_send_check_in = lambda do |event, hint|
|
|
101
|
+
# if event.monitor_slug == "unimportant_job"
|
|
102
|
+
# nil
|
|
103
|
+
# else
|
|
104
|
+
# event
|
|
105
|
+
# end
|
|
106
|
+
# end
|
|
107
|
+
# @return [Proc]
|
|
108
|
+
attr_reader :before_send_check_in
|
|
109
|
+
|
|
104
110
|
# Optional Proc, called before sending an event to the server
|
|
105
111
|
# @example
|
|
106
112
|
# config.before_send_log = lambda do |log|
|
|
@@ -117,7 +123,6 @@ module Sentry
|
|
|
117
123
|
#
|
|
118
124
|
# And if you also use sentry-rails:
|
|
119
125
|
# - :active_support_logger
|
|
120
|
-
# - :monotonic_active_support_logger
|
|
121
126
|
#
|
|
122
127
|
# @return [Array<Symbol>]
|
|
123
128
|
attr_reader :breadcrumbs_logger
|
|
@@ -144,7 +149,7 @@ module Sentry
|
|
|
144
149
|
attr_reader :dsn
|
|
145
150
|
|
|
146
151
|
# Whitelist of enabled_environments that will send notifications to Sentry. Array of Strings.
|
|
147
|
-
# @return [Array<String
|
|
152
|
+
# @return [Array<String>, nil]
|
|
148
153
|
attr_accessor :enabled_environments
|
|
149
154
|
|
|
150
155
|
# Logger 'progname's to exclude from breadcrumbs
|
|
@@ -173,18 +178,6 @@ module Sentry
|
|
|
173
178
|
# @return [Boolean, String]
|
|
174
179
|
attr_accessor :spotlight
|
|
175
180
|
|
|
176
|
-
# @deprecated Use {#include_local_variables} instead.
|
|
177
|
-
alias_method :capture_exception_frame_locals, :include_local_variables
|
|
178
|
-
|
|
179
|
-
# @deprecated Use {#include_local_variables=} instead.
|
|
180
|
-
def capture_exception_frame_locals=(value)
|
|
181
|
-
log_warn <<~MSG
|
|
182
|
-
`capture_exception_frame_locals` is now deprecated in favor of `include_local_variables`.
|
|
183
|
-
MSG
|
|
184
|
-
|
|
185
|
-
self.include_local_variables = value
|
|
186
|
-
end
|
|
187
|
-
|
|
188
181
|
# You may provide your own LineCache for matching paths with source files.
|
|
189
182
|
# This may be useful if you need to get source code from places other than the disk.
|
|
190
183
|
# @see LineCache
|
|
@@ -196,17 +189,10 @@ module Sentry
|
|
|
196
189
|
# @return [Logger]
|
|
197
190
|
attr_accessor :sdk_logger
|
|
198
191
|
|
|
199
|
-
#
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
# @deprecated Use {#sdk_logger} instead.
|
|
206
|
-
def logger
|
|
207
|
-
warn "[sentry] `config.logger` is deprecated. Please use `config.sdk_logger` instead."
|
|
208
|
-
self.sdk_logger
|
|
209
|
-
end
|
|
192
|
+
# File path for DebugTransport to log events to. If not set, defaults to a temporary file.
|
|
193
|
+
# This is useful for debugging and testing purposes.
|
|
194
|
+
# @return [String, nil]
|
|
195
|
+
attr_accessor :sdk_debug_transport_log_file
|
|
210
196
|
|
|
211
197
|
# Project directory root for in_app detection. Could be Rails root, etc.
|
|
212
198
|
# Set automatically for Rails.
|
|
@@ -249,6 +235,12 @@ module Sentry
|
|
|
249
235
|
# @return [Boolean]
|
|
250
236
|
attr_accessor :send_default_pii
|
|
251
237
|
|
|
238
|
+
# Capture queue time from X-Request-Start header set by reverse proxies.
|
|
239
|
+
# Works with any Rack app behind Nginx, HAProxy, Heroku router, etc.
|
|
240
|
+
# Defaults to true.
|
|
241
|
+
# @return [Boolean]
|
|
242
|
+
attr_accessor :capture_queue_time
|
|
243
|
+
|
|
252
244
|
# Allow to skip Sentry emails within rake tasks
|
|
253
245
|
# @return [Boolean]
|
|
254
246
|
attr_accessor :skip_rake_integration
|
|
@@ -267,10 +259,6 @@ module Sentry
|
|
|
267
259
|
# @return [Cron::Configuration]
|
|
268
260
|
attr_reader :cron
|
|
269
261
|
|
|
270
|
-
# Metrics related configuration.
|
|
271
|
-
# @return [Metrics::Configuration]
|
|
272
|
-
attr_reader :metrics
|
|
273
|
-
|
|
274
262
|
# Take a float between 0.0 and 1.0 as the sample rate for tracing events (transactions).
|
|
275
263
|
# @return [Float, nil]
|
|
276
264
|
attr_reader :traces_sample_rate
|
|
@@ -289,11 +277,9 @@ module Sentry
|
|
|
289
277
|
# @return [Boolean]
|
|
290
278
|
attr_accessor :enable_logs
|
|
291
279
|
|
|
292
|
-
#
|
|
293
|
-
#
|
|
294
|
-
|
|
295
|
-
# @return [Boolean, nil]
|
|
296
|
-
attr_reader :enable_tracing
|
|
280
|
+
# Structured logging configuration.
|
|
281
|
+
# @return [StructuredLoggingConfiguration]
|
|
282
|
+
attr_reader :structured_logging
|
|
297
283
|
|
|
298
284
|
# Send diagnostic client reports about dropped events, true by default
|
|
299
285
|
# tries to attach to an existing envelope max once every 30s
|
|
@@ -315,6 +301,18 @@ module Sentry
|
|
|
315
301
|
# @return [Array<String, Regexp>]
|
|
316
302
|
attr_accessor :trace_propagation_targets
|
|
317
303
|
|
|
304
|
+
# Collection of HTTP status codes or ranges of codes to ignore when tracing incoming requests.
|
|
305
|
+
# If a transaction's http.response.status_code matches one of these values,
|
|
306
|
+
# the transaction will be dropped and marked as not sampled.
|
|
307
|
+
# Defaults to TRACE_IGNORE_STATUS_CODES_DEFAULT.
|
|
308
|
+
#
|
|
309
|
+
# @example
|
|
310
|
+
# # ignore 404 and 502 <= status_code <= 511
|
|
311
|
+
# config.trace_ignore_status_codes = [404, (502..511)]
|
|
312
|
+
#
|
|
313
|
+
# @return [Array<Integer>, Array<Range>]
|
|
314
|
+
attr_reader :trace_ignore_status_codes
|
|
315
|
+
|
|
318
316
|
# The instrumenter to use, :sentry or :otel
|
|
319
317
|
# @return [Symbol]
|
|
320
318
|
attr_reader :instrumenter
|
|
@@ -329,6 +327,15 @@ module Sentry
|
|
|
329
327
|
# @return [Float, nil]
|
|
330
328
|
attr_reader :profiles_sample_rate
|
|
331
329
|
|
|
330
|
+
# Interval in microseconds at which to take samples.
|
|
331
|
+
# The default is 1e6 / 101, or 101Hz.
|
|
332
|
+
# Note that the 101 is intentional to avoid lockstep sampling.
|
|
333
|
+
#
|
|
334
|
+
# @example
|
|
335
|
+
# config.profiles_sample_interval = 1e5 / 101
|
|
336
|
+
# @return [Float]
|
|
337
|
+
attr_accessor :profiles_sample_interval
|
|
338
|
+
|
|
332
339
|
# Array of patches to apply.
|
|
333
340
|
# Default is {DEFAULT_PATCHES}
|
|
334
341
|
# @return [Array<Symbol>]
|
|
@@ -338,6 +345,50 @@ module Sentry
|
|
|
338
345
|
# @return [Integer]
|
|
339
346
|
attr_accessor :max_log_events
|
|
340
347
|
|
|
348
|
+
# Enable metrics collection, defaults to true
|
|
349
|
+
# @return [Boolean]
|
|
350
|
+
attr_accessor :enable_metrics
|
|
351
|
+
|
|
352
|
+
# Maximum number of metric events to buffer before sending
|
|
353
|
+
# @return [Integer]
|
|
354
|
+
attr_accessor :max_metric_events
|
|
355
|
+
|
|
356
|
+
# Optional Proc, called before sending a metric
|
|
357
|
+
# @example
|
|
358
|
+
# config.before_send_metric = lambda do |metric|
|
|
359
|
+
# # return nil to drop the metric
|
|
360
|
+
# metric
|
|
361
|
+
# end
|
|
362
|
+
# @return [Proc, nil]
|
|
363
|
+
attr_reader :before_send_metric
|
|
364
|
+
|
|
365
|
+
# Optional Proc, called to filter log messages before sending to Sentry
|
|
366
|
+
# @example
|
|
367
|
+
# config.std_lib_logger_filter = lambda do |logger, message, level|
|
|
368
|
+
# # Only send error and fatal logs to Sentry
|
|
369
|
+
# [:error, :fatal].include?(level)
|
|
370
|
+
# end
|
|
371
|
+
# @return [Proc, nil]
|
|
372
|
+
attr_reader :std_lib_logger_filter
|
|
373
|
+
|
|
374
|
+
# An optional organization ID. The SDK will try to extract it from the DSN in most cases
|
|
375
|
+
# but you can provide it explicitly for self-hosted and Relay setups.
|
|
376
|
+
# This value is used for trace propagation and for features like strict_trace_continuation.
|
|
377
|
+
# @return [String, nil]
|
|
378
|
+
attr_reader :org_id
|
|
379
|
+
|
|
380
|
+
# If set to true, the SDK will only continue a trace if the org_id of the incoming trace found in the
|
|
381
|
+
# baggage header matches the org_id of the current Sentry client and only if BOTH are present.
|
|
382
|
+
#
|
|
383
|
+
# If set to false, consistency of org_id will only be enforced if both are present.
|
|
384
|
+
# If either are missing, the trace will be continued.
|
|
385
|
+
#
|
|
386
|
+
# The client's organization ID is extracted from the DSN or can be set with the org_id option.
|
|
387
|
+
# If the organization IDs do not match, the SDK will start a new trace instead of continuing the incoming one.
|
|
388
|
+
# This is useful to prevent traces of unknown third-party services from being continued in your application.
|
|
389
|
+
# @return [Boolean]
|
|
390
|
+
attr_accessor :strict_trace_continuation
|
|
391
|
+
|
|
341
392
|
# these are not config options
|
|
342
393
|
# @!visibility private
|
|
343
394
|
attr_reader :errors, :gem_specs
|
|
@@ -366,6 +417,8 @@ module Sentry
|
|
|
366
417
|
SERVER_PORT
|
|
367
418
|
].freeze
|
|
368
419
|
|
|
420
|
+
TRACE_IGNORE_STATUS_CODES_DEFAULT = [(301..303), (305..399), (401..404)]
|
|
421
|
+
|
|
369
422
|
HEROKU_DYNO_METADATA_MESSAGE = "You are running on Heroku but haven't enabled Dyno Metadata. For Sentry's "\
|
|
370
423
|
"release detection to work correctly, please run `heroku labs:enable runtime-dyno-metadata`"
|
|
371
424
|
|
|
@@ -381,6 +434,9 @@ module Sentry
|
|
|
381
434
|
|
|
382
435
|
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/
|
|
383
436
|
|
|
437
|
+
# 101 Hz in microseconds
|
|
438
|
+
DEFAULT_PROFILES_SAMPLE_INTERVAL = 1e6 / 101
|
|
439
|
+
|
|
384
440
|
class << self
|
|
385
441
|
# Post initialization callbacks are called at the end of initialization process
|
|
386
442
|
# allowing extending the configuration of sentry-ruby by multiple extensions
|
|
@@ -390,7 +446,23 @@ module Sentry
|
|
|
390
446
|
|
|
391
447
|
# allow extensions to add their hooks to the Configuration class
|
|
392
448
|
def add_post_initialization_callback(&block)
|
|
393
|
-
|
|
449
|
+
callbacks[:initialize][:after] << block
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def before(event, &block)
|
|
453
|
+
callbacks[event.to_sym][:before] << block
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
def after(event, &block)
|
|
457
|
+
callbacks[event.to_sym][:after] << block
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
# @!visibility private
|
|
461
|
+
def callbacks
|
|
462
|
+
@callbacks ||= {
|
|
463
|
+
initialize: { before: [], after: [] },
|
|
464
|
+
configured: { before: [], after: [] }
|
|
465
|
+
}
|
|
394
466
|
end
|
|
395
467
|
|
|
396
468
|
def validations
|
|
@@ -434,6 +506,8 @@ module Sentry
|
|
|
434
506
|
validate :profiles_sample_rate, optional: true, type: :numeric
|
|
435
507
|
|
|
436
508
|
def initialize
|
|
509
|
+
run_callbacks(:before, :initialize)
|
|
510
|
+
|
|
437
511
|
self.app_dirs_pattern = APP_DIRS_PATTERN
|
|
438
512
|
self.debug = Sentry::Utils::EnvHelper.env_to_bool(ENV["SENTRY_DEBUG"])
|
|
439
513
|
self.background_worker_threads = (processor_count / 2.0).ceil
|
|
@@ -445,7 +519,7 @@ module Sentry
|
|
|
445
519
|
self.context_lines = 3
|
|
446
520
|
self.include_local_variables = false
|
|
447
521
|
self.environment = environment_from_env
|
|
448
|
-
self.enabled_environments =
|
|
522
|
+
self.enabled_environments = nil
|
|
449
523
|
self.exclude_loggers = []
|
|
450
524
|
self.excluded_exceptions = IGNORE_DEFAULT + PUMA_IGNORE_DEFAULT
|
|
451
525
|
self.inspect_exception_causes_for_exclusion = true
|
|
@@ -463,6 +537,9 @@ module Sentry
|
|
|
463
537
|
self.enable_backpressure_handling = false
|
|
464
538
|
self.trusted_proxies = []
|
|
465
539
|
self.dsn = ENV["SENTRY_DSN"]
|
|
540
|
+
self.capture_queue_time = true
|
|
541
|
+
self.org_id = nil
|
|
542
|
+
self.strict_trace_continuation = false
|
|
466
543
|
|
|
467
544
|
spotlight_env = ENV["SENTRY_SPOTLIGHT"]
|
|
468
545
|
spotlight_bool = Sentry::Utils::EnvHelper.env_to_bool(spotlight_env, strict: true)
|
|
@@ -470,26 +547,36 @@ module Sentry
|
|
|
470
547
|
self.server_name = server_name_from_env
|
|
471
548
|
self.instrumenter = :sentry
|
|
472
549
|
self.trace_propagation_targets = [PROPAGATION_TARGETS_MATCH_ALL]
|
|
550
|
+
self.trace_ignore_status_codes = TRACE_IGNORE_STATUS_CODES_DEFAULT
|
|
473
551
|
self.enabled_patches = DEFAULT_PATCHES.dup
|
|
474
552
|
|
|
475
553
|
self.before_send = nil
|
|
476
554
|
self.before_send_transaction = nil
|
|
555
|
+
self.before_send_check_in = nil
|
|
477
556
|
self.before_send_log = nil
|
|
557
|
+
self.before_send_metric = nil
|
|
558
|
+
self.std_lib_logger_filter = nil
|
|
478
559
|
self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
|
|
479
560
|
self.traces_sampler = nil
|
|
480
|
-
self.enable_tracing = nil
|
|
481
561
|
self.enable_logs = false
|
|
562
|
+
self.enable_metrics = true
|
|
482
563
|
|
|
483
564
|
self.profiler_class = Sentry::Profiler
|
|
565
|
+
self.profiles_sample_interval = DEFAULT_PROFILES_SAMPLE_INTERVAL
|
|
484
566
|
|
|
485
567
|
@transport = Transport::Configuration.new
|
|
486
568
|
@cron = Cron::Configuration.new
|
|
487
|
-
@
|
|
569
|
+
@structured_logging = StructuredLoggingConfiguration.new
|
|
488
570
|
@gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
|
489
571
|
|
|
490
|
-
run_post_initialization_callbacks
|
|
491
|
-
|
|
492
572
|
self.max_log_events = LogEventBuffer::DEFAULT_MAX_EVENTS
|
|
573
|
+
self.max_metric_events = MetricEventBuffer::DEFAULT_MAX_METRICS
|
|
574
|
+
|
|
575
|
+
run_callbacks(:after, :initialize)
|
|
576
|
+
|
|
577
|
+
yield(self) if block_given?
|
|
578
|
+
|
|
579
|
+
run_callbacks(:after, :configured)
|
|
493
580
|
end
|
|
494
581
|
|
|
495
582
|
def validate
|
|
@@ -522,22 +609,6 @@ module Sentry
|
|
|
522
609
|
@release = value
|
|
523
610
|
end
|
|
524
611
|
|
|
525
|
-
def async=(value)
|
|
526
|
-
check_callable!("async", value)
|
|
527
|
-
|
|
528
|
-
log_warn <<~MSG
|
|
529
|
-
|
|
530
|
-
sentry-ruby now sends events asynchronously by default with its background worker (supported since 4.1.0).
|
|
531
|
-
The `config.async` callback has become redundant while continuing to cause issues.
|
|
532
|
-
(The problems of `async` are detailed in https://github.com/getsentry/sentry-ruby/issues/1522)
|
|
533
|
-
|
|
534
|
-
Therefore, we encourage you to remove it and let the background worker take care of async job sending.
|
|
535
|
-
It's deprecation is planned in the next major release (6.0), which is scheduled around the 3rd quarter of 2022.
|
|
536
|
-
MSG
|
|
537
|
-
|
|
538
|
-
@async = value
|
|
539
|
-
end
|
|
540
|
-
|
|
541
612
|
def breadcrumbs_logger=(logger)
|
|
542
613
|
loggers =
|
|
543
614
|
if logger.is_a?(Array)
|
|
@@ -563,12 +634,30 @@ module Sentry
|
|
|
563
634
|
@before_send_transaction = value
|
|
564
635
|
end
|
|
565
636
|
|
|
637
|
+
def before_send_check_in=(value)
|
|
638
|
+
check_callable!("before_send_check_in", value)
|
|
639
|
+
|
|
640
|
+
@before_send_check_in = value
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
def before_send_metric=(value)
|
|
644
|
+
check_callable!("before_send_metric", value)
|
|
645
|
+
|
|
646
|
+
@before_send_metric = value
|
|
647
|
+
end
|
|
648
|
+
|
|
566
649
|
def before_breadcrumb=(value)
|
|
567
650
|
check_callable!("before_breadcrumb", value)
|
|
568
651
|
|
|
569
652
|
@before_breadcrumb = value
|
|
570
653
|
end
|
|
571
654
|
|
|
655
|
+
def std_lib_logger_filter=(value)
|
|
656
|
+
check_callable!("std_lib_logger_filter", value)
|
|
657
|
+
|
|
658
|
+
@std_lib_logger_filter = value
|
|
659
|
+
end
|
|
660
|
+
|
|
572
661
|
def environment=(environment)
|
|
573
662
|
@environment = environment.to_s
|
|
574
663
|
end
|
|
@@ -577,15 +666,12 @@ module Sentry
|
|
|
577
666
|
@instrumenter = INSTRUMENTERS.include?(instrumenter) ? instrumenter : :sentry
|
|
578
667
|
end
|
|
579
668
|
|
|
580
|
-
def
|
|
581
|
-
unless
|
|
582
|
-
|
|
583
|
-
`enable_tracing` is now deprecated in favor of `traces_sample_rate = 1.0`.
|
|
584
|
-
MSG
|
|
669
|
+
def trace_ignore_status_codes=(codes)
|
|
670
|
+
unless codes.is_a?(Array) && codes.all? { |code| valid_status_code_entry?(code) }
|
|
671
|
+
raise ArgumentError, "trace_ignore_status_codes must be an Array of integers or ranges between (100-599) where begin <= end"
|
|
585
672
|
end
|
|
586
673
|
|
|
587
|
-
@
|
|
588
|
-
@traces_sample_rate ||= 1.0 if enable_tracing
|
|
674
|
+
@trace_ignore_status_codes = codes
|
|
589
675
|
end
|
|
590
676
|
|
|
591
677
|
def traces_sample_rate=(traces_sample_rate)
|
|
@@ -607,6 +693,16 @@ module Sentry
|
|
|
607
693
|
@profiler_class = profiler_class
|
|
608
694
|
end
|
|
609
695
|
|
|
696
|
+
def org_id=(value)
|
|
697
|
+
@org_id = value&.to_s
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
# Returns the effective org ID, preferring the explicit config option over the DSN-parsed value.
|
|
701
|
+
# @return [String, nil]
|
|
702
|
+
def effective_org_id
|
|
703
|
+
org_id || dsn&.org_id
|
|
704
|
+
end
|
|
705
|
+
|
|
610
706
|
def sending_allowed?
|
|
611
707
|
spotlight || sending_to_dsn_allowed?
|
|
612
708
|
end
|
|
@@ -641,7 +737,7 @@ module Sentry
|
|
|
641
737
|
end
|
|
642
738
|
|
|
643
739
|
def enabled_in_current_env?
|
|
644
|
-
enabled_environments.
|
|
740
|
+
enabled_environments.nil? || enabled_environments.include?(environment)
|
|
645
741
|
end
|
|
646
742
|
|
|
647
743
|
def valid_sample_rate?(sample_rate)
|
|
@@ -652,7 +748,7 @@ module Sentry
|
|
|
652
748
|
def tracing_enabled?
|
|
653
749
|
valid_sampler = !!((valid_sample_rate?(@traces_sample_rate)) || @traces_sampler)
|
|
654
750
|
|
|
655
|
-
|
|
751
|
+
valid_sampler && sending_allowed?
|
|
656
752
|
end
|
|
657
753
|
|
|
658
754
|
def profiling_enabled?
|
|
@@ -773,8 +869,8 @@ module Sentry
|
|
|
773
869
|
File.directory?("/etc/heroku") && !ENV["CI"]
|
|
774
870
|
end
|
|
775
871
|
|
|
776
|
-
def
|
|
777
|
-
self.class.
|
|
872
|
+
def run_callbacks(hook, event)
|
|
873
|
+
self.class.callbacks[event][hook].each do |hook|
|
|
778
874
|
instance_eval(&hook)
|
|
779
875
|
end
|
|
780
876
|
end
|
|
@@ -783,5 +879,37 @@ module Sentry
|
|
|
783
879
|
available_processor_count = Concurrent.available_processor_count if Concurrent.respond_to?(:available_processor_count)
|
|
784
880
|
available_processor_count || Concurrent.processor_count
|
|
785
881
|
end
|
|
882
|
+
|
|
883
|
+
def valid_http_status_code?(code)
|
|
884
|
+
code.is_a?(Integer) && code >= 100 && code <= 599
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
def valid_status_code_entry?(entry)
|
|
888
|
+
case entry
|
|
889
|
+
when Integer
|
|
890
|
+
valid_http_status_code?(entry)
|
|
891
|
+
when Range
|
|
892
|
+
valid_http_status_code?(entry.begin) &&
|
|
893
|
+
valid_http_status_code?(entry.end) &&
|
|
894
|
+
entry.begin <= entry.end
|
|
895
|
+
else
|
|
896
|
+
false
|
|
897
|
+
end
|
|
898
|
+
end
|
|
899
|
+
end
|
|
900
|
+
|
|
901
|
+
class StructuredLoggingConfiguration
|
|
902
|
+
# File path for DebugStructuredLogger to log events to
|
|
903
|
+
# @return [String, Pathname, nil]
|
|
904
|
+
attr_accessor :file_path
|
|
905
|
+
|
|
906
|
+
# The class to use as a structured logger.
|
|
907
|
+
# @return [Class]
|
|
908
|
+
attr_accessor :logger_class
|
|
909
|
+
|
|
910
|
+
def initialize
|
|
911
|
+
@file_path = nil
|
|
912
|
+
@logger_class = Sentry::StructuredLogger
|
|
913
|
+
end
|
|
786
914
|
end
|
|
787
915
|
end
|
|
@@ -14,12 +14,12 @@ module Sentry
|
|
|
14
14
|
:in_progress,
|
|
15
15
|
monitor_config: monitor_config)
|
|
16
16
|
|
|
17
|
-
start =
|
|
17
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
18
18
|
|
|
19
19
|
begin
|
|
20
20
|
# need to do this on ruby <= 2.6 sadly
|
|
21
21
|
ret = method(:perform).super_method.arity == 0 ? super() : super
|
|
22
|
-
duration =
|
|
22
|
+
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
|
23
23
|
|
|
24
24
|
Sentry.capture_check_in(slug,
|
|
25
25
|
:ok,
|
|
@@ -29,7 +29,7 @@ module Sentry
|
|
|
29
29
|
|
|
30
30
|
ret
|
|
31
31
|
rescue Exception
|
|
32
|
-
duration =
|
|
32
|
+
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
|
33
33
|
|
|
34
34
|
Sentry.capture_check_in(slug,
|
|
35
35
|
:error,
|
|
@@ -40,9 +40,9 @@ module Sentry
|
|
|
40
40
|
new(MonitorSchedule::Interval.new(num, unit), **options)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def
|
|
43
|
+
def to_h
|
|
44
44
|
{
|
|
45
|
-
schedule: schedule.
|
|
45
|
+
schedule: schedule.to_h,
|
|
46
46
|
checkin_margin: checkin_margin,
|
|
47
47
|
max_runtime: max_runtime,
|
|
48
48
|
timezone: timezone
|
|
@@ -12,7 +12,7 @@ module Sentry
|
|
|
12
12
|
@value = value
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def to_h
|
|
16
16
|
{ type: :crontab, value: value }
|
|
17
17
|
end
|
|
18
18
|
end
|
|
@@ -33,7 +33,7 @@ module Sentry
|
|
|
33
33
|
@unit = unit
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
def
|
|
36
|
+
def to_h
|
|
37
37
|
{ type: :interval, value: value, unit: unit }
|
|
38
38
|
end
|
|
39
39
|
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "pathname"
|
|
6
|
+
require "delegate"
|
|
7
|
+
|
|
8
|
+
module Sentry
|
|
9
|
+
# DebugStructuredLogger is a logger that captures structured log events to a file for debugging purposes.
|
|
10
|
+
#
|
|
11
|
+
# It can optionally also send log events to Sentry via the normal structured logger if logging
|
|
12
|
+
# is enabled.
|
|
13
|
+
class DebugStructuredLogger < SimpleDelegator
|
|
14
|
+
DEFAULT_LOG_FILE_PATH = File.join("log", "sentry_debug_logs.log")
|
|
15
|
+
|
|
16
|
+
attr_reader :log_file, :backend
|
|
17
|
+
|
|
18
|
+
def initialize(configuration)
|
|
19
|
+
@log_file = initialize_log_file(
|
|
20
|
+
configuration.structured_logging.file_path || DEFAULT_LOG_FILE_PATH
|
|
21
|
+
)
|
|
22
|
+
@backend = initialize_backend(configuration)
|
|
23
|
+
|
|
24
|
+
super(@backend)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Override all log level methods to capture events
|
|
28
|
+
%i[trace debug info warn error fatal].each do |level|
|
|
29
|
+
define_method(level) do |message, parameters = [], **attributes|
|
|
30
|
+
log_event = capture_log_event(level, message, parameters, **attributes)
|
|
31
|
+
backend.public_send(level, message, parameters, **attributes)
|
|
32
|
+
log_event
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def log(level, message, parameters:, **attributes)
|
|
37
|
+
log_event = capture_log_event(level, message, parameters, **attributes)
|
|
38
|
+
backend.log(level, message, parameters: parameters, **attributes)
|
|
39
|
+
log_event
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def capture_log_event(level, message, parameters, **attributes)
|
|
43
|
+
log_event_json = {
|
|
44
|
+
timestamp: Time.now.utc.iso8601,
|
|
45
|
+
level: level.to_s,
|
|
46
|
+
message: message,
|
|
47
|
+
parameters: parameters,
|
|
48
|
+
attributes: attributes
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
File.open(log_file, "a") { |file| file << JSON.dump(log_event_json) << "\n" }
|
|
52
|
+
log_event_json
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def logged_events
|
|
56
|
+
File.readlines(log_file).map do |line|
|
|
57
|
+
JSON.parse(line)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def clear
|
|
62
|
+
File.write(log_file, "")
|
|
63
|
+
if backend.respond_to?(:config)
|
|
64
|
+
backend.config.sdk_logger.debug("DebugStructuredLogger: Cleared events from #{log_file}")
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def initialize_backend(configuration)
|
|
71
|
+
if configuration.enable_logs
|
|
72
|
+
StructuredLogger.new(configuration)
|
|
73
|
+
else
|
|
74
|
+
# Create a no-op logger if logging is disabled
|
|
75
|
+
NoOpLogger.new
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def initialize_log_file(log_file_path)
|
|
80
|
+
log_file = Pathname(log_file_path)
|
|
81
|
+
|
|
82
|
+
FileUtils.mkdir_p(log_file.dirname) unless log_file.dirname.exist?
|
|
83
|
+
|
|
84
|
+
log_file
|
|
85
|
+
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
|
+
end
|
|
94
|
+
end
|