sentry-ruby 5.9.0 → 5.16.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -10
  3. data/README.md +9 -9
  4. data/lib/sentry/background_worker.rb +8 -1
  5. data/lib/sentry/backpressure_monitor.rb +75 -0
  6. data/lib/sentry/breadcrumb.rb +8 -2
  7. data/lib/sentry/check_in_event.rb +60 -0
  8. data/lib/sentry/client.rb +48 -10
  9. data/lib/sentry/configuration.rb +89 -17
  10. data/lib/sentry/cron/configuration.rb +23 -0
  11. data/lib/sentry/cron/monitor_check_ins.rb +75 -0
  12. data/lib/sentry/cron/monitor_config.rb +53 -0
  13. data/lib/sentry/cron/monitor_schedule.rb +42 -0
  14. data/lib/sentry/envelope.rb +1 -1
  15. data/lib/sentry/event.rb +6 -28
  16. data/lib/sentry/hub.rb +74 -2
  17. data/lib/sentry/integrable.rb +6 -0
  18. data/lib/sentry/interfaces/single_exception.rb +5 -3
  19. data/lib/sentry/net/http.rb +26 -20
  20. data/lib/sentry/profiler.rb +18 -7
  21. data/lib/sentry/propagation_context.rb +134 -0
  22. data/lib/sentry/puma.rb +11 -4
  23. data/lib/sentry/rack/capture_exceptions.rb +1 -4
  24. data/lib/sentry/rake.rb +0 -13
  25. data/lib/sentry/redis.rb +9 -3
  26. data/lib/sentry/release_detector.rb +1 -1
  27. data/lib/sentry/scope.rb +29 -13
  28. data/lib/sentry/span.rb +39 -2
  29. data/lib/sentry/test_helper.rb +18 -12
  30. data/lib/sentry/transaction.rb +18 -19
  31. data/lib/sentry/transaction_event.rb +0 -3
  32. data/lib/sentry/transport/configuration.rb +74 -1
  33. data/lib/sentry/transport/http_transport.rb +68 -37
  34. data/lib/sentry/transport/spotlight_transport.rb +50 -0
  35. data/lib/sentry/transport.rb +21 -17
  36. data/lib/sentry/utils/argument_checking_helper.rb +9 -3
  37. data/lib/sentry/version.rb +1 -1
  38. data/lib/sentry-ruby.rb +83 -25
  39. metadata +10 -3
  40. data/CODE_OF_CONDUCT.md +0 -74
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "zlib"
5
+
6
+ module Sentry
7
+ # Designed to just report events to Spotlight in development.
8
+ class SpotlightTransport < HTTPTransport
9
+ DEFAULT_SIDECAR_URL = "http://localhost:8969/stream"
10
+ MAX_FAILED_REQUESTS = 3
11
+
12
+ def initialize(configuration)
13
+ super
14
+ @sidecar_url = configuration.spotlight.is_a?(String) ? configuration.spotlight : DEFAULT_SIDECAR_URL
15
+ @failed = 0
16
+ @logged = false
17
+
18
+ log_debug("[Spotlight] initialized for url #{@sidecar_url}")
19
+ end
20
+
21
+ def endpoint
22
+ "/stream"
23
+ end
24
+
25
+ def send_data(data)
26
+ if @failed >= MAX_FAILED_REQUESTS
27
+ unless @logged
28
+ log_debug("[Spotlight] disabling because of too many request failures")
29
+ @logged = true
30
+ end
31
+
32
+ return
33
+ end
34
+
35
+ super
36
+ end
37
+
38
+ def on_error
39
+ @failed += 1
40
+ end
41
+
42
+ # Similar to HTTPTransport connection, but does not support Proxy and SSL
43
+ def conn
44
+ sidecar = URI(@sidecar_url)
45
+ connection = ::Net::HTTP.new(sidecar.hostname, sidecar.port, nil)
46
+ connection.use_ssl = false
47
+ connection
48
+ end
49
+ end
50
+ end
@@ -18,7 +18,9 @@ module Sentry
18
18
  :network_error,
19
19
  :sample_rate,
20
20
  :before_send,
21
- :event_processor
21
+ :event_processor,
22
+ :insufficient_data,
23
+ :backpressure
22
24
  ]
23
25
 
24
26
  include LoggingHelper
@@ -73,7 +75,7 @@ module Sentry
73
75
  result, oversized = item.serialize
74
76
 
75
77
  if oversized
76
- log_info("Envelope item [#{item.type}] is still oversized after size reduction: {#{item.size_breakdown}}")
78
+ log_debug("Envelope item [#{item.type}] is still oversized after size reduction: {#{item.size_breakdown}}")
77
79
 
78
80
  next
79
81
  end
@@ -118,16 +120,8 @@ module Sentry
118
120
  !!delay && delay > Time.now
119
121
  end
120
122
 
121
- def generate_auth_header
122
- now = Sentry.utc_now.to_i
123
- fields = {
124
- 'sentry_version' => PROTOCOL_VERSION,
125
- 'sentry_client' => USER_AGENT,
126
- 'sentry_timestamp' => now,
127
- 'sentry_key' => @dsn.public_key
128
- }
129
- fields['sentry_secret'] = @dsn.secret_key if @dsn.secret_key
130
- 'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
123
+ def any_rate_limited?
124
+ @rate_limits.values.any? { |t| t && t > Time.now }
131
125
  end
132
126
 
133
127
  def envelope_from_event(event)
@@ -143,7 +137,7 @@ module Sentry
143
137
  sent_at: Sentry.utc_now.iso8601
144
138
  }
145
139
 
146
- if event.is_a?(TransactionEvent) && event.dynamic_sampling_context
140
+ if event.is_a?(Event) && event.dynamic_sampling_context
147
141
  envelope_headers[:trace] = event.dynamic_sampling_context
148
142
  end
149
143
 
@@ -174,18 +168,27 @@ module Sentry
174
168
  @discarded_events[[reason, item_type]] += 1
175
169
  end
176
170
 
171
+ def flush
172
+ client_report_headers, client_report_payload = fetch_pending_client_report(force: true)
173
+ return unless client_report_headers
174
+
175
+ envelope = Envelope.new
176
+ envelope.add_item(client_report_headers, client_report_payload)
177
+ send_envelope(envelope)
178
+ end
179
+
177
180
  private
178
181
 
179
- def fetch_pending_client_report
182
+ def fetch_pending_client_report(force: false)
180
183
  return nil unless @send_client_reports
181
- return nil if @last_client_report_sent > Time.now - CLIENT_REPORT_INTERVAL
184
+ return nil if !force && @last_client_report_sent > Time.now - CLIENT_REPORT_INTERVAL
182
185
  return nil if @discarded_events.empty?
183
186
 
184
187
  discarded_events_hash = @discarded_events.map do |key, val|
185
188
  reason, type = key
186
189
 
187
190
  # 'event' has to be mapped to 'error'
188
- category = type == 'transaction' ? 'transaction' : 'error'
191
+ category = type == 'event' ? 'error' : type
189
192
 
190
193
  { reason: reason, category: category, quantity: val }
191
194
  end
@@ -205,7 +208,7 @@ module Sentry
205
208
  def reject_rate_limited_items(envelope)
206
209
  envelope.items.reject! do |item|
207
210
  if is_rate_limited?(item.type)
208
- log_info("[Transport] Envelope item [#{item.type}] not sent: rate limiting")
211
+ log_debug("[Transport] Envelope item [#{item.type}] not sent: rate limiting")
209
212
  record_lost_event(:ratelimit_backoff, item.type)
210
213
 
211
214
  true
@@ -219,3 +222,4 @@ end
219
222
 
220
223
  require "sentry/transport/dummy_transport"
221
224
  require "sentry/transport/http_transport"
225
+ require "sentry/transport/spotlight_transport"
@@ -4,9 +4,15 @@ module Sentry
4
4
  module ArgumentCheckingHelper
5
5
  private
6
6
 
7
- def check_argument_type!(argument, expected_type)
8
- unless argument.is_a?(expected_type)
9
- raise ArgumentError, "expect the argument to be a #{expected_type}, got #{argument.class} (#{argument.inspect})"
7
+ def check_argument_type!(argument, *expected_types)
8
+ unless expected_types.any? { |t| argument.is_a?(t) }
9
+ raise ArgumentError, "expect the argument to be a #{expected_types.join(' or ')}, got #{argument.class} (#{argument.inspect})"
10
+ end
11
+ end
12
+
13
+ def check_argument_includes!(argument, values)
14
+ unless values.include?(argument)
15
+ raise ArgumentError, "expect the argument to be one of #{values.map(&:inspect).join(' or ')}, got #{argument.inspect}"
10
16
  end
11
17
  end
12
18
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentry
4
- VERSION = "5.9.0"
4
+ VERSION = "5.16.1"
5
5
  end
data/lib/sentry-ruby.rb CHANGED
@@ -15,11 +15,14 @@ require "sentry/logger"
15
15
  require "sentry/event"
16
16
  require "sentry/error_event"
17
17
  require "sentry/transaction_event"
18
+ require "sentry/check_in_event"
18
19
  require "sentry/span"
19
20
  require "sentry/transaction"
20
21
  require "sentry/hub"
21
22
  require "sentry/background_worker"
22
23
  require "sentry/session_flusher"
24
+ require "sentry/backpressure_monitor"
25
+ require "sentry/cron/monitor_check_ins"
23
26
 
24
27
  [
25
28
  "sentry/rake",
@@ -63,25 +66,29 @@ module Sentry
63
66
  end
64
67
 
65
68
  # @!attribute [rw] background_worker
66
- # @return [BackgroundWorker, nil]
69
+ # @return [BackgroundWorker]
67
70
  attr_accessor :background_worker
68
71
 
69
72
  # @!attribute [r] session_flusher
70
73
  # @return [SessionFlusher, nil]
71
74
  attr_reader :session_flusher
72
75
 
76
+ # @!attribute [r] backpressure_monitor
77
+ # @return [BackpressureMonitor, nil]
78
+ attr_reader :backpressure_monitor
79
+
73
80
  ##### Patch Registration #####
74
81
 
75
82
  # @!visibility private
76
- def register_patch(patch = nil, target = nil, &block)
83
+ def register_patch(key, patch = nil, target = nil, &block)
77
84
  if patch && block
78
85
  raise ArgumentError.new("Please provide either a patch and its target OR a block, but not both")
79
86
  end
80
87
 
81
88
  if block
82
- registered_patches << block
89
+ registered_patches[key] = block
83
90
  else
84
- registered_patches << proc do
91
+ registered_patches[key] = proc do
85
92
  target.send(:prepend, patch) unless target.ancestors.include?(patch)
86
93
  end
87
94
  end
@@ -89,14 +96,14 @@ module Sentry
89
96
 
90
97
  # @!visibility private
91
98
  def apply_patches(config)
92
- registered_patches.each do |patch|
93
- patch.call(config)
99
+ registered_patches.each do |key, patch|
100
+ patch.call(config) if config.enabled_patches.include?(key)
94
101
  end
95
102
  end
96
103
 
97
104
  # @!visibility private
98
105
  def registered_patches
99
- @registered_patches ||= []
106
+ @registered_patches ||= {}
100
107
  end
101
108
 
102
109
  ##### Integrations #####
@@ -215,17 +222,9 @@ module Sentry
215
222
  Thread.current.thread_variable_set(THREAD_LOCAL, hub)
216
223
  @main_hub = hub
217
224
  @background_worker = Sentry::BackgroundWorker.new(config)
218
-
219
- @session_flusher = if config.auto_session_tracking
220
- Sentry::SessionFlusher.new(config, client)
221
- else
222
- nil
223
- end
224
-
225
- if config.include_local_variables
226
- exception_locals_tp.enable
227
- end
228
-
225
+ @session_flusher = config.auto_session_tracking ? Sentry::SessionFlusher.new(config, client) : nil
226
+ @backpressure_monitor = config.enable_backpressure_handling ? Sentry::BackpressureMonitor.new(config, client) : nil
227
+ exception_locals_tp.enable if config.include_local_variables
229
228
  at_exit { close }
230
229
  end
231
230
 
@@ -234,20 +233,27 @@ module Sentry
234
233
  #
235
234
  # @return [void]
236
235
  def close
237
- if @background_worker
238
- @background_worker.shutdown
239
- @background_worker = nil
240
- end
241
-
242
236
  if @session_flusher
237
+ @session_flusher.flush
243
238
  @session_flusher.kill
244
239
  @session_flusher = nil
245
240
  end
246
241
 
247
- if configuration&.include_local_variables
248
- exception_locals_tp.disable
242
+ if @backpressure_monitor
243
+ @backpressure_monitor.kill
244
+ @backpressure_monitor = nil
249
245
  end
250
246
 
247
+ if client = get_current_client
248
+ client.transport.flush
249
+
250
+ if client.configuration.include_local_variables
251
+ exception_locals_tp.disable
252
+ end
253
+ end
254
+
255
+ @background_worker.shutdown
256
+
251
257
  @main_hub = nil
252
258
  Thread.current.thread_variable_set(THREAD_LOCAL, nil)
253
259
  end
@@ -430,6 +436,22 @@ module Sentry
430
436
  get_current_hub.capture_event(event)
431
437
  end
432
438
 
439
+ # Captures a check-in and sends it to Sentry via the currently active hub.
440
+ #
441
+ # @param slug [String] identifier of this monitor
442
+ # @param status [Symbol] status of this check-in, one of {CheckInEvent::VALID_STATUSES}
443
+ #
444
+ # @param [Hash] options extra check-in options
445
+ # @option options [String] check_in_id for updating the status of an existing monitor
446
+ # @option options [Integer] duration seconds elapsed since this monitor started
447
+ # @option options [Cron::MonitorConfig] monitor_config configuration for this monitor
448
+ #
449
+ # @return [String, nil] The {CheckInEvent#check_in_id} to use for later updates on the same slug
450
+ def capture_check_in(slug, status, **options)
451
+ return unless initialized?
452
+ get_current_hub.capture_check_in(slug, status, **options)
453
+ end
454
+
433
455
  # Takes or initializes a new Sentry::Transaction and makes a sampling decision for it.
434
456
  #
435
457
  # @return [Transaction, nil]
@@ -489,6 +511,42 @@ module Sentry
489
511
  Scope.add_global_event_processor(&block)
490
512
  end
491
513
 
514
+ # Returns the traceparent (sentry-trace) header for distributed tracing.
515
+ # Can be either from the currently active span or the propagation context.
516
+ #
517
+ # @return [String, nil]
518
+ def get_traceparent
519
+ return nil unless initialized?
520
+ get_current_hub.get_traceparent
521
+ end
522
+
523
+ # Returns the baggage header for distributed tracing.
524
+ # Can be either from the currently active span or the propagation context.
525
+ #
526
+ # @return [String, nil]
527
+ def get_baggage
528
+ return nil unless initialized?
529
+ get_current_hub.get_baggage
530
+ end
531
+
532
+ # Returns the a Hash containing sentry-trace and baggage.
533
+ # Can be either from the currently active span or the propagation context.
534
+ #
535
+ # @return [Hash, nil]
536
+ def get_trace_propagation_headers
537
+ return nil unless initialized?
538
+ get_current_hub.get_trace_propagation_headers
539
+ end
540
+
541
+ # Continue an incoming trace from a rack env like hash.
542
+ #
543
+ # @param env [Hash]
544
+ # @return [Transaction, nil]
545
+ def continue_trace(env, **options)
546
+ return nil unless initialized?
547
+ get_current_hub.continue_trace(env, **options)
548
+ end
549
+
492
550
  ##### Helpers #####
493
551
 
494
552
  # @!visibility private
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.9.0
4
+ version: 5.16.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-19 00:00:00.000000000 Z
11
+ date: 2024-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -42,7 +42,6 @@ files:
42
42
  - ".rspec"
43
43
  - ".yardopts"
44
44
  - CHANGELOG.md
45
- - CODE_OF_CONDUCT.md
46
45
  - Gemfile
47
46
  - LICENSE.txt
48
47
  - Makefile
@@ -52,15 +51,21 @@ files:
52
51
  - bin/setup
53
52
  - lib/sentry-ruby.rb
54
53
  - lib/sentry/background_worker.rb
54
+ - lib/sentry/backpressure_monitor.rb
55
55
  - lib/sentry/backtrace.rb
56
56
  - lib/sentry/baggage.rb
57
57
  - lib/sentry/breadcrumb.rb
58
58
  - lib/sentry/breadcrumb/sentry_logger.rb
59
59
  - lib/sentry/breadcrumb_buffer.rb
60
+ - lib/sentry/check_in_event.rb
60
61
  - lib/sentry/client.rb
61
62
  - lib/sentry/configuration.rb
62
63
  - lib/sentry/core_ext/object/deep_dup.rb
63
64
  - lib/sentry/core_ext/object/duplicable.rb
65
+ - lib/sentry/cron/configuration.rb
66
+ - lib/sentry/cron/monitor_check_ins.rb
67
+ - lib/sentry/cron/monitor_config.rb
68
+ - lib/sentry/cron/monitor_schedule.rb
64
69
  - lib/sentry/dsn.rb
65
70
  - lib/sentry/envelope.rb
66
71
  - lib/sentry/error_event.rb
@@ -79,6 +84,7 @@ files:
79
84
  - lib/sentry/logger.rb
80
85
  - lib/sentry/net/http.rb
81
86
  - lib/sentry/profiler.rb
87
+ - lib/sentry/propagation_context.rb
82
88
  - lib/sentry/puma.rb
83
89
  - lib/sentry/rack.rb
84
90
  - lib/sentry/rack/capture_exceptions.rb
@@ -96,6 +102,7 @@ files:
96
102
  - lib/sentry/transport/configuration.rb
97
103
  - lib/sentry/transport/dummy_transport.rb
98
104
  - lib/sentry/transport/http_transport.rb
105
+ - lib/sentry/transport/spotlight_transport.rb
99
106
  - lib/sentry/utils/argument_checking_helper.rb
100
107
  - lib/sentry/utils/custom_inspection.rb
101
108
  - lib/sentry/utils/encoding_helper.rb
data/CODE_OF_CONDUCT.md DELETED
@@ -1,74 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
11
-
12
- ## Our Standards
13
-
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
16
-
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
22
-
23
- Examples of unacceptable behavior by participants include:
24
-
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
28
- * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
31
- * Other conduct which could reasonably be considered inappropriate in a
32
- professional setting
33
-
34
- ## Our Responsibilities
35
-
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
39
-
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
45
-
46
- ## Scope
47
-
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
-
55
- ## Enforcement
56
-
57
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at stan001212@gmail.com. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
-
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
67
-
68
- ## Attribution
69
-
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [https://contributor-covenant.org/version/1/4][version]
72
-
73
- [homepage]: https://contributor-covenant.org
74
- [version]: https://contributor-covenant.org/version/1/4/