sentry-ruby 5.26.0 → 6.1.1
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 +2 -4
- data/README.md +1 -1
- 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/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 +39 -89
- data/lib/sentry/configuration.rb +125 -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 +32 -0
- data/lib/sentry/envelope/item.rb +1 -2
- data/lib/sentry/error_event.rb +3 -3
- data/lib/sentry/event.rb +4 -10
- data/lib/sentry/graphql.rb +1 -1
- data/lib/sentry/hub.rb +6 -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 +3 -3
- 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 +19 -6
- data/lib/sentry/profiler.rb +4 -5
- data/lib/sentry/propagation_context.rb +55 -18
- data/lib/sentry/rspec.rb +1 -1
- data/lib/sentry/span.rb +2 -17
- data/lib/sentry/std_lib_logger.rb +6 -1
- data/lib/sentry/test_helper.rb +23 -0
- data/lib/sentry/transaction.rb +72 -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 +9 -5
- data/lib/sentry/transport.rb +3 -5
- data/lib/sentry/utils/encoding_helper.rb +7 -0
- data/lib/sentry/utils/logging_helper.rb +8 -6
- data/lib/sentry/utils/sample_rand.rb +97 -0
- data/lib/sentry/vernier/profiler.rb +4 -3
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +6 -30
- data/sentry-ruby-core.gemspec +1 -1
- data/sentry-ruby.gemspec +1 -1
- metadata +12 -18
- 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/metrics.rb +0 -56
data/lib/sentry/configuration.rb
CHANGED
|
@@ -9,10 +9,10 @@ require "sentry/dsn"
|
|
|
9
9
|
require "sentry/release_detector"
|
|
10
10
|
require "sentry/transport/configuration"
|
|
11
11
|
require "sentry/cron/configuration"
|
|
12
|
-
require "sentry/metrics/configuration"
|
|
13
12
|
require "sentry/linecache"
|
|
14
13
|
require "sentry/interfaces/stacktrace_builder"
|
|
15
14
|
require "sentry/logger"
|
|
15
|
+
require "sentry/structured_logger"
|
|
16
16
|
require "sentry/log_event_buffer"
|
|
17
17
|
|
|
18
18
|
module Sentry
|
|
@@ -30,13 +30,6 @@ module Sentry
|
|
|
30
30
|
# @return [Regexp, nil]
|
|
31
31
|
attr_accessor :app_dirs_pattern
|
|
32
32
|
|
|
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
33
|
# to send events in a non-blocking way, sentry-ruby has its own background worker
|
|
41
34
|
# by default, the worker holds a thread pool that has [the number of processors] threads
|
|
42
35
|
# but you can configure it with this configuration option
|
|
@@ -74,11 +67,10 @@ module Sentry
|
|
|
74
67
|
# @return [Proc]
|
|
75
68
|
attr_reader :before_breadcrumb
|
|
76
69
|
|
|
77
|
-
# Optional Proc, called before sending an event to the server
|
|
70
|
+
# Optional Proc, called before sending an error event to the server
|
|
78
71
|
# @example
|
|
79
72
|
# config.before_send = lambda do |event, hint|
|
|
80
73
|
# # skip ZeroDivisionError exceptions
|
|
81
|
-
# # note: hint[:exception] would be a String if you use async callback
|
|
82
74
|
# if hint[:exception].is_a?(ZeroDivisionError)
|
|
83
75
|
# nil
|
|
84
76
|
# else
|
|
@@ -88,7 +80,7 @@ module Sentry
|
|
|
88
80
|
# @return [Proc]
|
|
89
81
|
attr_reader :before_send
|
|
90
82
|
|
|
91
|
-
# Optional Proc, called before sending
|
|
83
|
+
# Optional Proc, called before sending a transaction event to the server
|
|
92
84
|
# @example
|
|
93
85
|
# config.before_send_transaction = lambda do |event, hint|
|
|
94
86
|
# # skip unimportant transactions or strip sensitive data
|
|
@@ -101,6 +93,18 @@ module Sentry
|
|
|
101
93
|
# @return [Proc]
|
|
102
94
|
attr_reader :before_send_transaction
|
|
103
95
|
|
|
96
|
+
# Optional Proc, called before sending a check-in event to the server
|
|
97
|
+
# @example
|
|
98
|
+
# config.before_send_check_in = lambda do |event, hint|
|
|
99
|
+
# if event.monitor_slug == "unimportant_job"
|
|
100
|
+
# nil
|
|
101
|
+
# else
|
|
102
|
+
# event
|
|
103
|
+
# end
|
|
104
|
+
# end
|
|
105
|
+
# @return [Proc]
|
|
106
|
+
attr_reader :before_send_check_in
|
|
107
|
+
|
|
104
108
|
# Optional Proc, called before sending an event to the server
|
|
105
109
|
# @example
|
|
106
110
|
# config.before_send_log = lambda do |log|
|
|
@@ -117,7 +121,6 @@ module Sentry
|
|
|
117
121
|
#
|
|
118
122
|
# And if you also use sentry-rails:
|
|
119
123
|
# - :active_support_logger
|
|
120
|
-
# - :monotonic_active_support_logger
|
|
121
124
|
#
|
|
122
125
|
# @return [Array<Symbol>]
|
|
123
126
|
attr_reader :breadcrumbs_logger
|
|
@@ -144,7 +147,7 @@ module Sentry
|
|
|
144
147
|
attr_reader :dsn
|
|
145
148
|
|
|
146
149
|
# Whitelist of enabled_environments that will send notifications to Sentry. Array of Strings.
|
|
147
|
-
# @return [Array<String
|
|
150
|
+
# @return [Array<String>, nil]
|
|
148
151
|
attr_accessor :enabled_environments
|
|
149
152
|
|
|
150
153
|
# Logger 'progname's to exclude from breadcrumbs
|
|
@@ -173,18 +176,6 @@ module Sentry
|
|
|
173
176
|
# @return [Boolean, String]
|
|
174
177
|
attr_accessor :spotlight
|
|
175
178
|
|
|
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
179
|
# You may provide your own LineCache for matching paths with source files.
|
|
189
180
|
# This may be useful if you need to get source code from places other than the disk.
|
|
190
181
|
# @see LineCache
|
|
@@ -196,17 +187,10 @@ module Sentry
|
|
|
196
187
|
# @return [Logger]
|
|
197
188
|
attr_accessor :sdk_logger
|
|
198
189
|
|
|
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
|
|
190
|
+
# File path for DebugTransport to log events to. If not set, defaults to a temporary file.
|
|
191
|
+
# This is useful for debugging and testing purposes.
|
|
192
|
+
# @return [String, nil]
|
|
193
|
+
attr_accessor :sdk_debug_transport_log_file
|
|
210
194
|
|
|
211
195
|
# Project directory root for in_app detection. Could be Rails root, etc.
|
|
212
196
|
# Set automatically for Rails.
|
|
@@ -267,10 +251,6 @@ module Sentry
|
|
|
267
251
|
# @return [Cron::Configuration]
|
|
268
252
|
attr_reader :cron
|
|
269
253
|
|
|
270
|
-
# Metrics related configuration.
|
|
271
|
-
# @return [Metrics::Configuration]
|
|
272
|
-
attr_reader :metrics
|
|
273
|
-
|
|
274
254
|
# Take a float between 0.0 and 1.0 as the sample rate for tracing events (transactions).
|
|
275
255
|
# @return [Float, nil]
|
|
276
256
|
attr_reader :traces_sample_rate
|
|
@@ -289,11 +269,9 @@ module Sentry
|
|
|
289
269
|
# @return [Boolean]
|
|
290
270
|
attr_accessor :enable_logs
|
|
291
271
|
|
|
292
|
-
#
|
|
293
|
-
#
|
|
294
|
-
|
|
295
|
-
# @return [Boolean, nil]
|
|
296
|
-
attr_reader :enable_tracing
|
|
272
|
+
# Structured logging configuration.
|
|
273
|
+
# @return [StructuredLoggingConfiguration]
|
|
274
|
+
attr_reader :structured_logging
|
|
297
275
|
|
|
298
276
|
# Send diagnostic client reports about dropped events, true by default
|
|
299
277
|
# tries to attach to an existing envelope max once every 30s
|
|
@@ -315,6 +293,18 @@ module Sentry
|
|
|
315
293
|
# @return [Array<String, Regexp>]
|
|
316
294
|
attr_accessor :trace_propagation_targets
|
|
317
295
|
|
|
296
|
+
# Collection of HTTP status codes or ranges of codes to ignore when tracing incoming requests.
|
|
297
|
+
# If a transaction's http.response.status_code matches one of these values,
|
|
298
|
+
# the transaction will be dropped and marked as not sampled.
|
|
299
|
+
# Defaults to TRACE_IGNORE_STATUS_CODES_DEFAULT.
|
|
300
|
+
#
|
|
301
|
+
# @example
|
|
302
|
+
# # ignore 404 and 502 <= status_code <= 511
|
|
303
|
+
# config.trace_ignore_status_codes = [404, (502..511)]
|
|
304
|
+
#
|
|
305
|
+
# @return [Array<Integer>, Array<Range>]
|
|
306
|
+
attr_reader :trace_ignore_status_codes
|
|
307
|
+
|
|
318
308
|
# The instrumenter to use, :sentry or :otel
|
|
319
309
|
# @return [Symbol]
|
|
320
310
|
attr_reader :instrumenter
|
|
@@ -329,6 +319,15 @@ module Sentry
|
|
|
329
319
|
# @return [Float, nil]
|
|
330
320
|
attr_reader :profiles_sample_rate
|
|
331
321
|
|
|
322
|
+
# Interval in microseconds at which to take samples.
|
|
323
|
+
# The default is 1e6 / 101, or 101Hz.
|
|
324
|
+
# Note that the 101 is intentional to avoid lockstep sampling.
|
|
325
|
+
#
|
|
326
|
+
# @example
|
|
327
|
+
# config.profiles_sample_interval = 1e5 / 101
|
|
328
|
+
# @return [Float]
|
|
329
|
+
attr_accessor :profiles_sample_interval
|
|
330
|
+
|
|
332
331
|
# Array of patches to apply.
|
|
333
332
|
# Default is {DEFAULT_PATCHES}
|
|
334
333
|
# @return [Array<Symbol>]
|
|
@@ -366,6 +365,8 @@ module Sentry
|
|
|
366
365
|
SERVER_PORT
|
|
367
366
|
].freeze
|
|
368
367
|
|
|
368
|
+
TRACE_IGNORE_STATUS_CODES_DEFAULT = [(301..303), (305..399), (401..404)]
|
|
369
|
+
|
|
369
370
|
HEROKU_DYNO_METADATA_MESSAGE = "You are running on Heroku but haven't enabled Dyno Metadata. For Sentry's "\
|
|
370
371
|
"release detection to work correctly, please run `heroku labs:enable runtime-dyno-metadata`"
|
|
371
372
|
|
|
@@ -381,6 +382,9 @@ module Sentry
|
|
|
381
382
|
|
|
382
383
|
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/
|
|
383
384
|
|
|
385
|
+
# 101 Hz in microseconds
|
|
386
|
+
DEFAULT_PROFILES_SAMPLE_INTERVAL = 1e6 / 101
|
|
387
|
+
|
|
384
388
|
class << self
|
|
385
389
|
# Post initialization callbacks are called at the end of initialization process
|
|
386
390
|
# allowing extending the configuration of sentry-ruby by multiple extensions
|
|
@@ -390,7 +394,23 @@ module Sentry
|
|
|
390
394
|
|
|
391
395
|
# allow extensions to add their hooks to the Configuration class
|
|
392
396
|
def add_post_initialization_callback(&block)
|
|
393
|
-
|
|
397
|
+
callbacks[:initialize][:after] << block
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def before(event, &block)
|
|
401
|
+
callbacks[event.to_sym][:before] << block
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def after(event, &block)
|
|
405
|
+
callbacks[event.to_sym][:after] << block
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# @!visibility private
|
|
409
|
+
def callbacks
|
|
410
|
+
@callbacks ||= {
|
|
411
|
+
initialize: { before: [], after: [] },
|
|
412
|
+
configured: { before: [], after: [] }
|
|
413
|
+
}
|
|
394
414
|
end
|
|
395
415
|
|
|
396
416
|
def validations
|
|
@@ -434,6 +454,8 @@ module Sentry
|
|
|
434
454
|
validate :profiles_sample_rate, optional: true, type: :numeric
|
|
435
455
|
|
|
436
456
|
def initialize
|
|
457
|
+
run_callbacks(:before, :initialize)
|
|
458
|
+
|
|
437
459
|
self.app_dirs_pattern = APP_DIRS_PATTERN
|
|
438
460
|
self.debug = Sentry::Utils::EnvHelper.env_to_bool(ENV["SENTRY_DEBUG"])
|
|
439
461
|
self.background_worker_threads = (processor_count / 2.0).ceil
|
|
@@ -445,7 +467,7 @@ module Sentry
|
|
|
445
467
|
self.context_lines = 3
|
|
446
468
|
self.include_local_variables = false
|
|
447
469
|
self.environment = environment_from_env
|
|
448
|
-
self.enabled_environments =
|
|
470
|
+
self.enabled_environments = nil
|
|
449
471
|
self.exclude_loggers = []
|
|
450
472
|
self.excluded_exceptions = IGNORE_DEFAULT + PUMA_IGNORE_DEFAULT
|
|
451
473
|
self.inspect_exception_causes_for_exclusion = true
|
|
@@ -470,26 +492,32 @@ module Sentry
|
|
|
470
492
|
self.server_name = server_name_from_env
|
|
471
493
|
self.instrumenter = :sentry
|
|
472
494
|
self.trace_propagation_targets = [PROPAGATION_TARGETS_MATCH_ALL]
|
|
495
|
+
self.trace_ignore_status_codes = TRACE_IGNORE_STATUS_CODES_DEFAULT
|
|
473
496
|
self.enabled_patches = DEFAULT_PATCHES.dup
|
|
474
497
|
|
|
475
498
|
self.before_send = nil
|
|
476
499
|
self.before_send_transaction = nil
|
|
500
|
+
self.before_send_check_in = nil
|
|
477
501
|
self.before_send_log = nil
|
|
478
502
|
self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
|
|
479
503
|
self.traces_sampler = nil
|
|
480
|
-
self.enable_tracing = nil
|
|
481
504
|
self.enable_logs = false
|
|
482
505
|
|
|
483
506
|
self.profiler_class = Sentry::Profiler
|
|
507
|
+
self.profiles_sample_interval = DEFAULT_PROFILES_SAMPLE_INTERVAL
|
|
484
508
|
|
|
485
509
|
@transport = Transport::Configuration.new
|
|
486
510
|
@cron = Cron::Configuration.new
|
|
487
|
-
@
|
|
511
|
+
@structured_logging = StructuredLoggingConfiguration.new
|
|
488
512
|
@gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
|
489
513
|
|
|
490
|
-
run_post_initialization_callbacks
|
|
491
|
-
|
|
492
514
|
self.max_log_events = LogEventBuffer::DEFAULT_MAX_EVENTS
|
|
515
|
+
|
|
516
|
+
run_callbacks(:after, :initialize)
|
|
517
|
+
|
|
518
|
+
yield(self) if block_given?
|
|
519
|
+
|
|
520
|
+
run_callbacks(:after, :configured)
|
|
493
521
|
end
|
|
494
522
|
|
|
495
523
|
def validate
|
|
@@ -522,22 +550,6 @@ module Sentry
|
|
|
522
550
|
@release = value
|
|
523
551
|
end
|
|
524
552
|
|
|
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
553
|
def breadcrumbs_logger=(logger)
|
|
542
554
|
loggers =
|
|
543
555
|
if logger.is_a?(Array)
|
|
@@ -563,6 +575,12 @@ module Sentry
|
|
|
563
575
|
@before_send_transaction = value
|
|
564
576
|
end
|
|
565
577
|
|
|
578
|
+
def before_send_check_in=(value)
|
|
579
|
+
check_callable!("before_send_check_in", value)
|
|
580
|
+
|
|
581
|
+
@before_send_check_in = value
|
|
582
|
+
end
|
|
583
|
+
|
|
566
584
|
def before_breadcrumb=(value)
|
|
567
585
|
check_callable!("before_breadcrumb", value)
|
|
568
586
|
|
|
@@ -577,15 +595,12 @@ module Sentry
|
|
|
577
595
|
@instrumenter = INSTRUMENTERS.include?(instrumenter) ? instrumenter : :sentry
|
|
578
596
|
end
|
|
579
597
|
|
|
580
|
-
def
|
|
581
|
-
unless
|
|
582
|
-
|
|
583
|
-
`enable_tracing` is now deprecated in favor of `traces_sample_rate = 1.0`.
|
|
584
|
-
MSG
|
|
598
|
+
def trace_ignore_status_codes=(codes)
|
|
599
|
+
unless codes.is_a?(Array) && codes.all? { |code| valid_status_code_entry?(code) }
|
|
600
|
+
raise ArgumentError, "trace_ignore_status_codes must be an Array of integers or ranges between (100-599) where begin <= end"
|
|
585
601
|
end
|
|
586
602
|
|
|
587
|
-
@
|
|
588
|
-
@traces_sample_rate ||= 1.0 if enable_tracing
|
|
603
|
+
@trace_ignore_status_codes = codes
|
|
589
604
|
end
|
|
590
605
|
|
|
591
606
|
def traces_sample_rate=(traces_sample_rate)
|
|
@@ -641,7 +656,7 @@ module Sentry
|
|
|
641
656
|
end
|
|
642
657
|
|
|
643
658
|
def enabled_in_current_env?
|
|
644
|
-
enabled_environments.
|
|
659
|
+
enabled_environments.nil? || enabled_environments.include?(environment)
|
|
645
660
|
end
|
|
646
661
|
|
|
647
662
|
def valid_sample_rate?(sample_rate)
|
|
@@ -652,7 +667,7 @@ module Sentry
|
|
|
652
667
|
def tracing_enabled?
|
|
653
668
|
valid_sampler = !!((valid_sample_rate?(@traces_sample_rate)) || @traces_sampler)
|
|
654
669
|
|
|
655
|
-
|
|
670
|
+
valid_sampler && sending_allowed?
|
|
656
671
|
end
|
|
657
672
|
|
|
658
673
|
def profiling_enabled?
|
|
@@ -773,8 +788,8 @@ module Sentry
|
|
|
773
788
|
File.directory?("/etc/heroku") && !ENV["CI"]
|
|
774
789
|
end
|
|
775
790
|
|
|
776
|
-
def
|
|
777
|
-
self.class.
|
|
791
|
+
def run_callbacks(hook, event)
|
|
792
|
+
self.class.callbacks[event][hook].each do |hook|
|
|
778
793
|
instance_eval(&hook)
|
|
779
794
|
end
|
|
780
795
|
end
|
|
@@ -783,5 +798,37 @@ module Sentry
|
|
|
783
798
|
available_processor_count = Concurrent.available_processor_count if Concurrent.respond_to?(:available_processor_count)
|
|
784
799
|
available_processor_count || Concurrent.processor_count
|
|
785
800
|
end
|
|
801
|
+
|
|
802
|
+
def valid_http_status_code?(code)
|
|
803
|
+
code.is_a?(Integer) && code >= 100 && code <= 599
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
def valid_status_code_entry?(entry)
|
|
807
|
+
case entry
|
|
808
|
+
when Integer
|
|
809
|
+
valid_http_status_code?(entry)
|
|
810
|
+
when Range
|
|
811
|
+
valid_http_status_code?(entry.begin) &&
|
|
812
|
+
valid_http_status_code?(entry.end) &&
|
|
813
|
+
entry.begin <= entry.end
|
|
814
|
+
else
|
|
815
|
+
false
|
|
816
|
+
end
|
|
817
|
+
end
|
|
818
|
+
end
|
|
819
|
+
|
|
820
|
+
class StructuredLoggingConfiguration
|
|
821
|
+
# File path for DebugStructuredLogger to log events to
|
|
822
|
+
# @return [String, Pathname, nil]
|
|
823
|
+
attr_accessor :file_path
|
|
824
|
+
|
|
825
|
+
# The class to use as a structured logger.
|
|
826
|
+
# @return [Class]
|
|
827
|
+
attr_accessor :logger_class
|
|
828
|
+
|
|
829
|
+
def initialize
|
|
830
|
+
@file_path = nil
|
|
831
|
+
@logger_class = Sentry::StructuredLogger
|
|
832
|
+
end
|
|
786
833
|
end
|
|
787
834
|
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
|
data/lib/sentry/dsn.rb
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "uri"
|
|
4
|
+
require "ipaddr"
|
|
5
|
+
require "resolv"
|
|
4
6
|
|
|
5
7
|
module Sentry
|
|
6
8
|
class DSN
|
|
7
9
|
PORT_MAP = { "http" => 80, "https" => 443 }.freeze
|
|
8
10
|
REQUIRED_ATTRIBUTES = %w[host path public_key project_id].freeze
|
|
11
|
+
LOCALHOST_NAMES = %w[localhost 127.0.0.1 ::1 [::1]].freeze
|
|
12
|
+
LOCALHOST_PATTERN = /\.local(host|domain)?$/i
|
|
9
13
|
|
|
10
14
|
attr_reader :scheme, :secret_key, :port, *REQUIRED_ATTRIBUTES
|
|
11
15
|
|
|
@@ -49,5 +53,33 @@ module Sentry
|
|
|
49
53
|
def envelope_endpoint
|
|
50
54
|
"#{path}/api/#{project_id}/envelope/"
|
|
51
55
|
end
|
|
56
|
+
|
|
57
|
+
def local?
|
|
58
|
+
@local ||= (localhost? || private_ip? || resolved_ips_private?)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def localhost?
|
|
62
|
+
LOCALHOST_NAMES.include?(host.downcase) || LOCALHOST_PATTERN.match?(host)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def private_ip?
|
|
66
|
+
@private_ip ||= begin
|
|
67
|
+
begin
|
|
68
|
+
IPAddr.new(host).private?
|
|
69
|
+
rescue IPAddr::InvalidAddressError
|
|
70
|
+
false
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def resolved_ips_private?
|
|
76
|
+
@resolved_ips_private ||= begin
|
|
77
|
+
begin
|
|
78
|
+
Resolv.getaddresses(host).any? { |ip| IPAddr.new(ip).private? }
|
|
79
|
+
rescue Resolv::ResolvError, IPAddr::InvalidAddressError
|
|
80
|
+
false
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
52
84
|
end
|
|
53
85
|
end
|
data/lib/sentry/envelope/item.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Sentry
|
|
4
4
|
# @api private
|
|
5
5
|
class Envelope::Item
|
|
6
|
-
STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD =
|
|
6
|
+
STACKTRACE_FRAME_LIMIT_ON_OVERSIZED_PAYLOAD = 1000
|
|
7
7
|
MAX_SERIALIZED_PAYLOAD_SIZE = 1024 * 1000
|
|
8
8
|
|
|
9
9
|
SIZE_LIMITS = Hash.new(MAX_SERIALIZED_PAYLOAD_SIZE).update(
|
|
@@ -18,7 +18,6 @@ module Sentry
|
|
|
18
18
|
when "session", "attachment", "transaction", "profile", "span", "log" then type
|
|
19
19
|
when "sessions" then "session"
|
|
20
20
|
when "check_in" then "monitor"
|
|
21
|
-
when "statsd", "metric_meta" then "metric_bucket"
|
|
22
21
|
when "event" then "error"
|
|
23
22
|
when "client_report" then "internal"
|
|
24
23
|
else "default"
|
data/lib/sentry/error_event.rb
CHANGED
|
@@ -10,10 +10,10 @@ module Sentry
|
|
|
10
10
|
attr_reader :threads
|
|
11
11
|
|
|
12
12
|
# @return [Hash]
|
|
13
|
-
def
|
|
13
|
+
def to_h
|
|
14
14
|
data = super
|
|
15
|
-
data[:threads] = threads.
|
|
16
|
-
data[:exception] = exception.
|
|
15
|
+
data[:threads] = threads.to_h if threads
|
|
16
|
+
data[:exception] = exception.to_h if exception
|
|
17
17
|
data
|
|
18
18
|
end
|
|
19
19
|
|
data/lib/sentry/event.rb
CHANGED
|
@@ -81,12 +81,6 @@ module Sentry
|
|
|
81
81
|
@message = (message || "").byteslice(0..MAX_MESSAGE_SIZE_IN_BYTES)
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
# @deprecated This method will be removed in v5.0.0. Please just use Sentry.configuration
|
|
85
|
-
# @return [Configuration]
|
|
86
|
-
def configuration
|
|
87
|
-
Sentry.configuration
|
|
88
|
-
end
|
|
89
|
-
|
|
90
84
|
# Sets the event's timestamp.
|
|
91
85
|
# @param time [Time, Float]
|
|
92
86
|
# @return [void]
|
|
@@ -118,16 +112,16 @@ module Sentry
|
|
|
118
112
|
end
|
|
119
113
|
|
|
120
114
|
# @return [Hash]
|
|
121
|
-
def
|
|
115
|
+
def to_h
|
|
122
116
|
data = serialize_attributes
|
|
123
|
-
data[:breadcrumbs] = breadcrumbs.
|
|
124
|
-
data[:request] = request.
|
|
117
|
+
data[:breadcrumbs] = breadcrumbs.to_h if breadcrumbs
|
|
118
|
+
data[:request] = request.to_h if request
|
|
125
119
|
data
|
|
126
120
|
end
|
|
127
121
|
|
|
128
122
|
# @return [Hash]
|
|
129
123
|
def to_json_compatible
|
|
130
|
-
JSON.parse(JSON.generate(
|
|
124
|
+
JSON.parse(JSON.generate(to_h))
|
|
131
125
|
end
|
|
132
126
|
|
|
133
127
|
private
|
data/lib/sentry/graphql.rb
CHANGED
|
@@ -4,6 +4,6 @@ Sentry.register_patch(:graphql) do |config|
|
|
|
4
4
|
if defined?(::GraphQL::Schema) && defined?(::GraphQL::Tracing::SentryTrace) && ::GraphQL::Schema.respond_to?(:trace_with)
|
|
5
5
|
::GraphQL::Schema.trace_with(::GraphQL::Tracing::SentryTrace, set_transaction_name: true)
|
|
6
6
|
else
|
|
7
|
-
config.
|
|
7
|
+
config.sdk_logger.warn(Sentry::LOGGER_PROGNAME) { "You tried to enable the GraphQL integration but no GraphQL gem was detected. Make sure you have the `graphql` gem (>= 2.2.6) in your Gemfile." }
|
|
8
8
|
end
|
|
9
9
|
end
|