sentry-ruby 5.9.0 → 5.16.1

Sign up to get free protection for your applications and to get access to all the features.
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/