bugsnag 6.19.0 → 6.26.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/.yardopts +1 -0
- data/CHANGELOG.md +176 -0
- data/VERSION +1 -1
- data/bugsnag.gemspec +18 -1
- data/lib/bugsnag/breadcrumb_type.rb +14 -0
- data/lib/bugsnag/breadcrumbs/breadcrumb.rb +34 -1
- data/lib/bugsnag/breadcrumbs/breadcrumbs.rb +1 -0
- data/lib/bugsnag/breadcrumbs/on_breadcrumb_callback_list.rb +50 -0
- data/lib/bugsnag/cleaner.rb +31 -18
- data/lib/bugsnag/configuration.rb +243 -25
- data/lib/bugsnag/delivery/synchronous.rb +2 -2
- data/lib/bugsnag/delivery/thread_queue.rb +2 -2
- data/lib/bugsnag/endpoint_configuration.rb +11 -0
- data/lib/bugsnag/endpoint_validator.rb +80 -0
- data/lib/bugsnag/error.rb +25 -0
- data/lib/bugsnag/event.rb +7 -0
- data/lib/bugsnag/feature_flag.rb +74 -0
- data/lib/bugsnag/integrations/mongo.rb +5 -3
- data/lib/bugsnag/integrations/rack.rb +3 -3
- data/lib/bugsnag/integrations/rails/active_job.rb +102 -0
- data/lib/bugsnag/integrations/rails/rails_breadcrumbs.rb +2 -0
- data/lib/bugsnag/integrations/railtie.rb +70 -27
- data/lib/bugsnag/integrations/resque.rb +17 -3
- data/lib/bugsnag/integrations/sidekiq.rb +1 -0
- data/lib/bugsnag/middleware/active_job.rb +18 -0
- data/lib/bugsnag/middleware/classify_error.rb +1 -0
- data/lib/bugsnag/middleware/delayed_job.rb +21 -2
- data/lib/bugsnag/middleware/exception_meta_data.rb +2 -0
- data/lib/bugsnag/middleware/rack_request.rb +84 -19
- data/lib/bugsnag/middleware/rails3_request.rb +2 -2
- data/lib/bugsnag/middleware/rake.rb +1 -1
- data/lib/bugsnag/middleware/session_data.rb +3 -1
- data/lib/bugsnag/middleware/sidekiq.rb +1 -1
- data/lib/bugsnag/middleware/suggestion_data.rb +9 -7
- data/lib/bugsnag/middleware_stack.rb +6 -6
- data/lib/bugsnag/report.rb +204 -8
- data/lib/bugsnag/session_tracker.rb +52 -12
- data/lib/bugsnag/stacktrace.rb +13 -2
- data/lib/bugsnag/tasks/bugsnag.rake +1 -1
- data/lib/bugsnag/utility/duplicator.rb +124 -0
- data/lib/bugsnag/utility/feature_data_store.rb +41 -0
- data/lib/bugsnag/utility/feature_flag_delegate.rb +89 -0
- data/lib/bugsnag/utility/metadata_delegate.rb +102 -0
- data/lib/bugsnag.rb +156 -8
- metadata +24 -7
@@ -12,6 +12,9 @@ require "bugsnag/middleware/session_data"
|
|
12
12
|
require "bugsnag/middleware/breadcrumbs"
|
13
13
|
require "bugsnag/utility/circular_buffer"
|
14
14
|
require "bugsnag/breadcrumbs/breadcrumbs"
|
15
|
+
require "bugsnag/breadcrumbs/on_breadcrumb_callback_list"
|
16
|
+
require "bugsnag/endpoint_configuration"
|
17
|
+
require "bugsnag/endpoint_validator"
|
15
18
|
|
16
19
|
module Bugsnag
|
17
20
|
class Configuration
|
@@ -24,6 +27,7 @@ module Bugsnag
|
|
24
27
|
attr_accessor :release_stage
|
25
28
|
|
26
29
|
# A list of which release stages should cause notifications to be sent
|
30
|
+
# @deprecated Use {#enabled_release_stages} instead
|
27
31
|
# @return [Array<String>, nil]
|
28
32
|
attr_accessor :notify_release_stages
|
29
33
|
|
@@ -52,9 +56,20 @@ module Bugsnag
|
|
52
56
|
|
53
57
|
# A list of keys that should be filtered out from the report and breadcrumb
|
54
58
|
# metadata before sending them to Bugsnag
|
59
|
+
# @deprecated Use {#redacted_keys} instead
|
55
60
|
# @return [Set<String, Regexp>]
|
56
61
|
attr_accessor :meta_data_filters
|
57
62
|
|
63
|
+
# A set of keys that should be redacted from the report and breadcrumb
|
64
|
+
# metadata before sending them to Bugsnag
|
65
|
+
#
|
66
|
+
# When adding strings, keys that are equal to the string (ignoring case)
|
67
|
+
# will be redacted. When adding regular expressions, any keys which match
|
68
|
+
# the regular expression will be redacted
|
69
|
+
#
|
70
|
+
# @return [Set<String, Regexp>]
|
71
|
+
attr_accessor :redacted_keys
|
72
|
+
|
58
73
|
# The logger to use for Bugsnag log messages
|
59
74
|
# @return [Logger]
|
60
75
|
attr_accessor :logger
|
@@ -104,6 +119,7 @@ module Bugsnag
|
|
104
119
|
attr_accessor :discard_classes
|
105
120
|
|
106
121
|
# Whether Bugsnag should automatically record sessions
|
122
|
+
# @deprecated Use {#auto_track_sessions} instead
|
107
123
|
# @return [Boolean]
|
108
124
|
attr_accessor :auto_capture_sessions
|
109
125
|
|
@@ -111,21 +127,23 @@ module Bugsnag
|
|
111
127
|
# @return [Set<Class, Proc>]
|
112
128
|
attr_accessor :ignore_classes
|
113
129
|
|
114
|
-
# The
|
115
|
-
# @return [
|
116
|
-
attr_reader :
|
117
|
-
alias :endpoint :notify_endpoint
|
130
|
+
# The URLs to send events and sessions to
|
131
|
+
# @return [EndpointConfiguration]
|
132
|
+
attr_reader :endpoints
|
118
133
|
|
119
|
-
#
|
120
|
-
# @
|
121
|
-
|
134
|
+
# Whether events will be delivered
|
135
|
+
# @api private
|
136
|
+
# @return [Boolean]
|
137
|
+
attr_reader :enable_events
|
122
138
|
|
123
139
|
# Whether sessions will be delivered
|
140
|
+
# @api private
|
124
141
|
# @return [Boolean]
|
125
142
|
attr_reader :enable_sessions
|
126
143
|
|
127
144
|
# A list of strings indicating allowable automatic breadcrumb types
|
128
|
-
# @
|
145
|
+
# @deprecated Use {#enabled_breadcrumb_types} instead
|
146
|
+
# @see Bugsnag::BreadcrumbType
|
129
147
|
# @return [Array<String>]
|
130
148
|
attr_accessor :enabled_automatic_breadcrumb_types
|
131
149
|
|
@@ -137,14 +155,37 @@ module Bugsnag
|
|
137
155
|
# @return [Integer]
|
138
156
|
attr_reader :max_breadcrumbs
|
139
157
|
|
140
|
-
#
|
158
|
+
# @deprecated Use {vendor_paths} instead
|
141
159
|
# @return [Regexp]
|
142
160
|
attr_accessor :vendor_path
|
143
161
|
|
162
|
+
# An array of paths within the {project_root} that should not be considered
|
163
|
+
# as "in project"
|
164
|
+
#
|
165
|
+
# These paths should be relative to the {project_root} and will only match
|
166
|
+
# whole directory names
|
167
|
+
#
|
168
|
+
# @return [Array<String>]
|
169
|
+
attr_accessor :vendor_paths
|
170
|
+
|
171
|
+
# The default context for all future events
|
172
|
+
# Setting this will disable automatic context setting
|
173
|
+
# @return [String, nil]
|
174
|
+
attr_accessor :context
|
175
|
+
|
176
|
+
# Global metadata added to every event
|
177
|
+
# @return [Hash]
|
178
|
+
attr_reader :metadata
|
179
|
+
|
144
180
|
# @api private
|
145
181
|
# @return [Array<String>]
|
146
182
|
attr_reader :scopes_to_filter
|
147
183
|
|
184
|
+
# Expose on_breadcrumb_callbacks internally for Bugsnag.leave_breadcrumb
|
185
|
+
# @api private
|
186
|
+
# @return [Breadcrumbs::OnBreadcrumbCallbackList]
|
187
|
+
attr_reader :on_breadcrumb_callbacks
|
188
|
+
|
148
189
|
API_KEY_REGEX = /[0-9a-f]{32}/i
|
149
190
|
THREAD_LOCAL_NAME = "bugsnag_req_data"
|
150
191
|
|
@@ -180,6 +221,7 @@ module Bugsnag
|
|
180
221
|
self.send_environment = false
|
181
222
|
self.send_code = true
|
182
223
|
self.meta_data_filters = Set.new(DEFAULT_META_DATA_FILTERS)
|
224
|
+
@redacted_keys = Set.new
|
183
225
|
self.scopes_to_filter = DEFAULT_SCOPES_TO_FILTER
|
184
226
|
self.hostname = default_hostname
|
185
227
|
self.runtime_versions = {}
|
@@ -193,16 +235,20 @@ module Bugsnag
|
|
193
235
|
# All valid breadcrumb types should be allowable initially
|
194
236
|
self.enabled_automatic_breadcrumb_types = Bugsnag::Breadcrumbs::VALID_BREADCRUMB_TYPES.dup
|
195
237
|
self.before_breadcrumb_callbacks = []
|
238
|
+
@on_breadcrumb_callbacks = Breadcrumbs::OnBreadcrumbCallbackList.new(self)
|
196
239
|
|
197
240
|
# Store max_breadcrumbs here instead of outputting breadcrumbs.max_items
|
198
241
|
# to avoid infinite recursion when creating breadcrumb buffer
|
199
242
|
@max_breadcrumbs = DEFAULT_MAX_BREADCRUMBS
|
200
243
|
|
201
|
-
|
202
|
-
|
203
|
-
@
|
244
|
+
@endpoints = EndpointConfiguration.new(DEFAULT_NOTIFY_ENDPOINT, DEFAULT_SESSION_ENDPOINT)
|
245
|
+
|
246
|
+
@enable_events = true
|
204
247
|
@enable_sessions = true
|
205
248
|
|
249
|
+
@metadata = {}
|
250
|
+
@metadata_delegate = Utility::MetadataDelegate.new
|
251
|
+
|
206
252
|
# SystemExit and SignalException are common Exception types seen with
|
207
253
|
# successful exits and are not automatically reported to Bugsnag
|
208
254
|
# TODO move these defaults into `discard_classes` when `ignore_classes`
|
@@ -222,6 +268,7 @@ module Bugsnag
|
|
222
268
|
# Stacktrace lines that matches regex will be marked as "out of project"
|
223
269
|
# will only appear in the full trace.
|
224
270
|
self.vendor_path = DEFAULT_VENDOR_PATH
|
271
|
+
@vendor_paths = []
|
225
272
|
|
226
273
|
# Set up logging
|
227
274
|
self.logger = Logger.new(STDOUT)
|
@@ -389,15 +436,23 @@ module Bugsnag
|
|
389
436
|
##
|
390
437
|
# Logs a warning level message
|
391
438
|
#
|
392
|
-
# @param
|
439
|
+
# @param message [String, #to_s] The message to log
|
393
440
|
def warn(message)
|
394
441
|
logger.warn(PROG_NAME) { message }
|
395
442
|
end
|
396
443
|
|
444
|
+
##
|
445
|
+
# Logs an error level message
|
446
|
+
#
|
447
|
+
# @param message [String, #to_s] The message to log
|
448
|
+
def error(message)
|
449
|
+
logger.error(PROG_NAME) { message }
|
450
|
+
end
|
451
|
+
|
397
452
|
##
|
398
453
|
# Logs a debug level message
|
399
454
|
#
|
400
|
-
# @param
|
455
|
+
# @param message [String, #to_s] The message to log
|
401
456
|
def debug(message)
|
402
457
|
logger.debug(PROG_NAME) { message }
|
403
458
|
end
|
@@ -426,33 +481,54 @@ module Bugsnag
|
|
426
481
|
end
|
427
482
|
|
428
483
|
##
|
429
|
-
# Returns the
|
484
|
+
# Returns the current list of breadcrumbs
|
485
|
+
#
|
486
|
+
# This is a per-thread circular buffer, containing at most 'max_breadcrumbs'
|
487
|
+
# breadcrumbs
|
430
488
|
#
|
431
|
-
# @return [Bugsnag::Utility::CircularBuffer]
|
489
|
+
# @return [Bugsnag::Utility::CircularBuffer]
|
432
490
|
def breadcrumbs
|
433
491
|
request_data[:breadcrumbs] ||= Bugsnag::Utility::CircularBuffer.new(@max_breadcrumbs)
|
434
492
|
end
|
435
493
|
|
494
|
+
# The URL error notifications will be delivered to
|
495
|
+
# @!attribute notify_endpoint
|
496
|
+
# @return [String]
|
497
|
+
# @deprecated Use {#endpoints} instead
|
498
|
+
def notify_endpoint
|
499
|
+
@endpoints.notify
|
500
|
+
end
|
501
|
+
|
502
|
+
alias :endpoint :notify_endpoint
|
503
|
+
|
436
504
|
# Sets the notification endpoint
|
437
505
|
#
|
438
|
-
# @deprecated Use {#
|
506
|
+
# @deprecated Use {#endpoints} instead
|
439
507
|
#
|
440
508
|
# @param new_notify_endpoint [String] The URL to deliver error notifications to
|
441
509
|
# @return [void]
|
442
510
|
def endpoint=(new_notify_endpoint)
|
443
|
-
warn("The 'endpoint' configuration option is deprecated.
|
511
|
+
warn("The 'endpoint' configuration option is deprecated. Set both endpoints with the 'endpoints=' method instead")
|
444
512
|
set_endpoints(new_notify_endpoint, session_endpoint) # Pass the existing session_endpoint through so it doesn't get overwritten
|
445
513
|
end
|
446
514
|
|
515
|
+
# The URL session notifications will be delivered to
|
516
|
+
# @!attribute session_endpoint
|
517
|
+
# @return [String]
|
518
|
+
# @deprecated Use {#endpoints} instead
|
519
|
+
def session_endpoint
|
520
|
+
@endpoints.sessions
|
521
|
+
end
|
522
|
+
|
447
523
|
##
|
448
524
|
# Sets the sessions endpoint
|
449
525
|
#
|
450
|
-
# @deprecated Use {#
|
526
|
+
# @deprecated Use {#endpoints} instead
|
451
527
|
#
|
452
528
|
# @param new_session_endpoint [String] The URL to deliver session notifications to
|
453
529
|
# @return [void]
|
454
530
|
def session_endpoint=(new_session_endpoint)
|
455
|
-
warn("The 'session_endpoint' configuration option is deprecated.
|
531
|
+
warn("The 'session_endpoint' configuration option is deprecated. Set both endpoints with the 'endpoints=' method instead")
|
456
532
|
set_endpoints(notify_endpoint, new_session_endpoint) # Pass the existing notify_endpoint through so it doesn't get overwritten
|
457
533
|
end
|
458
534
|
|
@@ -462,9 +538,26 @@ module Bugsnag
|
|
462
538
|
# @param new_notify_endpoint [String] The URL to deliver error notifications to
|
463
539
|
# @param new_session_endpoint [String] The URL to deliver session notifications to
|
464
540
|
# @return [void]
|
541
|
+
# @deprecated Use {#endpoints} instead
|
465
542
|
def set_endpoints(new_notify_endpoint, new_session_endpoint)
|
466
|
-
|
467
|
-
|
543
|
+
self.endpoints = EndpointConfiguration.new(new_notify_endpoint, new_session_endpoint)
|
544
|
+
end
|
545
|
+
|
546
|
+
def endpoints=(endpoint_configuration)
|
547
|
+
result = EndpointValidator.validate(endpoint_configuration)
|
548
|
+
|
549
|
+
if result.valid?
|
550
|
+
@enable_events = true
|
551
|
+
@enable_sessions = true
|
552
|
+
else
|
553
|
+
warn(result.reason)
|
554
|
+
|
555
|
+
@enable_events = result.keep_events_enabled_for_backwards_compatibility?
|
556
|
+
@enable_sessions = false
|
557
|
+
end
|
558
|
+
|
559
|
+
# use the given endpoints even if they are invalid
|
560
|
+
@endpoints = endpoint_configuration
|
468
561
|
end
|
469
562
|
|
470
563
|
##
|
@@ -485,7 +578,7 @@ module Bugsnag
|
|
485
578
|
# Returning false from an on_error callback will cause the error to be ignored
|
486
579
|
# and will prevent any remaining callbacks from being called
|
487
580
|
#
|
488
|
-
# @param callback [Proc]
|
581
|
+
# @param callback [Proc, Method, #call]
|
489
582
|
# @return [void]
|
490
583
|
def add_on_error(callback)
|
491
584
|
middleware.use(callback)
|
@@ -494,15 +587,140 @@ module Bugsnag
|
|
494
587
|
##
|
495
588
|
# Remove the given callback from the list of on_error callbacks
|
496
589
|
#
|
497
|
-
# Note that this must be the same
|
590
|
+
# Note that this must be the same instance that was passed to
|
498
591
|
# {#add_on_error}, otherwise it will not be removed
|
499
592
|
#
|
500
|
-
# @param callback [Proc]
|
593
|
+
# @param callback [Proc, Method, #call]
|
501
594
|
# @return [void]
|
502
595
|
def remove_on_error(callback)
|
503
596
|
middleware.remove(callback)
|
504
597
|
end
|
505
598
|
|
599
|
+
##
|
600
|
+
# Add the given callback to the list of on_breadcrumb callbacks
|
601
|
+
#
|
602
|
+
# The on_breadcrumb callbacks will be called when a breadcrumb is left and
|
603
|
+
# are passed the {Breadcrumbs::Breadcrumb Breadcrumb} object
|
604
|
+
#
|
605
|
+
# Returning false from an on_breadcrumb callback will cause the breadcrumb
|
606
|
+
# to be ignored and will prevent any remaining callbacks from being called
|
607
|
+
#
|
608
|
+
# @param callback [Proc, Method, #call]
|
609
|
+
# @return [void]
|
610
|
+
def add_on_breadcrumb(callback)
|
611
|
+
@on_breadcrumb_callbacks.add(callback)
|
612
|
+
end
|
613
|
+
|
614
|
+
##
|
615
|
+
# Remove the given callback from the list of on_breadcrumb callbacks
|
616
|
+
#
|
617
|
+
# Note that this must be the same instance that was passed to
|
618
|
+
# {add_on_breadcrumb}, otherwise it will not be removed
|
619
|
+
#
|
620
|
+
# @param callback [Proc, Method, #call]
|
621
|
+
# @return [void]
|
622
|
+
def remove_on_breadcrumb(callback)
|
623
|
+
@on_breadcrumb_callbacks.remove(callback)
|
624
|
+
end
|
625
|
+
|
626
|
+
##
|
627
|
+
# Add values to metadata
|
628
|
+
#
|
629
|
+
# @overload add_metadata(section, data)
|
630
|
+
# Merges data into the given section of metadata
|
631
|
+
# @param section [String, Symbol]
|
632
|
+
# @param data [Hash]
|
633
|
+
#
|
634
|
+
# @overload add_metadata(section, key, value)
|
635
|
+
# Sets key to value in the given section of metadata. If the value is nil
|
636
|
+
# the key will be deleted
|
637
|
+
# @param section [String, Symbol]
|
638
|
+
# @param key [String, Symbol]
|
639
|
+
# @param value
|
640
|
+
#
|
641
|
+
# @return [void]
|
642
|
+
def add_metadata(section, key_or_data, *args)
|
643
|
+
@mutex.synchronize do
|
644
|
+
@metadata_delegate.add_metadata(@metadata, section, key_or_data, *args)
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
##
|
649
|
+
# Clear values from metadata
|
650
|
+
#
|
651
|
+
# @overload clear_metadata(section)
|
652
|
+
# Clears the given section of metadata
|
653
|
+
# @param section [String, Symbol]
|
654
|
+
#
|
655
|
+
# @overload clear_metadata(section, key)
|
656
|
+
# Clears the key in the given section of metadata
|
657
|
+
# @param section [String, Symbol]
|
658
|
+
# @param key [String, Symbol]
|
659
|
+
#
|
660
|
+
# @return [void]
|
661
|
+
def clear_metadata(section, *args)
|
662
|
+
@mutex.synchronize do
|
663
|
+
@metadata_delegate.clear_metadata(@metadata, section, *args)
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
##
|
668
|
+
# Has the context been explicitly set?
|
669
|
+
#
|
670
|
+
# This is necessary to differentiate between the context not being set and
|
671
|
+
# the context being set to 'nil' explicitly
|
672
|
+
#
|
673
|
+
# @api private
|
674
|
+
# @return [Boolean]
|
675
|
+
def context_set?
|
676
|
+
defined?(@context) != nil
|
677
|
+
end
|
678
|
+
|
679
|
+
# TODO: These methods can be a simple attr_accessor when they replace the
|
680
|
+
# methods they are aliasing
|
681
|
+
# NOTE: they are not aliases as YARD doesn't allow documenting the non-alias
|
682
|
+
# as deprecated without also marking the alias as deprecated
|
683
|
+
|
684
|
+
# A list of which release stages should cause notifications to be sent
|
685
|
+
# @!attribute enabled_release_stages
|
686
|
+
# @return [Array<String>, nil]
|
687
|
+
def enabled_release_stages
|
688
|
+
@notify_release_stages
|
689
|
+
end
|
690
|
+
|
691
|
+
# @param release_stages [Array<String>, nil]
|
692
|
+
# @return [void]
|
693
|
+
def enabled_release_stages=(release_stages)
|
694
|
+
@notify_release_stages = release_stages
|
695
|
+
end
|
696
|
+
|
697
|
+
# A list of breadcrumb types that Bugsnag will collect automatically
|
698
|
+
# @!attribute enabled_breadcrumb_types
|
699
|
+
# @see Bugsnag::BreadcrumbType
|
700
|
+
# @return [Array<String>]
|
701
|
+
def enabled_breadcrumb_types
|
702
|
+
@enabled_automatic_breadcrumb_types
|
703
|
+
end
|
704
|
+
|
705
|
+
# @param breadcrumb_types [Array<String>]
|
706
|
+
# @return [void]
|
707
|
+
def enabled_breadcrumb_types=(breadcrumb_types)
|
708
|
+
@enabled_automatic_breadcrumb_types = breadcrumb_types
|
709
|
+
end
|
710
|
+
|
711
|
+
# Whether sessions should be tracked automatically
|
712
|
+
# @!attribute auto_track_sessions
|
713
|
+
# @return [Boolean]
|
714
|
+
def auto_track_sessions
|
715
|
+
@auto_capture_sessions
|
716
|
+
end
|
717
|
+
|
718
|
+
# @param track_sessions [Boolean]
|
719
|
+
# @return [void]
|
720
|
+
def auto_track_sessions=(track_sessions)
|
721
|
+
@auto_capture_sessions = track_sessions
|
722
|
+
end
|
723
|
+
|
506
724
|
private
|
507
725
|
|
508
726
|
attr_writer :scopes_to_filter
|
@@ -18,8 +18,8 @@ module Bugsnag
|
|
18
18
|
# KLUDGE: Since we don't re-raise http exceptions, this breaks rspec
|
19
19
|
raise if e.class.to_s == "RSpec::Expectations::ExpectationNotMetError"
|
20
20
|
|
21
|
-
configuration.
|
22
|
-
configuration.
|
21
|
+
configuration.error("Unable to send information to Bugsnag (#{url}), #{e.inspect}")
|
22
|
+
configuration.error(e.backtrace)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -31,8 +31,8 @@ module Bugsnag
|
|
31
31
|
begin
|
32
32
|
payload = get_payload.call
|
33
33
|
rescue StandardError => e
|
34
|
-
configuration.
|
35
|
-
configuration.
|
34
|
+
configuration.error("Unable to send information to Bugsnag (#{url}), #{e.inspect}")
|
35
|
+
configuration.error(e.backtrace)
|
36
36
|
end
|
37
37
|
|
38
38
|
Synchronous.deliver(url, payload, configuration, options) unless payload.nil?
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
# @api private
|
3
|
+
class EndpointValidator
|
4
|
+
def self.validate(endpoints)
|
5
|
+
# ensure we have an EndpointConfiguration object
|
6
|
+
return Result.missing_urls unless endpoints.is_a?(EndpointConfiguration)
|
7
|
+
|
8
|
+
# check for missing URLs
|
9
|
+
return Result.missing_urls if endpoints.notify.nil? && endpoints.sessions.nil?
|
10
|
+
return Result.missing_notify if endpoints.notify.nil?
|
11
|
+
return Result.missing_session if endpoints.sessions.nil?
|
12
|
+
|
13
|
+
# check for empty URLs
|
14
|
+
return Result.invalid_urls if endpoints.notify.empty? && endpoints.sessions.empty?
|
15
|
+
return Result.invalid_notify if endpoints.notify.empty?
|
16
|
+
return Result.invalid_session if endpoints.sessions.empty?
|
17
|
+
|
18
|
+
Result.valid
|
19
|
+
end
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
class Result
|
23
|
+
# rubocop:disable Layout/LineLength
|
24
|
+
MISSING_URLS = "Invalid configuration. endpoints must be set with both a notify and session URL. Bugsnag will not send any requests.".freeze
|
25
|
+
MISSING_NOTIFY_URL = "Invalid configuration. endpoints.sessions cannot be set without also setting endpoints.notify. Bugsnag will not send any requests.".freeze
|
26
|
+
MISSING_SESSION_URL = "Invalid configuration. endpoints.notify cannot be set without also setting endpoints.sessions. Bugsnag will not send any sessions.".freeze
|
27
|
+
|
28
|
+
INVALID_URLS = "Invalid configuration. endpoints should be valid URLs, got empty strings. Bugsnag will not send any requests.".freeze
|
29
|
+
INVALID_NOTIFY_URL = "Invalid configuration. endpoints.notify should be a valid URL, got empty string. Bugsnag will not send any requests.".freeze
|
30
|
+
INVALID_SESSION_URL = "Invalid configuration. endpoints.sessions should be a valid URL, got empty string. Bugsnag will not send any sessions.".freeze
|
31
|
+
# rubocop:enable Layout/LineLength
|
32
|
+
|
33
|
+
attr_reader :reason
|
34
|
+
|
35
|
+
def initialize(valid, keep_events_enabled_for_backwards_compatibility = true, reason = nil)
|
36
|
+
@valid = valid
|
37
|
+
@keep_events_enabled_for_backwards_compatibility = keep_events_enabled_for_backwards_compatibility
|
38
|
+
@reason = reason
|
39
|
+
end
|
40
|
+
|
41
|
+
def valid?
|
42
|
+
@valid
|
43
|
+
end
|
44
|
+
|
45
|
+
def keep_events_enabled_for_backwards_compatibility?
|
46
|
+
@keep_events_enabled_for_backwards_compatibility
|
47
|
+
end
|
48
|
+
|
49
|
+
# factory functions
|
50
|
+
|
51
|
+
def self.valid
|
52
|
+
new(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.missing_urls
|
56
|
+
new(false, false, MISSING_URLS)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.missing_notify
|
60
|
+
new(false, false, MISSING_NOTIFY_URL)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.missing_session
|
64
|
+
new(false, true, MISSING_SESSION_URL)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.invalid_urls
|
68
|
+
new(false, false, INVALID_URLS)
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.invalid_notify
|
72
|
+
new(false, false, INVALID_NOTIFY_URL)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.invalid_session
|
76
|
+
new(false, true, INVALID_SESSION_URL)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
class Error
|
3
|
+
# @return [String] the error's class name
|
4
|
+
attr_accessor :error_class
|
5
|
+
|
6
|
+
# @return [String] the error's message
|
7
|
+
attr_accessor :error_message
|
8
|
+
|
9
|
+
# @return [Hash] the error's processed stacktrace
|
10
|
+
attr_reader :stacktrace
|
11
|
+
|
12
|
+
# @return [String] the type of error (always "ruby")
|
13
|
+
attr_accessor :type
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
TYPE = "ruby".freeze
|
17
|
+
|
18
|
+
def initialize(error_class, error_message, stacktrace)
|
19
|
+
@error_class = error_class
|
20
|
+
@error_message = error_message
|
21
|
+
@stacktrace = stacktrace
|
22
|
+
@type = TYPE
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Bugsnag
|
2
|
+
class FeatureFlag
|
3
|
+
# Get the name of this feature flag
|
4
|
+
#
|
5
|
+
# @return [String]
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
# Get the variant of this feature flag
|
9
|
+
#
|
10
|
+
# @return [String, nil]
|
11
|
+
attr_reader :variant
|
12
|
+
|
13
|
+
# @param name [String] The name of this feature flags
|
14
|
+
# @param variant [String, nil] An optional variant for this flag
|
15
|
+
def initialize(name, variant = nil)
|
16
|
+
@name = name
|
17
|
+
@variant = coerce_variant(variant)
|
18
|
+
end
|
19
|
+
|
20
|
+
def ==(other)
|
21
|
+
self.class == other.class && @name == other.name && @variant == other.variant
|
22
|
+
end
|
23
|
+
|
24
|
+
def hash
|
25
|
+
[@name, @variant].hash
|
26
|
+
end
|
27
|
+
|
28
|
+
# Convert this flag to a hash
|
29
|
+
#
|
30
|
+
# @example With no variant
|
31
|
+
# { "featureFlag" => "name" }
|
32
|
+
#
|
33
|
+
# @example With a variant
|
34
|
+
# { "featureFlag" => "name", "variant" => "variant" }
|
35
|
+
#
|
36
|
+
# @return [Hash{String => String}]
|
37
|
+
def to_h
|
38
|
+
if @variant.nil?
|
39
|
+
{ "featureFlag" => @name }
|
40
|
+
else
|
41
|
+
{ "featureFlag" => @name, "variant" => @variant }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Check if this flag is valid, i.e. has a name that's a String and a variant
|
46
|
+
# that's either nil or a String
|
47
|
+
#
|
48
|
+
# @return [Boolean]
|
49
|
+
def valid?
|
50
|
+
@name.is_a?(String) &&
|
51
|
+
!@name.empty? &&
|
52
|
+
(@variant.nil? || @variant.is_a?(String))
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# Coerce this variant into a valid value (String or nil)
|
58
|
+
#
|
59
|
+
# If the variant is not already a string or nil, we use #to_s to coerce it.
|
60
|
+
# If #to_s raises, the variant will be set to nil
|
61
|
+
#
|
62
|
+
# @param variant [Object]
|
63
|
+
# @return [String, nil]
|
64
|
+
def coerce_variant(variant)
|
65
|
+
if variant.nil? || variant.is_a?(String)
|
66
|
+
variant
|
67
|
+
else
|
68
|
+
variant.to_s
|
69
|
+
end
|
70
|
+
rescue StandardError
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -127,6 +127,8 @@ module Bugsnag
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
-
|
131
|
-
|
132
|
-
Mongo
|
130
|
+
if defined?(Mongo::Monitoring)
|
131
|
+
##
|
132
|
+
# Add the subscriber to the global Mongo monitoring object
|
133
|
+
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::COMMAND, Bugsnag::MongoBreadcrumbSubscriber.new)
|
134
|
+
end
|
@@ -25,9 +25,9 @@ module Bugsnag
|
|
25
25
|
end
|
26
26
|
|
27
27
|
# Hook up rack-based notification middlewares
|
28
|
-
config.
|
29
|
-
config.
|
30
|
-
config.
|
28
|
+
config.internal_middleware.insert_before(Bugsnag::Middleware::Rails3Request, Bugsnag::Middleware::RackRequest) if defined?(::Rack)
|
29
|
+
config.internal_middleware.use(Bugsnag::Middleware::WardenUser) if defined?(Warden)
|
30
|
+
config.internal_middleware.use(Bugsnag::Middleware::ClearanceUser) if defined?(Clearance)
|
31
31
|
|
32
32
|
# Set environment data for payload
|
33
33
|
# Note we only set the detected app_type if it's not already set. This
|