sentry-ruby 5.3.1 → 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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.yardopts +2 -0
  5. data/CHANGELOG.md +313 -0
  6. data/Gemfile +26 -0
  7. data/Makefile +4 -0
  8. data/README.md +11 -8
  9. data/Rakefile +20 -0
  10. data/bin/console +18 -0
  11. data/bin/setup +8 -0
  12. data/lib/sentry/background_worker.rb +79 -0
  13. data/lib/sentry/backpressure_monitor.rb +75 -0
  14. data/lib/sentry/backtrace.rb +124 -0
  15. data/lib/sentry/baggage.rb +70 -0
  16. data/lib/sentry/breadcrumb/sentry_logger.rb +90 -0
  17. data/lib/sentry/breadcrumb.rb +76 -0
  18. data/lib/sentry/breadcrumb_buffer.rb +64 -0
  19. data/lib/sentry/check_in_event.rb +60 -0
  20. data/lib/sentry/client.rb +248 -0
  21. data/lib/sentry/configuration.rb +650 -0
  22. data/lib/sentry/core_ext/object/deep_dup.rb +61 -0
  23. data/lib/sentry/core_ext/object/duplicable.rb +155 -0
  24. data/lib/sentry/cron/configuration.rb +23 -0
  25. data/lib/sentry/cron/monitor_check_ins.rb +75 -0
  26. data/lib/sentry/cron/monitor_config.rb +53 -0
  27. data/lib/sentry/cron/monitor_schedule.rb +42 -0
  28. data/lib/sentry/dsn.rb +53 -0
  29. data/lib/sentry/envelope.rb +93 -0
  30. data/lib/sentry/error_event.rb +38 -0
  31. data/lib/sentry/event.rb +156 -0
  32. data/lib/sentry/exceptions.rb +9 -0
  33. data/lib/sentry/hub.rb +316 -0
  34. data/lib/sentry/integrable.rb +32 -0
  35. data/lib/sentry/interface.rb +16 -0
  36. data/lib/sentry/interfaces/exception.rb +43 -0
  37. data/lib/sentry/interfaces/request.rb +134 -0
  38. data/lib/sentry/interfaces/single_exception.rb +67 -0
  39. data/lib/sentry/interfaces/stacktrace.rb +87 -0
  40. data/lib/sentry/interfaces/stacktrace_builder.rb +79 -0
  41. data/lib/sentry/interfaces/threads.rb +42 -0
  42. data/lib/sentry/linecache.rb +47 -0
  43. data/lib/sentry/logger.rb +20 -0
  44. data/lib/sentry/net/http.rb +106 -0
  45. data/lib/sentry/profiler.rb +233 -0
  46. data/lib/sentry/propagation_context.rb +134 -0
  47. data/lib/sentry/puma.rb +32 -0
  48. data/lib/sentry/rack/capture_exceptions.rb +79 -0
  49. data/lib/sentry/rack.rb +5 -0
  50. data/lib/sentry/rake.rb +28 -0
  51. data/lib/sentry/redis.rb +108 -0
  52. data/lib/sentry/release_detector.rb +39 -0
  53. data/lib/sentry/scope.rb +360 -0
  54. data/lib/sentry/session.rb +33 -0
  55. data/lib/sentry/session_flusher.rb +90 -0
  56. data/lib/sentry/span.rb +273 -0
  57. data/lib/sentry/test_helper.rb +84 -0
  58. data/lib/sentry/transaction.rb +359 -0
  59. data/lib/sentry/transaction_event.rb +80 -0
  60. data/lib/sentry/transport/configuration.rb +98 -0
  61. data/lib/sentry/transport/dummy_transport.rb +21 -0
  62. data/lib/sentry/transport/http_transport.rb +206 -0
  63. data/lib/sentry/transport/spotlight_transport.rb +50 -0
  64. data/lib/sentry/transport.rb +225 -0
  65. data/lib/sentry/utils/argument_checking_helper.rb +19 -0
  66. data/lib/sentry/utils/custom_inspection.rb +14 -0
  67. data/lib/sentry/utils/encoding_helper.rb +22 -0
  68. data/lib/sentry/utils/exception_cause_chain.rb +20 -0
  69. data/lib/sentry/utils/logging_helper.rb +26 -0
  70. data/lib/sentry/utils/real_ip.rb +84 -0
  71. data/lib/sentry/utils/request_id.rb +18 -0
  72. data/lib/sentry/version.rb +5 -0
  73. data/lib/sentry-ruby.rb +580 -0
  74. data/sentry-ruby-core.gemspec +23 -0
  75. data/sentry-ruby.gemspec +24 -0
  76. metadata +75 -16
@@ -0,0 +1,580 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "English"
4
+ require "forwardable"
5
+ require "time"
6
+
7
+ require "sentry/version"
8
+ require "sentry/exceptions"
9
+ require "sentry/core_ext/object/deep_dup"
10
+ require "sentry/utils/argument_checking_helper"
11
+ require "sentry/utils/encoding_helper"
12
+ require "sentry/utils/logging_helper"
13
+ require "sentry/configuration"
14
+ require "sentry/logger"
15
+ require "sentry/event"
16
+ require "sentry/error_event"
17
+ require "sentry/transaction_event"
18
+ require "sentry/check_in_event"
19
+ require "sentry/span"
20
+ require "sentry/transaction"
21
+ require "sentry/hub"
22
+ require "sentry/background_worker"
23
+ require "sentry/session_flusher"
24
+ require "sentry/backpressure_monitor"
25
+ require "sentry/cron/monitor_check_ins"
26
+
27
+ [
28
+ "sentry/rake",
29
+ "sentry/rack",
30
+ ].each do |lib|
31
+ begin
32
+ require lib
33
+ rescue LoadError
34
+ end
35
+ end
36
+
37
+ module Sentry
38
+ META = { "name" => "sentry.ruby", "version" => Sentry::VERSION }.freeze
39
+
40
+ CAPTURED_SIGNATURE = :@__sentry_captured
41
+
42
+ LOGGER_PROGNAME = "sentry".freeze
43
+
44
+ SENTRY_TRACE_HEADER_NAME = "sentry-trace".freeze
45
+
46
+ BAGGAGE_HEADER_NAME = "baggage".freeze
47
+
48
+ THREAD_LOCAL = :sentry_hub
49
+
50
+ class << self
51
+ # @!visibility private
52
+ def exception_locals_tp
53
+ @exception_locals_tp ||= TracePoint.new(:raise) do |tp|
54
+ exception = tp.raised_exception
55
+
56
+ # don't collect locals again if the exception is re-raised
57
+ next if exception.instance_variable_get(:@sentry_locals)
58
+ next unless tp.binding
59
+
60
+ locals = tp.binding.local_variables.each_with_object({}) do |local, result|
61
+ result[local] = tp.binding.local_variable_get(local)
62
+ end
63
+
64
+ exception.instance_variable_set(:@sentry_locals, locals)
65
+ end
66
+ end
67
+
68
+ # @!attribute [rw] background_worker
69
+ # @return [BackgroundWorker]
70
+ attr_accessor :background_worker
71
+
72
+ # @!attribute [r] session_flusher
73
+ # @return [SessionFlusher, nil]
74
+ attr_reader :session_flusher
75
+
76
+ # @!attribute [r] backpressure_monitor
77
+ # @return [BackpressureMonitor, nil]
78
+ attr_reader :backpressure_monitor
79
+
80
+ ##### Patch Registration #####
81
+
82
+ # @!visibility private
83
+ def register_patch(key, patch = nil, target = nil, &block)
84
+ if patch && block
85
+ raise ArgumentError.new("Please provide either a patch and its target OR a block, but not both")
86
+ end
87
+
88
+ if block
89
+ registered_patches[key] = block
90
+ else
91
+ registered_patches[key] = proc do
92
+ target.send(:prepend, patch) unless target.ancestors.include?(patch)
93
+ end
94
+ end
95
+ end
96
+
97
+ # @!visibility private
98
+ def apply_patches(config)
99
+ registered_patches.each do |key, patch|
100
+ patch.call(config) if config.enabled_patches.include?(key)
101
+ end
102
+ end
103
+
104
+ # @!visibility private
105
+ def registered_patches
106
+ @registered_patches ||= {}
107
+ end
108
+
109
+ ##### Integrations #####
110
+
111
+ # Returns a hash that contains all the integrations that have been registered to the main SDK.
112
+ #
113
+ # @return [Hash{String=>Hash}]
114
+ def integrations
115
+ @integrations ||= {}
116
+ end
117
+
118
+ # Registers the SDK integration with its name and version.
119
+ #
120
+ # @param name [String] name of the integration
121
+ # @param version [String] version of the integration
122
+ def register_integration(name, version)
123
+ if initialized?
124
+ logger.warn(LOGGER_PROGNAME) do
125
+ <<~MSG
126
+ Integration '#{name}' is loaded after the SDK is initialized, which can cause unexpected behavior. Please make sure all integrations are loaded before SDK initialization.
127
+ MSG
128
+ end
129
+ end
130
+
131
+ meta = { name: "sentry.ruby.#{name}", version: version }.freeze
132
+ integrations[name.to_s] = meta
133
+ end
134
+
135
+ ##### Method Delegation #####
136
+
137
+ extend Forwardable
138
+
139
+ # @!macro [new] configuration
140
+ # The Configuration object that's used for configuring the client and its transport.
141
+ # @return [Configuration]
142
+ # @!macro [new] send_event
143
+ # Sends the event to Sentry.
144
+ # @param event [Event] the event to be sent.
145
+ # @param hint [Hash] the hint data that'll be passed to `before_send` callback.
146
+ # @return [Event]
147
+
148
+ # @!method configuration
149
+ # @!macro configuration
150
+ def configuration
151
+ return unless initialized?
152
+ get_current_client.configuration
153
+ end
154
+
155
+ # @!method send_event
156
+ # @!macro send_event
157
+ def send_event(*args)
158
+ return unless initialized?
159
+ get_current_client.send_event(*args)
160
+ end
161
+
162
+ # @!macro [new] set_extras
163
+ # Updates the scope's extras attribute by merging with the old value.
164
+ # @param extras [Hash]
165
+ # @return [Hash]
166
+ # @!macro [new] set_user
167
+ # Sets the scope's user attribute.
168
+ # @param user [Hash]
169
+ # @return [Hash]
170
+ # @!macro [new] set_context
171
+ # Adds a new key-value pair to current contexts.
172
+ # @param key [String, Symbol]
173
+ # @param value [Object]
174
+ # @return [Hash]
175
+ # @!macro [new] set_tags
176
+ # Updates the scope's tags attribute by merging with the old value.
177
+ # @param tags [Hash]
178
+ # @return [Hash]
179
+
180
+ # @!method set_tags
181
+ # @!macro set_tags
182
+ def set_tags(*args)
183
+ return unless initialized?
184
+ get_current_scope.set_tags(*args)
185
+ end
186
+
187
+ # @!method set_extras
188
+ # @!macro set_extras
189
+ def set_extras(*args)
190
+ return unless initialized?
191
+ get_current_scope.set_extras(*args)
192
+ end
193
+
194
+ # @!method set_user
195
+ # @!macro set_user
196
+ def set_user(*args)
197
+ return unless initialized?
198
+ get_current_scope.set_user(*args)
199
+ end
200
+
201
+ # @!method set_context
202
+ # @!macro set_context
203
+ def set_context(*args)
204
+ return unless initialized?
205
+ get_current_scope.set_context(*args)
206
+ end
207
+
208
+ ##### Main APIs #####
209
+
210
+ # Initializes the SDK with given configuration.
211
+ #
212
+ # @yieldparam config [Configuration]
213
+ # @return [void]
214
+ def init(&block)
215
+ config = Configuration.new
216
+ yield(config) if block_given?
217
+ config.detect_release
218
+ apply_patches(config)
219
+ client = Client.new(config)
220
+ scope = Scope.new(max_breadcrumbs: config.max_breadcrumbs)
221
+ hub = Hub.new(client, scope)
222
+ Thread.current.thread_variable_set(THREAD_LOCAL, hub)
223
+ @main_hub = hub
224
+ @background_worker = Sentry::BackgroundWorker.new(config)
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
228
+ at_exit { close }
229
+ end
230
+
231
+ # Flushes pending events and cleans up SDK state.
232
+ # SDK will stop sending events and all top-level APIs will be no-ops after this.
233
+ #
234
+ # @return [void]
235
+ def close
236
+ if @session_flusher
237
+ @session_flusher.flush
238
+ @session_flusher.kill
239
+ @session_flusher = nil
240
+ end
241
+
242
+ if @backpressure_monitor
243
+ @backpressure_monitor.kill
244
+ @backpressure_monitor = nil
245
+ end
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
+
257
+ @main_hub = nil
258
+ Thread.current.thread_variable_set(THREAD_LOCAL, nil)
259
+ end
260
+
261
+ # Returns true if the SDK is initialized.
262
+ #
263
+ # @return [Boolean]
264
+ def initialized?
265
+ !!get_main_hub
266
+ end
267
+
268
+ # Returns an uri for security policy reporting that's generated from the given DSN
269
+ # (To learn more about security policy reporting: https://docs.sentry.io/product/security-policy-reporting/)
270
+ #
271
+ # It returns nil if
272
+ # - The SDK is not initialized yet.
273
+ # - The DSN is not provided or is invalid.
274
+ #
275
+ # @return [String, nil]
276
+ def csp_report_uri
277
+ return unless initialized?
278
+ configuration.csp_report_uri
279
+ end
280
+
281
+ # Returns the main thread's active hub.
282
+ #
283
+ # @return [Hub]
284
+ def get_main_hub
285
+ @main_hub
286
+ end
287
+
288
+ # Takes an instance of Sentry::Breadcrumb and stores it to the current active scope.
289
+ #
290
+ # @return [Breadcrumb, nil]
291
+ def add_breadcrumb(breadcrumb, **options)
292
+ return unless initialized?
293
+ get_current_hub.add_breadcrumb(breadcrumb, **options)
294
+ end
295
+
296
+ # Returns the current active hub.
297
+ # If the current thread doesn't have an active hub, it will clone the main thread's active hub,
298
+ # stores it in the current thread, and then returns it.
299
+ #
300
+ # @return [Hub]
301
+ def get_current_hub
302
+ # we need to assign a hub to the current thread if it doesn't have one yet
303
+ #
304
+ # ideally, we should do this proactively whenever a new thread is created
305
+ # but it's impossible for the SDK to keep track every new thread
306
+ # so we need to use this rather passive way to make sure the app doesn't crash
307
+ Thread.current.thread_variable_get(THREAD_LOCAL) || clone_hub_to_current_thread
308
+ end
309
+
310
+ # Returns the current active client.
311
+ # @return [Client, nil]
312
+ def get_current_client
313
+ return unless initialized?
314
+ get_current_hub.current_client
315
+ end
316
+
317
+ # Returns the current active scope.
318
+ #
319
+ # @return [Scope, nil]
320
+ def get_current_scope
321
+ return unless initialized?
322
+ get_current_hub.current_scope
323
+ end
324
+
325
+ # Clones the main thread's active hub and stores it to the current thread.
326
+ #
327
+ # @return [void]
328
+ def clone_hub_to_current_thread
329
+ return unless initialized?
330
+ Thread.current.thread_variable_set(THREAD_LOCAL, get_main_hub.clone)
331
+ end
332
+
333
+ # Takes a block and yields the current active scope.
334
+ #
335
+ # @example
336
+ # Sentry.configure_scope do |scope|
337
+ # scope.set_tags(foo: "bar")
338
+ # end
339
+ #
340
+ # Sentry.capture_message("test message") # this event will have tags { foo: "bar" }
341
+ #
342
+ # @yieldparam scope [Scope]
343
+ # @return [void]
344
+ def configure_scope(&block)
345
+ return unless initialized?
346
+ get_current_hub.configure_scope(&block)
347
+ end
348
+
349
+ # Takes a block and yields a temporary scope.
350
+ # The temporary scope will inherit all the attributes from the current active scope and replace it to be the active
351
+ # scope inside the block.
352
+ #
353
+ # @example
354
+ # Sentry.configure_scope do |scope|
355
+ # scope.set_tags(foo: "bar")
356
+ # end
357
+ #
358
+ # Sentry.capture_message("test message") # this event will have tags { foo: "bar" }
359
+ #
360
+ # Sentry.with_scope do |temp_scope|
361
+ # temp_scope.set_tags(foo: "baz")
362
+ # Sentry.capture_message("test message 2") # this event will have tags { foo: "baz" }
363
+ # end
364
+ #
365
+ # Sentry.capture_message("test message 3") # this event will have tags { foo: "bar" }
366
+ #
367
+ # @yieldparam scope [Scope]
368
+ # @return [void]
369
+ def with_scope(&block)
370
+ return yield unless initialized?
371
+ get_current_hub.with_scope(&block)
372
+ end
373
+
374
+ # Wrap a given block with session tracking.
375
+ # Aggregate sessions in minutely buckets will be recorded
376
+ # around this block and flushed every minute.
377
+ #
378
+ # @example
379
+ # Sentry.with_session_tracking do
380
+ # a = 1 + 1 # new session recorded with :exited status
381
+ # end
382
+ #
383
+ # Sentry.with_session_tracking do
384
+ # 1 / 0
385
+ # rescue => e
386
+ # Sentry.capture_exception(e) # new session recorded with :errored status
387
+ # end
388
+ # @return [void]
389
+ def with_session_tracking(&block)
390
+ return yield unless initialized?
391
+ get_current_hub.with_session_tracking(&block)
392
+ end
393
+
394
+ # Takes an exception and reports it to Sentry via the currently active hub.
395
+ #
396
+ # @yieldparam scope [Scope]
397
+ # @return [Event, nil]
398
+ def capture_exception(exception, **options, &block)
399
+ return unless initialized?
400
+ get_current_hub.capture_exception(exception, **options, &block)
401
+ end
402
+
403
+ # Takes a block and evaluates it. If the block raised an exception, it reports the exception to Sentry and re-raises it.
404
+ # If the block ran without exception, it returns the evaluation result.
405
+ #
406
+ # @example
407
+ # Sentry.with_exception_captured do
408
+ # 1/1 #=> 1 will be returned
409
+ # end
410
+ #
411
+ # Sentry.with_exception_captured do
412
+ # 1/0 #=> ZeroDivisionError will be reported and re-raised
413
+ # end
414
+ #
415
+ def with_exception_captured(**options, &block)
416
+ yield
417
+ rescue Exception => e
418
+ capture_exception(e, **options)
419
+ raise
420
+ end
421
+
422
+ # Takes a message string and reports it to Sentry via the currently active hub.
423
+ #
424
+ # @yieldparam scope [Scope]
425
+ # @return [Event, nil]
426
+ def capture_message(message, **options, &block)
427
+ return unless initialized?
428
+ get_current_hub.capture_message(message, **options, &block)
429
+ end
430
+
431
+ # Takes an instance of Sentry::Event and dispatches it to the currently active hub.
432
+ #
433
+ # @return [Event, nil]
434
+ def capture_event(event)
435
+ return unless initialized?
436
+ get_current_hub.capture_event(event)
437
+ end
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
+
455
+ # Takes or initializes a new Sentry::Transaction and makes a sampling decision for it.
456
+ #
457
+ # @return [Transaction, nil]
458
+ def start_transaction(**options)
459
+ return unless initialized?
460
+ get_current_hub.start_transaction(**options)
461
+ end
462
+
463
+ # Records the block's execution as a child of the current span.
464
+ # If the current scope doesn't have a span, the block would still be executed but the yield param will be nil.
465
+ # @param attributes [Hash] attributes for the child span.
466
+ # @yieldparam child_span [Span, nil]
467
+ # @return yield result
468
+ #
469
+ # @example
470
+ # Sentry.with_child_span(op: "my operation") do |child_span|
471
+ # child_span.set_data(operation_data)
472
+ # child_span.set_description(operation_detail)
473
+ # # result will be returned
474
+ # end
475
+ #
476
+ def with_child_span(**attributes, &block)
477
+ return yield(nil) unless Sentry.initialized?
478
+ get_current_hub.with_child_span(**attributes, &block)
479
+ end
480
+
481
+ # Returns the id of the lastly reported Sentry::Event.
482
+ #
483
+ # @return [String, nil]
484
+ def last_event_id
485
+ return unless initialized?
486
+ get_current_hub.last_event_id
487
+ end
488
+
489
+ # Checks if the exception object has been captured by the SDK.
490
+ #
491
+ # @return [Boolean]
492
+ def exception_captured?(exc)
493
+ return false unless initialized?
494
+ !!exc.instance_variable_get(CAPTURED_SIGNATURE)
495
+ end
496
+
497
+ # Add a global event processor [Proc].
498
+ # These run before scope event processors.
499
+ #
500
+ # @yieldparam event [Event]
501
+ # @yieldparam hint [Hash, nil]
502
+ # @return [void]
503
+ #
504
+ # @example
505
+ # Sentry.add_global_event_processor do |event, hint|
506
+ # event.tags = { foo: 42 }
507
+ # event
508
+ # end
509
+ #
510
+ def add_global_event_processor(&block)
511
+ Scope.add_global_event_processor(&block)
512
+ end
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
+
550
+ ##### Helpers #####
551
+
552
+ # @!visibility private
553
+ def sys_command(command)
554
+ result = `#{command} 2>&1` rescue nil
555
+ return if result.nil? || result.empty? || ($CHILD_STATUS && $CHILD_STATUS.exitstatus != 0)
556
+
557
+ result.strip
558
+ end
559
+
560
+ # @!visibility private
561
+ def logger
562
+ configuration.logger
563
+ end
564
+
565
+ # @!visibility private
566
+ def sdk_meta
567
+ META
568
+ end
569
+
570
+ # @!visibility private
571
+ def utc_now
572
+ Time.now.utc
573
+ end
574
+ end
575
+ end
576
+
577
+ # patches
578
+ require "sentry/net/http"
579
+ require "sentry/redis"
580
+ require "sentry/puma"
@@ -0,0 +1,23 @@
1
+ require_relative "lib/sentry/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "sentry-ruby-core"
5
+ spec.version = Sentry::VERSION
6
+ spec.authors = ["Sentry Team"]
7
+ spec.description = spec.summary = "A gem that provides a client interface for the Sentry error logger"
8
+ spec.email = "accounts@sentry.io"
9
+ spec.license = 'MIT'
10
+ spec.homepage = "https://github.com/getsentry/sentry-ruby"
11
+
12
+ spec.platform = Gem::Platform::RUBY
13
+ spec.required_ruby_version = '>= 2.4'
14
+ spec.extra_rdoc_files = ["README.md", "LICENSE.txt"]
15
+ spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n")
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
20
+
21
+ spec.add_dependency "sentry-ruby", Sentry::VERSION
22
+ spec.add_dependency "concurrent-ruby"
23
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "lib/sentry/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "sentry-ruby"
5
+ spec.version = Sentry::VERSION
6
+ spec.authors = ["Sentry Team"]
7
+ spec.description = spec.summary = "A gem that provides a client interface for the Sentry error logger"
8
+ spec.email = "accounts@sentry.io"
9
+ spec.license = 'MIT'
10
+ spec.homepage = "https://github.com/getsentry/sentry-ruby"
11
+
12
+ spec.platform = Gem::Platform::RUBY
13
+ spec.required_ruby_version = '>= 2.4'
14
+ spec.extra_rdoc_files = ["README.md", "LICENSE.txt"]
15
+ spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n")
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
20
+
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_dependency "concurrent-ruby", '~> 1.0', '>= 1.0.2'
24
+ end