sentry-ruby 5.16.1 → 5.18.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +10 -10
  4. data/Rakefile +1 -1
  5. data/bin/console +1 -0
  6. data/lib/sentry/background_worker.rb +1 -1
  7. data/lib/sentry/backpressure_monitor.rb +2 -32
  8. data/lib/sentry/backtrace.rb +7 -3
  9. data/lib/sentry/check_in_event.rb +1 -1
  10. data/lib/sentry/client.rb +42 -9
  11. data/lib/sentry/configuration.rb +20 -12
  12. data/lib/sentry/cron/monitor_schedule.rb +1 -1
  13. data/lib/sentry/dsn.rb +1 -1
  14. data/lib/sentry/envelope.rb +18 -1
  15. data/lib/sentry/error_event.rb +2 -2
  16. data/lib/sentry/event.rb +8 -8
  17. data/lib/sentry/graphql.rb +9 -0
  18. data/lib/sentry/hub.rb +13 -2
  19. data/lib/sentry/integrable.rb +4 -0
  20. data/lib/sentry/interface.rb +1 -0
  21. data/lib/sentry/interfaces/exception.rb +5 -3
  22. data/lib/sentry/interfaces/mechanism.rb +20 -0
  23. data/lib/sentry/interfaces/request.rb +2 -2
  24. data/lib/sentry/interfaces/single_exception.rb +6 -4
  25. data/lib/sentry/interfaces/stacktrace_builder.rb +8 -0
  26. data/lib/sentry/metrics/aggregator.rb +248 -0
  27. data/lib/sentry/metrics/configuration.rb +47 -0
  28. data/lib/sentry/metrics/counter_metric.rb +25 -0
  29. data/lib/sentry/metrics/distribution_metric.rb +25 -0
  30. data/lib/sentry/metrics/gauge_metric.rb +35 -0
  31. data/lib/sentry/metrics/local_aggregator.rb +53 -0
  32. data/lib/sentry/metrics/metric.rb +19 -0
  33. data/lib/sentry/metrics/set_metric.rb +28 -0
  34. data/lib/sentry/metrics/timing.rb +43 -0
  35. data/lib/sentry/metrics.rb +56 -0
  36. data/lib/sentry/net/http.rb +2 -1
  37. data/lib/sentry/propagation_context.rb +9 -8
  38. data/lib/sentry/puma.rb +1 -1
  39. data/lib/sentry/rack/capture_exceptions.rb +14 -2
  40. data/lib/sentry/rake.rb +3 -1
  41. data/lib/sentry/redis.rb +2 -1
  42. data/lib/sentry/scope.rb +21 -26
  43. data/lib/sentry/session.rb +2 -2
  44. data/lib/sentry/session_flusher.rb +6 -38
  45. data/lib/sentry/span.rb +39 -5
  46. data/lib/sentry/test_helper.rb +1 -1
  47. data/lib/sentry/threaded_periodic_worker.rb +39 -0
  48. data/lib/sentry/transaction.rb +15 -14
  49. data/lib/sentry/transaction_event.rb +5 -0
  50. data/lib/sentry/transport/configuration.rb +0 -1
  51. data/lib/sentry/transport.rb +8 -22
  52. data/lib/sentry/utils/argument_checking_helper.rb +6 -0
  53. data/lib/sentry/utils/logging_helper.rb +0 -4
  54. data/lib/sentry/utils/real_ip.rb +1 -1
  55. data/lib/sentry/utils/request_id.rb +1 -1
  56. data/lib/sentry/version.rb +1 -1
  57. data/lib/sentry-ruby.rb +26 -3
  58. data/sentry-ruby.gemspec +1 -0
  59. metadata +30 -3
@@ -50,14 +50,15 @@ module Sentry
50
50
  if sentry_trace_data
51
51
  @trace_id, @parent_span_id, @parent_sampled = sentry_trace_data
52
52
 
53
- @baggage = if baggage_header && !baggage_header.empty?
54
- Baggage.from_incoming_header(baggage_header)
55
- else
56
- # If there's an incoming sentry-trace but no incoming baggage header,
57
- # for instance in traces coming from older SDKs,
58
- # baggage will be empty and frozen and won't be populated as head SDK.
59
- Baggage.new({})
60
- end
53
+ @baggage =
54
+ if baggage_header && !baggage_header.empty?
55
+ Baggage.from_incoming_header(baggage_header)
56
+ else
57
+ # If there's an incoming sentry-trace but no incoming baggage header,
58
+ # for instance in traces coming from older SDKs,
59
+ # baggage will be empty and frozen and won't be populated as head SDK.
60
+ Baggage.new({})
61
+ end
61
62
 
62
63
  @baggage.freeze!
63
64
  @incoming_trace = true
data/lib/sentry/puma.rb CHANGED
@@ -7,7 +7,7 @@ module Sentry
7
7
  module Server
8
8
  PUMA_4_AND_PRIOR = Gem::Version.new(::Puma::Const::PUMA_VERSION) < Gem::Version.new("5.0.0")
9
9
 
10
- def lowlevel_error(e, env, status=500)
10
+ def lowlevel_error(e, env, status = 500)
11
11
  result =
12
12
  if PUMA_4_AND_PRIOR
13
13
  super(e, env)
@@ -4,6 +4,8 @@ module Sentry
4
4
  module Rack
5
5
  class CaptureExceptions
6
6
  ERROR_EVENT_ID_KEY = "sentry.error_event_id"
7
+ MECHANISM_TYPE = "rack"
8
+ SPAN_ORIGIN = "auto.http.rack"
7
9
 
8
10
  def initialize(app)
9
11
  @app = app
@@ -56,13 +58,19 @@ module Sentry
56
58
  end
57
59
 
58
60
  def capture_exception(exception, env)
59
- Sentry.capture_exception(exception).tap do |event|
61
+ Sentry.capture_exception(exception, hint: { mechanism: mechanism }).tap do |event|
60
62
  env[ERROR_EVENT_ID_KEY] = event.event_id if event
61
63
  end
62
64
  end
63
65
 
64
66
  def start_transaction(env, scope)
65
- options = { name: scope.transaction_name, source: scope.transaction_source, op: transaction_op }
67
+ options = {
68
+ name: scope.transaction_name,
69
+ source: scope.transaction_source,
70
+ op: transaction_op,
71
+ origin: SPAN_ORIGIN
72
+ }
73
+
66
74
  transaction = Sentry.continue_trace(env, **options)
67
75
  Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
68
76
  end
@@ -74,6 +82,10 @@ module Sentry
74
82
  transaction.set_http_status(status_code)
75
83
  transaction.finish
76
84
  end
85
+
86
+ def mechanism
87
+ Sentry::Mechanism.new(type: MECHANISM_TYPE, handled: false)
88
+ end
77
89
  end
78
90
  end
79
91
  end
data/lib/sentry/rake.rb CHANGED
@@ -8,7 +8,9 @@ module Sentry
8
8
  module Application
9
9
  # @api private
10
10
  def display_error_message(ex)
11
- Sentry.capture_exception(ex) do |scope|
11
+ mechanism = Sentry::Mechanism.new(type: 'rake', handled: false)
12
+
13
+ Sentry.capture_exception(ex, hint: { mechanism: mechanism }) do |scope|
12
14
  task_name = top_level_tasks.join(' ')
13
15
  scope.set_transaction_name(task_name, source: :task)
14
16
  scope.set_tag("rake_task", task_name)
data/lib/sentry/redis.rb CHANGED
@@ -4,6 +4,7 @@ module Sentry
4
4
  # @api private
5
5
  class Redis
6
6
  OP_NAME = "db.redis"
7
+ SPAN_ORIGIN = "auto.db.redis"
7
8
  LOGGER_NAME = :redis_logger
8
9
 
9
10
  def initialize(commands, host, port, db)
@@ -13,7 +14,7 @@ module Sentry
13
14
  def instrument
14
15
  return yield unless Sentry.initialized?
15
16
 
16
- Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |span|
17
+ Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) do |span|
17
18
  yield.tap do
18
19
  record_breadcrumb
19
20
 
data/lib/sentry/scope.rb CHANGED
@@ -9,8 +9,8 @@ module Sentry
9
9
  include ArgumentCheckingHelper
10
10
 
11
11
  ATTRIBUTES = [
12
- :transaction_names,
13
- :transaction_sources,
12
+ :transaction_name,
13
+ :transaction_source,
14
14
  :contexts,
15
15
  :extra,
16
16
  :tags,
@@ -96,8 +96,8 @@ module Sentry
96
96
  copy.extra = extra.deep_dup
97
97
  copy.tags = tags.deep_dup
98
98
  copy.user = user.deep_dup
99
- copy.transaction_names = transaction_names.dup
100
- copy.transaction_sources = transaction_sources.dup
99
+ copy.transaction_name = transaction_name.dup
100
+ copy.transaction_source = transaction_source.dup
101
101
  copy.fingerprint = fingerprint.deep_dup
102
102
  copy.span = span.deep_dup
103
103
  copy.session = session.deep_dup
@@ -114,8 +114,8 @@ module Sentry
114
114
  self.extra = scope.extra
115
115
  self.tags = scope.tags
116
116
  self.user = scope.user
117
- self.transaction_names = scope.transaction_names
118
- self.transaction_sources = scope.transaction_sources
117
+ self.transaction_name = scope.transaction_name
118
+ self.transaction_source = scope.transaction_source
119
119
  self.fingerprint = scope.fingerprint
120
120
  self.span = scope.span
121
121
  self.propagation_context = scope.propagation_context
@@ -128,14 +128,15 @@ module Sentry
128
128
  # @param user [Hash]
129
129
  # @param level [String, Symbol]
130
130
  # @param fingerprint [Array]
131
- # @return [void]
131
+ # @return [Array]
132
132
  def update_from_options(
133
133
  contexts: nil,
134
134
  extra: nil,
135
135
  tags: nil,
136
136
  user: nil,
137
137
  level: nil,
138
- fingerprint: nil
138
+ fingerprint: nil,
139
+ **options
139
140
  )
140
141
  self.contexts.merge!(contexts) if contexts
141
142
  self.extra.merge!(extra) if extra
@@ -143,6 +144,9 @@ module Sentry
143
144
  self.user = user if user
144
145
  self.level = level if level
145
146
  self.fingerprint = fingerprint if fingerprint
147
+
148
+ # Returns unsupported option keys so we can notify users.
149
+ options.keys
146
150
  end
147
151
 
148
152
  # Sets the scope's rack_env attribute.
@@ -227,8 +231,8 @@ module Sentry
227
231
  # @param transaction_name [String]
228
232
  # @return [void]
229
233
  def set_transaction_name(transaction_name, source: :custom)
230
- @transaction_names << transaction_name
231
- @transaction_sources << source
234
+ @transaction_name = transaction_name
235
+ @transaction_source = source
232
236
  end
233
237
 
234
238
  # Sets the currently active session on the scope.
@@ -238,18 +242,10 @@ module Sentry
238
242
  @session = session
239
243
  end
240
244
 
241
- # Returns current transaction name.
242
- # The "transaction" here does not refer to `Transaction` objects.
243
- # @return [String, nil]
244
- def transaction_name
245
- @transaction_names.last
246
- end
247
-
248
- # Returns current transaction source.
249
- # The "transaction" here does not refer to `Transaction` objects.
250
- # @return [String, nil]
251
- def transaction_source
252
- @transaction_sources.last
245
+ # These are high cardinality and thus bad.
246
+ # @return [Boolean]
247
+ def transaction_source_low_quality?
248
+ transaction_source == :url
253
249
  end
254
250
 
255
251
  # Returns the associated Transaction object.
@@ -295,14 +291,14 @@ module Sentry
295
291
  private
296
292
 
297
293
  def set_default_value
298
- @contexts = { :os => self.class.os_context, :runtime => self.class.runtime_context }
294
+ @contexts = { os: self.class.os_context, runtime: self.class.runtime_context }
299
295
  @extra = {}
300
296
  @tags = {}
301
297
  @user = {}
302
298
  @level = :error
303
299
  @fingerprint = []
304
- @transaction_names = []
305
- @transaction_sources = []
300
+ @transaction_name = nil
301
+ @transaction_source = nil
306
302
  @event_processors = []
307
303
  @rack_env = {}
308
304
  @span = nil
@@ -355,6 +351,5 @@ module Sentry
355
351
  global_event_processors << block
356
352
  end
357
353
  end
358
-
359
354
  end
360
355
  end
@@ -5,8 +5,8 @@ module Sentry
5
5
  attr_reader :started, :status, :aggregation_key
6
6
 
7
7
  # TODO-neel add :crashed after adding handled mechanism
8
- STATUSES = %i(ok errored exited)
9
- AGGREGATE_STATUSES = %i(errored exited)
8
+ STATUSES = %i[ok errored exited]
9
+ AGGREGATE_STATUSES = %i[errored exited]
10
10
 
11
11
  def initialize
12
12
  @started = Sentry.utc_now
@@ -1,58 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentry
4
- class SessionFlusher
5
- include LoggingHelper
6
-
4
+ class SessionFlusher < ThreadedPeriodicWorker
7
5
  FLUSH_INTERVAL = 60
8
6
 
9
7
  def initialize(configuration, client)
10
- @thread = nil
11
- @exited = false
8
+ super(configuration.logger, FLUSH_INTERVAL)
12
9
  @client = client
13
10
  @pending_aggregates = {}
14
11
  @release = configuration.release
15
12
  @environment = configuration.environment
16
- @logger = configuration.logger
17
13
 
18
14
  log_debug("[Sessions] Sessions won't be captured without a valid release") unless @release
19
15
  end
20
16
 
21
17
  def flush
22
18
  return if @pending_aggregates.empty?
23
- envelope = pending_envelope
24
-
25
- Sentry.background_worker.perform do
26
- @client.transport.send_envelope(envelope)
27
- end
28
19
 
20
+ @client.capture_envelope(pending_envelope)
29
21
  @pending_aggregates = {}
30
22
  end
31
23
 
24
+ alias_method :run, :flush
25
+
32
26
  def add_session(session)
33
- return if @exited
34
27
  return unless @release
35
28
 
36
- begin
37
- ensure_thread
38
- rescue ThreadError
39
- log_debug("Session flusher thread creation failed")
40
- @exited = true
41
- return
42
- end
29
+ return unless ensure_thread
43
30
 
44
31
  return unless Session::AGGREGATE_STATUSES.include?(session.status)
45
32
  @pending_aggregates[session.aggregation_key] ||= init_aggregates(session.aggregation_key)
46
33
  @pending_aggregates[session.aggregation_key][session.status] += 1
47
34
  end
48
35
 
49
- def kill
50
- log_debug("Killing session flusher")
51
-
52
- @exited = true
53
- @thread&.kill
54
- end
55
-
56
36
  private
57
37
 
58
38
  def init_aggregates(aggregation_key)
@@ -74,17 +54,5 @@ module Sentry
74
54
  def attrs
75
55
  { release: @release, environment: @environment }
76
56
  end
77
-
78
- def ensure_thread
79
- return if @thread&.alive?
80
-
81
- @thread = Thread.new do
82
- loop do
83
- sleep(FLUSH_INTERVAL)
84
- flush
85
- end
86
- end
87
- end
88
-
89
57
  end
90
58
  end
data/lib/sentry/span.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "securerandom"
4
+ require "sentry/metrics/local_aggregator"
4
5
 
5
6
  module Sentry
6
7
  class Span
7
-
8
8
  # We will try to be consistent with OpenTelemetry on this front going forward.
9
9
  # https://develop.sentry.dev/sdk/performance/span-data-conventions/
10
10
  module DataConventions
@@ -39,6 +39,11 @@ module Sentry
39
39
  # Recommended: If different than server.port.
40
40
  # Example: 16456
41
41
  SERVER_SOCKET_PORT = "server.socket.port"
42
+
43
+ FILEPATH = "code.filepath"
44
+ LINENO = "code.lineno"
45
+ FUNCTION = "code.function"
46
+ NAMESPACE = "code.namespace"
42
47
  end
43
48
 
44
49
  STATUS_MAP = {
@@ -55,6 +60,8 @@ module Sentry
55
60
  504 => "deadline_exceeded"
56
61
  }
57
62
 
63
+ DEFAULT_SPAN_ORIGIN = "manual"
64
+
58
65
  # An uuid that can be used to identify a trace.
59
66
  # @return [String]
60
67
  attr_reader :trace_id
@@ -88,6 +95,9 @@ module Sentry
88
95
  # Span data
89
96
  # @return [Hash]
90
97
  attr_reader :data
98
+ # Span origin that tracks what kind of instrumentation created a span
99
+ # @return [String]
100
+ attr_reader :origin
91
101
 
92
102
  # The SpanRecorder the current span belongs to.
93
103
  # SpanRecorder holds all spans under the same Transaction object (including the Transaction itself).
@@ -109,7 +119,8 @@ module Sentry
109
119
  parent_span_id: nil,
110
120
  sampled: nil,
111
121
  start_timestamp: nil,
112
- timestamp: nil
122
+ timestamp: nil,
123
+ origin: nil
113
124
  )
114
125
  @trace_id = trace_id || SecureRandom.uuid.delete("-")
115
126
  @span_id = span_id || SecureRandom.uuid.delete("-").slice(0, 16)
@@ -123,6 +134,7 @@ module Sentry
123
134
  @status = status
124
135
  @data = {}
125
136
  @tags = {}
137
+ @origin = origin || DEFAULT_SPAN_ORIGIN
126
138
  end
127
139
 
128
140
  # Finishes the span by adding a timestamp.
@@ -150,7 +162,7 @@ module Sentry
150
162
 
151
163
  # @return [Hash]
152
164
  def to_hash
153
- {
165
+ hash = {
154
166
  trace_id: @trace_id,
155
167
  span_id: @span_id,
156
168
  parent_span_id: @parent_span_id,
@@ -160,8 +172,14 @@ module Sentry
160
172
  op: @op,
161
173
  status: @status,
162
174
  tags: @tags,
163
- data: @data
175
+ data: @data,
176
+ origin: @origin
164
177
  }
178
+
179
+ summary = metrics_summary
180
+ hash[:_metrics_summary] = summary if summary
181
+
182
+ hash
165
183
  end
166
184
 
167
185
  # Returns the span's context that can be used to embed in an Event.
@@ -173,7 +191,8 @@ module Sentry
173
191
  parent_span_id: @parent_span_id,
174
192
  description: @description,
175
193
  op: @op,
176
- status: @status
194
+ status: @status,
195
+ origin: @origin
177
196
  }
178
197
  end
179
198
 
@@ -269,5 +288,20 @@ module Sentry
269
288
  def set_tag(key, value)
270
289
  @tags[key] = value
271
290
  end
291
+
292
+ # Sets the origin of the span.
293
+ # @param origin [String]
294
+ def set_origin(origin)
295
+ @origin = origin
296
+ end
297
+
298
+ # Collects gauge metrics on the span for metric summaries.
299
+ def metrics_local_aggregator
300
+ @metrics_local_aggregator ||= Sentry::Metrics::LocalAggregator.new
301
+ end
302
+
303
+ def metrics_summary
304
+ @metrics_local_aggregator&.to_hash
305
+ end
272
306
  end
273
307
  end
@@ -20,7 +20,7 @@ module Sentry
20
20
  # set transport to DummyTransport, so we can easily intercept the captured events
21
21
  dummy_config.transport.transport_class = Sentry::DummyTransport
22
22
  # make sure SDK allows sending under the current environment
23
- dummy_config.enabled_environments << dummy_config.environment unless dummy_config.enabled_environments.include?(dummy_config.environment)
23
+ dummy_config.enabled_environments += [dummy_config.environment] unless dummy_config.enabled_environments.include?(dummy_config.environment)
24
24
  # disble async event sending
25
25
  dummy_config.background_worker_threads = 0
26
26
 
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ class ThreadedPeriodicWorker
5
+ include LoggingHelper
6
+
7
+ def initialize(logger, internal)
8
+ @thread = nil
9
+ @exited = false
10
+ @interval = internal
11
+ @logger = logger
12
+ end
13
+
14
+ def ensure_thread
15
+ return false if @exited
16
+ return true if @thread&.alive?
17
+
18
+ @thread = Thread.new do
19
+ loop do
20
+ sleep(@interval)
21
+ run
22
+ end
23
+ end
24
+
25
+ true
26
+ rescue ThreadError
27
+ log_debug("[#{self.class.name}] thread creation failed")
28
+ @exited = true
29
+ false
30
+ end
31
+
32
+ def kill
33
+ log_debug("[#{self.class.name}] thread killed")
34
+
35
+ @exited = true
36
+ @thread&.kill
37
+ end
38
+ end
39
+ end
@@ -13,7 +13,7 @@ module Sentry
13
13
  MESSAGE_PREFIX = "[Tracing]"
14
14
 
15
15
  # https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations
16
- SOURCES = %i(custom url route view component task)
16
+ SOURCES = %i[custom url route view component task]
17
17
 
18
18
  include LoggingHelper
19
19
 
@@ -110,14 +110,15 @@ module Sentry
110
110
 
111
111
  trace_id, parent_span_id, parent_sampled = sentry_trace_data
112
112
 
113
- baggage = if baggage && !baggage.empty?
114
- Baggage.from_incoming_header(baggage)
115
- else
116
- # If there's an incoming sentry-trace but no incoming baggage header,
117
- # for instance in traces coming from older SDKs,
118
- # baggage will be empty and frozen and won't be populated as head SDK.
119
- Baggage.new({})
120
- end
113
+ baggage =
114
+ if baggage && !baggage.empty?
115
+ Baggage.from_incoming_header(baggage)
116
+ else
117
+ # If there's an incoming sentry-trace but no incoming baggage header,
118
+ # for instance in traces coming from older SDKs,
119
+ # baggage will be empty and frozen and won't be populated as head SDK.
120
+ Baggage.new({})
121
+ end
121
122
 
122
123
  baggage.freeze!
123
124
 
@@ -301,6 +302,11 @@ module Sentry
301
302
  profiler.start
302
303
  end
303
304
 
305
+ # These are high cardinality and thus bad
306
+ def source_low_quality?
307
+ source == :url
308
+ end
309
+
304
310
  protected
305
311
 
306
312
  def init_span_recorder(limit = 1000)
@@ -336,11 +342,6 @@ module Sentry
336
342
  @baggage = Baggage.new(items, mutable: false)
337
343
  end
338
344
 
339
- # These are high cardinality and thus bad
340
- def source_low_quality?
341
- source == :url
342
- end
343
-
344
345
  class SpanRecorder
345
346
  attr_reader :max_length, :spans
346
347
 
@@ -17,6 +17,9 @@ module Sentry
17
17
  # @return [Hash, nil]
18
18
  attr_accessor :profile
19
19
 
20
+ # @return [Hash, nil]
21
+ attr_accessor :metrics_summary
22
+
20
23
  def initialize(transaction:, **options)
21
24
  super(**options)
22
25
 
@@ -29,6 +32,7 @@ module Sentry
29
32
  self.tags = transaction.tags
30
33
  self.dynamic_sampling_context = transaction.get_baggage.dynamic_sampling_context
31
34
  self.measurements = transaction.measurements
35
+ self.metrics_summary = transaction.metrics_summary
32
36
 
33
37
  finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
34
38
  self.spans = finished_spans.map(&:to_hash)
@@ -49,6 +53,7 @@ module Sentry
49
53
  data[:spans] = @spans.map(&:to_hash) if @spans
50
54
  data[:start_timestamp] = @start_timestamp
51
55
  data[:measurements] = @measurements
56
+ data[:_metrics_summary] = @metrics_summary if @metrics_summary
52
57
  data
53
58
  end
54
59
 
@@ -3,7 +3,6 @@
3
3
  module Sentry
4
4
  class Transport
5
5
  class Configuration
6
-
7
6
  # The timeout in seconds to open a connection to Sentry, in seconds.
8
7
  # Default value is 2.
9
8
  #
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "json"
4
- require "base64"
5
4
  require "sentry/envelope"
6
5
 
7
6
  module Sentry
@@ -62,7 +61,7 @@ module Sentry
62
61
  data, serialized_items = serialize_envelope(envelope)
63
62
 
64
63
  if data
65
- log_info("[Transport] Sending envelope with items [#{serialized_items.map(&:type).join(', ')}] #{envelope.event_id} to Sentry")
64
+ log_debug("[Transport] Sending envelope with items [#{serialized_items.map(&:type).join(', ')}] #{envelope.event_id} to Sentry")
66
65
  send_data(data)
67
66
  end
68
67
  end
@@ -89,18 +88,9 @@ module Sentry
89
88
  [data, serialized_items]
90
89
  end
91
90
 
92
- def is_rate_limited?(item_type)
91
+ def is_rate_limited?(data_category)
93
92
  # check category-specific limit
94
- category_delay =
95
- case item_type
96
- when "transaction"
97
- @rate_limits["transaction"]
98
- when "sessions"
99
- @rate_limits["session"]
100
- else
101
- @rate_limits["error"]
102
- end
103
-
93
+ category_delay = @rate_limits[data_category]
104
94
  # check universal limit if not category limit
105
95
  universal_delay = @rate_limits[nil]
106
96
 
@@ -161,11 +151,11 @@ module Sentry
161
151
  envelope
162
152
  end
163
153
 
164
- def record_lost_event(reason, item_type)
154
+ def record_lost_event(reason, data_category)
165
155
  return unless @send_client_reports
166
156
  return unless CLIENT_REPORT_REASONS.include?(reason)
167
157
 
168
- @discarded_events[[reason, item_type]] += 1
158
+ @discarded_events[[reason, data_category]] += 1
169
159
  end
170
160
 
171
161
  def flush
@@ -185,11 +175,7 @@ module Sentry
185
175
  return nil if @discarded_events.empty?
186
176
 
187
177
  discarded_events_hash = @discarded_events.map do |key, val|
188
- reason, type = key
189
-
190
- # 'event' has to be mapped to 'error'
191
- category = type == 'event' ? 'error' : type
192
-
178
+ reason, category = key
193
179
  { reason: reason, category: category, quantity: val }
194
180
  end
195
181
 
@@ -207,9 +193,9 @@ module Sentry
207
193
 
208
194
  def reject_rate_limited_items(envelope)
209
195
  envelope.items.reject! do |item|
210
- if is_rate_limited?(item.type)
196
+ if is_rate_limited?(item.data_category)
211
197
  log_debug("[Transport] Envelope item [#{item.type}] not sent: rate limiting")
212
- record_lost_event(:ratelimit_backoff, item.type)
198
+ record_lost_event(:ratelimit_backoff, item.data_category)
213
199
 
214
200
  true
215
201
  else
@@ -15,5 +15,11 @@ module Sentry
15
15
  raise ArgumentError, "expect the argument to be one of #{values.map(&:inspect).join(' or ')}, got #{argument.inspect}"
16
16
  end
17
17
  end
18
+
19
+ def check_callable!(name, value)
20
+ unless value == nil || value.respond_to?(:call)
21
+ raise ArgumentError, "#{name} must be callable (or nil to disable)"
22
+ end
23
+ end
18
24
  end
19
25
  end
@@ -11,10 +11,6 @@ module Sentry
11
11
  end
12
12
  end
13
13
 
14
- def log_info(message)
15
- @logger.info(LOGGER_PROGNAME) { message }
16
- end
17
-
18
14
  def log_debug(message)
19
15
  @logger.debug(LOGGER_PROGNAME) { message }
20
16
  end
@@ -15,7 +15,7 @@ module Sentry
15
15
  "fc00::/7", # private IPv6 range fc00::/7
16
16
  "10.0.0.0/8", # private IPv4 range 10.x.x.x
17
17
  "172.16.0.0/12", # private IPv4 range 172.16.0.0 .. 172.31.255.255
18
- "192.168.0.0/16", # private IPv4 range 192.168.x.x
18
+ "192.168.0.0/16" # private IPv4 range 192.168.x.x
19
19
  ]
20
20
 
21
21
  attr_reader :ip