sentry-ruby-core 6.6.2 → 7.0.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/bin/test +15 -0
  3. data/gemfiles/ruby-2.7_rack-2_redis-4.gemfile.lock +159 -0
  4. data/gemfiles/ruby-2.7_rack-3.1_redis-4.gemfile.lock +159 -0
  5. data/gemfiles/ruby-2.7_rack-3_redis-4.gemfile.lock +159 -0
  6. data/gemfiles/ruby-3.0_rack-2_redis-4.gemfile.lock +173 -0
  7. data/gemfiles/ruby-3.0_rack-3.1_redis-4.gemfile.lock +173 -0
  8. data/gemfiles/ruby-3.0_rack-3_redis-4.gemfile.lock +173 -0
  9. data/gemfiles/ruby-3.1_rack-2_redis-4.gemfile.lock +241 -0
  10. data/gemfiles/ruby-3.1_rack-3.1_redis-4.gemfile.lock +241 -0
  11. data/gemfiles/ruby-3.1_rack-3_redis-4.gemfile.lock +241 -0
  12. data/gemfiles/ruby-3.2_rack-0_redis-5.gemfile.lock +263 -0
  13. data/gemfiles/ruby-3.2_rack-2_redis-4.gemfile.lock +260 -0
  14. data/gemfiles/ruby-3.2_rack-2_redis-5.gemfile.lock +266 -0
  15. data/gemfiles/ruby-3.2_rack-3.1_redis-4.gemfile.lock +260 -0
  16. data/gemfiles/ruby-3.2_rack-3_redis-4.gemfile.lock +260 -0
  17. data/gemfiles/ruby-3.2_rack-3_redis-5.gemfile.lock +266 -0
  18. data/gemfiles/ruby-3.3_rack-2_redis-4.gemfile.lock +263 -0
  19. data/gemfiles/ruby-3.3_rack-3.1_redis-4.gemfile.lock +263 -0
  20. data/gemfiles/ruby-3.3_rack-3.1_redis-5.3.gemfile.lock +269 -0
  21. data/gemfiles/ruby-3.3_rack-3_redis-4.gemfile.lock +263 -0
  22. data/gemfiles/ruby-3.4_rack-2_redis-4.gemfile.lock +254 -0
  23. data/gemfiles/ruby-3.4_rack-3.1_redis-4.gemfile.lock +254 -0
  24. data/gemfiles/ruby-3.4_rack-3.1_redis-5.3.gemfile.lock +260 -0
  25. data/gemfiles/ruby-3.4_rack-3_redis-4.gemfile.lock +254 -0
  26. data/gemfiles/ruby-4.0_rack-2_redis-4.gemfile.lock +254 -0
  27. data/gemfiles/ruby-4.0_rack-3.1_redis-4.gemfile.lock +254 -0
  28. data/gemfiles/ruby-4.0_rack-3_redis-4.gemfile.lock +254 -0
  29. data/gemfiles/ruby-jruby-9.4.14.0_rack-2_redis-4.gemfile.lock +266 -0
  30. data/gemfiles/ruby-jruby-9.4.14.0_rack-3.1_redis-4.gemfile.lock +266 -0
  31. data/gemfiles/ruby-jruby-9.4.14.0_rack-3_redis-4.gemfile.lock +266 -0
  32. data/lib/sentry/client.rb +9 -8
  33. data/lib/sentry/configuration.rb +74 -12
  34. data/lib/sentry/data_collection/key_value_collection.rb +136 -0
  35. data/lib/sentry/data_collection.rb +203 -0
  36. data/lib/sentry/debug_structured_logger.rb +2 -15
  37. data/lib/sentry/envelope/item.rb +21 -0
  38. data/lib/sentry/error_event.rb +6 -1
  39. data/lib/sentry/event.rb +8 -4
  40. data/lib/sentry/excon/middleware.rb +3 -8
  41. data/lib/sentry/faraday.rb +3 -4
  42. data/lib/sentry/hub.rb +2 -2
  43. data/lib/sentry/interfaces/exception.rb +8 -2
  44. data/lib/sentry/interfaces/request.rb +42 -46
  45. data/lib/sentry/interfaces/single_exception.rb +2 -2
  46. data/lib/sentry/net/http.rb +3 -4
  47. data/lib/sentry/redis.rb +1 -1
  48. data/lib/sentry/scope.rb +42 -3
  49. data/lib/sentry/span.rb +1 -0
  50. data/lib/sentry/std_lib_logger.rb +2 -6
  51. data/lib/sentry/telemetry_event_buffer.rb +9 -2
  52. data/lib/sentry/test_helper.rb +8 -7
  53. data/lib/sentry/threaded_periodic_worker.rb +8 -3
  54. data/lib/sentry/transport.rb +14 -3
  55. data/lib/sentry/utils/http_tracing.rb +42 -26
  56. data/lib/sentry/utils/telemetry_attributes.rb +26 -14
  57. data/lib/sentry/version.rb +1 -1
  58. data/lib/sentry-ruby.rb +94 -23
  59. data/sentry-ruby-core.gemspec +1 -1
  60. data/sentry-ruby.gemspec +1 -1
  61. metadata +35 -3
data/lib/sentry-ruby.rb CHANGED
@@ -220,6 +220,35 @@ module Sentry
220
220
  get_current_scope.set_context(*args)
221
221
  end
222
222
 
223
+ # @!method set_attributes
224
+ # Updates the current scope's attributes by merging with the old value.
225
+ # @param attributes_hash [Hash]
226
+ # @return [Hash]
227
+ def set_attributes(attributes_hash)
228
+ return unless initialized?
229
+ get_current_scope.set_attributes(attributes_hash)
230
+ end
231
+
232
+ # @!method set_attribute
233
+ # Sets a single attribute on the current scope.
234
+ # @param key [String, Symbol]
235
+ # @param value [Object]
236
+ # @param unit [String, Symbol, nil] an optional measurement unit for the value
237
+ # @return [Hash]
238
+ def set_attribute(key, value, unit: nil)
239
+ return unless initialized?
240
+ get_current_scope.set_attribute(key, value, unit: unit)
241
+ end
242
+
243
+ # @!method remove_attribute
244
+ # Removes a single attribute from the current scope.
245
+ # @param key [String, Symbol]
246
+ # @return [void]
247
+ def remove_attribute(key)
248
+ return unless initialized?
249
+ get_current_scope.remove_attribute(key)
250
+ end
251
+
223
252
  # @!method add_attachment
224
253
  # @!macro add_attachment
225
254
  def add_attachment(**opts)
@@ -242,12 +271,13 @@ module Sentry
242
271
  client = Client.new(config)
243
272
  scope = Scope.new(max_breadcrumbs: config.max_breadcrumbs)
244
273
  hub = Hub.new(client, scope)
245
- Thread.current.thread_variable_set(THREAD_LOCAL, hub)
274
+ @hub_isolation_level = config.hub_isolation_level
275
+ set_current_hub_internal(hub)
246
276
  @main_hub = hub
247
277
  @background_worker = Sentry::BackgroundWorker.new(config)
248
278
  @session_flusher = config.session_tracking? ? Sentry::SessionFlusher.new(config, client) : nil
249
279
  @backpressure_monitor = config.enable_backpressure_handling ? Sentry::BackpressureMonitor.new(config, client) : nil
250
- exception_locals_tp.enable if config.include_local_variables
280
+ exception_locals_tp.enable if config.data_collection.collect_stack_frame_variables?
251
281
  at_exit { close }
252
282
  end
253
283
 
@@ -271,7 +301,7 @@ module Sentry
271
301
  client.configuration.run_after_close_callbacks
272
302
  client.flush
273
303
 
274
- if client.configuration.include_local_variables
304
+ if client.configuration.data_collection.collect_stack_frame_variables?
275
305
  exception_locals_tp.disable
276
306
  end
277
307
  end
@@ -280,7 +310,7 @@ module Sentry
280
310
 
281
311
  MUTEX.synchronize do
282
312
  @main_hub = nil
283
- Thread.current.thread_variable_set(THREAD_LOCAL, nil)
313
+ set_current_hub_internal(nil)
284
314
  end
285
315
  end
286
316
 
@@ -333,7 +363,7 @@ module Sentry
333
363
  # ideally, we should do this proactively whenever a new thread is created
334
364
  # but it's impossible for the SDK to keep track every new thread
335
365
  # so we need to use this rather passive way to make sure the app doesn't crash
336
- Thread.current.thread_variable_get(THREAD_LOCAL) || clone_hub_to_current_thread
366
+ get_current_hub_internal || clone_hub_to_current_thread
337
367
  end
338
368
 
339
369
  # Returns the current active client.
@@ -351,12 +381,14 @@ module Sentry
351
381
  get_current_hub.current_scope
352
382
  end
353
383
 
354
- # Clones the main thread's active hub and stores it to the current thread.
384
+ # Clones the main hub and stores it for the current execution context
385
+ # (the current thread, or the current fiber when +config.hub_isolation_level+
386
+ # is +:fiber+).
355
387
  #
356
388
  # @return [void]
357
389
  def clone_hub_to_current_thread
358
390
  return unless initialized?
359
- Thread.current.thread_variable_set(THREAD_LOCAL, get_main_hub.clone)
391
+ set_current_hub_internal(get_main_hub.clone)
360
392
  end
361
393
 
362
394
  # Takes a block and yields the current active scope.
@@ -495,7 +527,7 @@ module Sentry
495
527
  # Sentry.capture_log("User logged in", level: :info, user_id: 123)
496
528
  #
497
529
  # @see https://develop.sentry.dev/sdk/telemetry/logs/ Sentry SDK Telemetry Logs Protocol
498
- # @return [LogEvent, nil] The created log event or nil if logging is disabled
530
+ # @return [LogEvent, nil] The created log event or nil if Sentry is not initialized
499
531
  def capture_log(message, **options)
500
532
  return unless initialized?
501
533
  get_current_hub.capture_log_event(message, **options)
@@ -607,14 +639,6 @@ module Sentry
607
639
 
608
640
  # Returns the structured logger instance that implements Sentry's SDK telemetry logs protocol.
609
641
  #
610
- # This logger is only available when logs are enabled in the configuration.
611
- #
612
- # @example Enable logs in configuration
613
- # Sentry.init do |config|
614
- # config.dsn = "YOUR_DSN"
615
- # config.enable_logs = true
616
- # end
617
- #
618
642
  # @example Basic usage
619
643
  # Sentry.logger.info("User logged in successfully", user_id: 123)
620
644
  # Sentry.logger.error("Failed to process payment",
@@ -624,19 +648,13 @@ module Sentry
624
648
  #
625
649
  # @see https://develop.sentry.dev/sdk/telemetry/logs/ Sentry SDK Telemetry Logs Protocol
626
650
  #
627
- # @return [StructuredLogger] The structured logger instance or nil if logs are disabled
651
+ # @return [StructuredLogger] The structured logger instance
628
652
  def logger
629
653
  @logger ||= configuration.structured_logging.logger_class.new(configuration)
630
654
  end
631
655
 
632
656
  # Returns the metrics API for capturing custom metrics.
633
657
  #
634
- # @example Enable metrics
635
- # Sentry.init do |config|
636
- # config.dsn = "YOUR_DSN"
637
- # config.enable_metrics = true
638
- # end
639
- #
640
658
  # @example Usage
641
659
  # Sentry.metrics.count("button.click", 1, attributes: { button_id: "submit" })
642
660
  # Sentry.metrics.distribution("response.time", 120.5, unit: "millisecond")
@@ -708,6 +726,59 @@ module Sentry
708
726
  def dependency_installed?(name)
709
727
  Object.const_defined?(name)
710
728
  end
729
+
730
+ # Reads the hub stored for the current execution context. The active
731
+ # isolation level (cached from +config.hub_isolation_level+ at init) decides
732
+ # whether that context is the current thread or the current fiber. Reads the
733
+ # cached level rather than the configuration to avoid recursing back through
734
+ # hub resolution.
735
+ #
736
+ # @!visibility private
737
+ # @return [Hub, nil]
738
+ def get_current_hub_internal
739
+ if @hub_isolation_level == :fiber
740
+ owner, hub = ::Fiber[THREAD_LOCAL]
741
+
742
+ # Child fibers, and threads started from them, inherit fiber storage
743
+ # holding the same Hub object rather than a copy.
744
+ if owner.equal?(::Fiber.current)
745
+ hub
746
+ elsif hub
747
+ set_current_hub_internal(fork_hub(hub))
748
+ end
749
+ else
750
+ ::Thread.current.thread_variable_get(THREAD_LOCAL)
751
+ end
752
+ end
753
+
754
+ # Copies +hub+ for a context that inherited it. The span is re-attached
755
+ # because Scope#dup deep-copies it, and spans recorded on a detached
756
+ # transaction copy are never sent.
757
+ #
758
+ # @!visibility private
759
+ # @param hub [Hub]
760
+ # @return [Hub]
761
+ def fork_hub(hub)
762
+ span = hub.current_scope.span
763
+ forked = hub.clone
764
+ forked.current_scope.set_span(span) if span
765
+
766
+ forked
767
+ end
768
+
769
+ # Stores +hub+ for the current execution context (thread or fiber).
770
+ #
771
+ # @!visibility private
772
+ # @param hub [Hub, nil]
773
+ # @return [Hub, nil]
774
+ def set_current_hub_internal(hub)
775
+ if @hub_isolation_level == :fiber
776
+ ::Fiber[THREAD_LOCAL] = [::Fiber.current, hub]
777
+ hub # callers use the return value, so don't return the pair
778
+ else
779
+ ::Thread.current.thread_variable_set(THREAD_LOCAL, hub)
780
+ end
781
+ end
711
782
  end
712
783
  end
713
784
 
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.platform = Gem::Platform::RUBY
15
15
  spec.required_ruby_version = '>= 2.7'
16
16
  spec.extra_rdoc_files = ["README.md", "LICENSE.txt"]
17
- spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n")
17
+ spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|test-matrix\.json|\.rubocop\.yml)'`.split("\n")
18
18
 
19
19
  spec.metadata["homepage_uri"] = spec.homepage
20
20
  spec.metadata["source_code_uri"] = spec.homepage
data/sentry-ruby.gemspec CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.platform = Gem::Platform::RUBY
14
14
  spec.required_ruby_version = '>= 2.7'
15
15
  spec.extra_rdoc_files = ["README.md", "LICENSE.txt"]
16
- spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n")
16
+ spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|test-matrix\.json|\.rubocop\.yml)'`.split("\n")
17
17
 
18
18
  github_root_uri = 'https://github.com/getsentry/sentry-ruby'
19
19
  spec.homepage = "#{github_root_uri}/tree/#{spec.version}/#{spec.name}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry-ruby-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.6.2
4
+ version: 7.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 6.6.2
18
+ version: 7.0.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 6.6.2
25
+ version: 7.0.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: concurrent-ruby
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -56,6 +56,36 @@ files:
56
56
  - Rakefile
57
57
  - bin/console
58
58
  - bin/setup
59
+ - bin/test
60
+ - gemfiles/ruby-2.7_rack-2_redis-4.gemfile.lock
61
+ - gemfiles/ruby-2.7_rack-3.1_redis-4.gemfile.lock
62
+ - gemfiles/ruby-2.7_rack-3_redis-4.gemfile.lock
63
+ - gemfiles/ruby-3.0_rack-2_redis-4.gemfile.lock
64
+ - gemfiles/ruby-3.0_rack-3.1_redis-4.gemfile.lock
65
+ - gemfiles/ruby-3.0_rack-3_redis-4.gemfile.lock
66
+ - gemfiles/ruby-3.1_rack-2_redis-4.gemfile.lock
67
+ - gemfiles/ruby-3.1_rack-3.1_redis-4.gemfile.lock
68
+ - gemfiles/ruby-3.1_rack-3_redis-4.gemfile.lock
69
+ - gemfiles/ruby-3.2_rack-0_redis-5.gemfile.lock
70
+ - gemfiles/ruby-3.2_rack-2_redis-4.gemfile.lock
71
+ - gemfiles/ruby-3.2_rack-2_redis-5.gemfile.lock
72
+ - gemfiles/ruby-3.2_rack-3.1_redis-4.gemfile.lock
73
+ - gemfiles/ruby-3.2_rack-3_redis-4.gemfile.lock
74
+ - gemfiles/ruby-3.2_rack-3_redis-5.gemfile.lock
75
+ - gemfiles/ruby-3.3_rack-2_redis-4.gemfile.lock
76
+ - gemfiles/ruby-3.3_rack-3.1_redis-4.gemfile.lock
77
+ - gemfiles/ruby-3.3_rack-3.1_redis-5.3.gemfile.lock
78
+ - gemfiles/ruby-3.3_rack-3_redis-4.gemfile.lock
79
+ - gemfiles/ruby-3.4_rack-2_redis-4.gemfile.lock
80
+ - gemfiles/ruby-3.4_rack-3.1_redis-4.gemfile.lock
81
+ - gemfiles/ruby-3.4_rack-3.1_redis-5.3.gemfile.lock
82
+ - gemfiles/ruby-3.4_rack-3_redis-4.gemfile.lock
83
+ - gemfiles/ruby-4.0_rack-2_redis-4.gemfile.lock
84
+ - gemfiles/ruby-4.0_rack-3.1_redis-4.gemfile.lock
85
+ - gemfiles/ruby-4.0_rack-3_redis-4.gemfile.lock
86
+ - gemfiles/ruby-jruby-9.4.14.0_rack-2_redis-4.gemfile.lock
87
+ - gemfiles/ruby-jruby-9.4.14.0_rack-3.1_redis-4.gemfile.lock
88
+ - gemfiles/ruby-jruby-9.4.14.0_rack-3_redis-4.gemfile.lock
59
89
  - lib/sentry-ruby.rb
60
90
  - lib/sentry/attachment.rb
61
91
  - lib/sentry/background_worker.rb
@@ -75,6 +105,8 @@ files:
75
105
  - lib/sentry/cron/monitor_check_ins.rb
76
106
  - lib/sentry/cron/monitor_config.rb
77
107
  - lib/sentry/cron/monitor_schedule.rb
108
+ - lib/sentry/data_collection.rb
109
+ - lib/sentry/data_collection/key_value_collection.rb
78
110
  - lib/sentry/debug_structured_logger.rb
79
111
  - lib/sentry/dsn.rb
80
112
  - lib/sentry/envelope.rb