sentry-ruby 5.26.0 → 6.3.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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +26 -4
  3. data/README.md +2 -2
  4. data/lib/sentry/background_worker.rb +1 -4
  5. data/lib/sentry/backtrace/line.rb +99 -0
  6. data/lib/sentry/backtrace.rb +44 -76
  7. data/lib/sentry/breadcrumb.rb +1 -1
  8. data/lib/sentry/breadcrumb_buffer.rb +2 -2
  9. data/lib/sentry/check_in_event.rb +2 -2
  10. data/lib/sentry/client.rb +59 -136
  11. data/lib/sentry/configuration.rb +168 -78
  12. data/lib/sentry/cron/monitor_check_ins.rb +3 -3
  13. data/lib/sentry/cron/monitor_config.rb +2 -2
  14. data/lib/sentry/cron/monitor_schedule.rb +2 -2
  15. data/lib/sentry/debug_structured_logger.rb +94 -0
  16. data/lib/sentry/dsn.rb +32 -0
  17. data/lib/sentry/envelope/item.rb +3 -3
  18. data/lib/sentry/error_event.rb +3 -3
  19. data/lib/sentry/event.rb +4 -10
  20. data/lib/sentry/graphql.rb +1 -1
  21. data/lib/sentry/hub.rb +29 -5
  22. data/lib/sentry/interface.rb +1 -1
  23. data/lib/sentry/interfaces/exception.rb +2 -2
  24. data/lib/sentry/interfaces/request.rb +2 -0
  25. data/lib/sentry/interfaces/single_exception.rb +4 -4
  26. data/lib/sentry/interfaces/stacktrace.rb +3 -3
  27. data/lib/sentry/interfaces/stacktrace_builder.rb +0 -8
  28. data/lib/sentry/interfaces/threads.rb +2 -2
  29. data/lib/sentry/log_event.rb +33 -138
  30. data/lib/sentry/log_event_buffer.rb +13 -60
  31. data/lib/sentry/metric_event.rb +49 -0
  32. data/lib/sentry/metric_event_buffer.rb +28 -0
  33. data/lib/sentry/metrics.rb +47 -42
  34. data/lib/sentry/profiler.rb +4 -5
  35. data/lib/sentry/propagation_context.rb +55 -18
  36. data/lib/sentry/rspec.rb +1 -1
  37. data/lib/sentry/scope.rb +32 -5
  38. data/lib/sentry/sequel.rb +35 -0
  39. data/lib/sentry/span.rb +2 -17
  40. data/lib/sentry/std_lib_logger.rb +10 -1
  41. data/lib/sentry/telemetry_event_buffer.rb +130 -0
  42. data/lib/sentry/test_helper.rb +30 -0
  43. data/lib/sentry/transaction.rb +72 -95
  44. data/lib/sentry/transaction_event.rb +4 -9
  45. data/lib/sentry/transport/debug_transport.rb +70 -0
  46. data/lib/sentry/transport/dummy_transport.rb +1 -0
  47. data/lib/sentry/transport/http_transport.rb +9 -5
  48. data/lib/sentry/transport.rb +3 -5
  49. data/lib/sentry/utils/encoding_helper.rb +6 -0
  50. data/lib/sentry/utils/logging_helper.rb +25 -9
  51. data/lib/sentry/utils/sample_rand.rb +97 -0
  52. data/lib/sentry/utils/telemetry_attributes.rb +30 -0
  53. data/lib/sentry/vernier/profiler.rb +4 -3
  54. data/lib/sentry/version.rb +1 -1
  55. data/lib/sentry-ruby.rb +25 -30
  56. data/sentry-ruby-core.gemspec +1 -1
  57. data/sentry-ruby.gemspec +1 -1
  58. metadata +17 -17
  59. data/lib/sentry/metrics/aggregator.rb +0 -248
  60. data/lib/sentry/metrics/configuration.rb +0 -47
  61. data/lib/sentry/metrics/counter_metric.rb +0 -25
  62. data/lib/sentry/metrics/distribution_metric.rb +0 -25
  63. data/lib/sentry/metrics/gauge_metric.rb +0 -35
  64. data/lib/sentry/metrics/local_aggregator.rb +0 -53
  65. data/lib/sentry/metrics/metric.rb +0 -19
  66. data/lib/sentry/metrics/set_metric.rb +0 -28
  67. data/lib/sentry/metrics/timing.rb +0 -51
data/lib/sentry/event.rb CHANGED
@@ -81,12 +81,6 @@ module Sentry
81
81
  @message = (message || "").byteslice(0..MAX_MESSAGE_SIZE_IN_BYTES)
82
82
  end
83
83
 
84
- # @deprecated This method will be removed in v5.0.0. Please just use Sentry.configuration
85
- # @return [Configuration]
86
- def configuration
87
- Sentry.configuration
88
- end
89
-
90
84
  # Sets the event's timestamp.
91
85
  # @param time [Time, Float]
92
86
  # @return [void]
@@ -118,16 +112,16 @@ module Sentry
118
112
  end
119
113
 
120
114
  # @return [Hash]
121
- def to_hash
115
+ def to_h
122
116
  data = serialize_attributes
123
- data[:breadcrumbs] = breadcrumbs.to_hash if breadcrumbs
124
- data[:request] = request.to_hash if request
117
+ data[:breadcrumbs] = breadcrumbs.to_h if breadcrumbs
118
+ data[:request] = request.to_h if request
125
119
  data
126
120
  end
127
121
 
128
122
  # @return [Hash]
129
123
  def to_json_compatible
130
- JSON.parse(JSON.generate(to_hash))
124
+ JSON.parse(JSON.generate(to_h))
131
125
  end
132
126
 
133
127
  private
@@ -4,6 +4,6 @@ Sentry.register_patch(:graphql) do |config|
4
4
  if defined?(::GraphQL::Schema) && defined?(::GraphQL::Tracing::SentryTrace) && ::GraphQL::Schema.respond_to?(:trace_with)
5
5
  ::GraphQL::Schema.trace_with(::GraphQL::Tracing::SentryTrace, set_transaction_name: true)
6
6
  else
7
- config.logger.warn(Sentry::LOGGER_PROGNAME) { "You tried to enable the GraphQL integration but no GraphQL gem was detected. Make sure you have the `graphql` gem (>= 2.2.6) in your Gemfile." }
7
+ config.sdk_logger.warn(Sentry::LOGGER_PROGNAME) { "You tried to enable the GraphQL integration but no GraphQL gem was detected. Make sure you have the `graphql` gem (>= 2.2.6) in your Gemfile." }
8
8
  end
9
9
  end
data/lib/sentry/hub.rb CHANGED
@@ -116,11 +116,12 @@ module Sentry
116
116
  return unless configuration.tracing_enabled?
117
117
  return unless instrumenter == configuration.instrumenter
118
118
 
119
- transaction ||= Transaction.new(**options.merge(hub: self))
119
+ transaction ||= Transaction.new(**options)
120
120
 
121
121
  sampling_context = {
122
- transaction_context: transaction.to_hash,
123
- parent_sampled: transaction.parent_sampled
122
+ transaction_context: transaction.to_h,
123
+ parent_sampled: transaction.parent_sampled,
124
+ parent_sample_rate: transaction.parent_sample_rate
124
125
  }
125
126
 
126
127
  sampling_context.merge!(custom_sampling_context)
@@ -217,7 +218,7 @@ module Sentry
217
218
  end
218
219
 
219
220
  def capture_log_event(message, **options)
220
- return unless current_client
221
+ return unless current_client && current_client.configuration.enable_logs
221
222
 
222
223
  event = current_client.event_from_log(message, **options)
223
224
 
@@ -226,6 +227,29 @@ module Sentry
226
227
  current_client.buffer_log_event(event, current_scope)
227
228
  end
228
229
 
230
+ # Captures a metric and sends it to Sentry
231
+ #
232
+ # @param name [String] the metric name
233
+ # @param type [Symbol] the metric type (:counter, :gauge, :distribution)
234
+ # @param value [Numeric] the metric value
235
+ # @param unit [String, nil] (optional) the metric unit
236
+ # @param attributes [Hash, nil] (optional) additional attributes for the metric
237
+ # @return [void]
238
+ def capture_metric(name:, type:, value:, unit: nil, attributes: nil)
239
+ return unless current_client&.configuration.enable_metrics
240
+
241
+ metric = MetricEvent.new(
242
+ name: name,
243
+ value: value,
244
+ type: type,
245
+ unit: unit,
246
+ attributes: attributes,
247
+ )
248
+
249
+ current_client.buffer_metric_event(metric, current_scope)
250
+ end
251
+
252
+
229
253
  def capture_event(event, **options, &block)
230
254
  check_argument_type!(event, Sentry::Event)
231
255
 
@@ -352,11 +376,11 @@ module Sentry
352
376
  return nil unless propagation_context.incoming_trace
353
377
 
354
378
  Transaction.new(
355
- hub: self,
356
379
  trace_id: propagation_context.trace_id,
357
380
  parent_span_id: propagation_context.parent_span_id,
358
381
  parent_sampled: propagation_context.parent_sampled,
359
382
  baggage: propagation_context.baggage,
383
+ sample_rand: propagation_context.sample_rand,
360
384
  **options
361
385
  )
362
386
  end
@@ -3,7 +3,7 @@
3
3
  module Sentry
4
4
  class Interface
5
5
  # @return [Hash]
6
- def to_hash
6
+ def to_h
7
7
  Hash[instance_variables.map { |name| [name[1..-1].to_sym, instance_variable_get(name)] }]
8
8
  end
9
9
  end
@@ -13,9 +13,9 @@ module Sentry
13
13
  end
14
14
 
15
15
  # @return [Hash]
16
- def to_hash
16
+ def to_h
17
17
  data = super
18
- data[:values] = data[:values].map(&:to_hash) if data[:values]
18
+ data[:values] = data[:values].map(&:to_h) if data[:values]
19
19
  data
20
20
  end
21
21
 
@@ -69,6 +69,8 @@ module Sentry
69
69
  private
70
70
 
71
71
  def read_data_from(request)
72
+ return "Skipped non-rewindable request body" unless request.body.respond_to?(:rewind)
73
+
72
74
  if request.form_data?
73
75
  request.POST
74
76
  elsif request.body # JSON requests, etc
@@ -32,10 +32,10 @@ module Sentry
32
32
  @mechanism = mechanism
33
33
  end
34
34
 
35
- def to_hash
35
+ def to_h
36
36
  data = super
37
- data[:stacktrace] = data[:stacktrace].to_hash if data[:stacktrace]
38
- data[:mechanism] = data[:mechanism].to_hash
37
+ data[:stacktrace] = data[:stacktrace].to_h if data[:stacktrace]
38
+ data[:mechanism] = data[:mechanism].to_h
39
39
  data
40
40
  end
41
41
 
@@ -60,7 +60,7 @@ module Sentry
60
60
  end
61
61
  end
62
62
 
63
- stacktrace.frames.last.vars = locals
63
+ stacktrace.frames.last&.vars = locals
64
64
  end
65
65
 
66
66
  new(exception: exception, stacktrace: stacktrace, mechanism: mechanism)
@@ -11,8 +11,8 @@ module Sentry
11
11
  end
12
12
 
13
13
  # @return [Hash]
14
- def to_hash
15
- { frames: @frames.map(&:to_hash) }
14
+ def to_h
15
+ { frames: @frames.map(&:to_h) }
16
16
  end
17
17
 
18
18
  # @return [String]
@@ -66,7 +66,7 @@ module Sentry
66
66
  linecache.get_file_context(abs_path, lineno, context_lines)
67
67
  end
68
68
 
69
- def to_hash(*args)
69
+ def to_h(*args)
70
70
  data = super(*args)
71
71
  data.delete(:vars) unless vars && !vars.empty?
72
72
  data.delete(:pre_context) unless pre_context && !pre_context.empty?
@@ -75,14 +75,6 @@ module Sentry
75
75
  StacktraceInterface.new(frames: frames)
76
76
  end
77
77
 
78
- # Get the code location hash for a single line for where metrics where added.
79
- # @return [Hash]
80
- def metrics_code_location(unparsed_line)
81
- parsed_line = Backtrace::Line.parse(unparsed_line)
82
- frame = convert_parsed_line_into_frame(parsed_line)
83
- frame.to_hash.reject { |k, _| %i[project_root in_app].include?(k) }
84
- end
85
-
86
78
  private
87
79
 
88
80
  def convert_parsed_line_into_frame(line)
@@ -13,7 +13,7 @@ module Sentry
13
13
  end
14
14
 
15
15
  # @return [Hash]
16
- def to_hash
16
+ def to_h
17
17
  {
18
18
  values: [
19
19
  {
@@ -21,7 +21,7 @@ module Sentry
21
21
  name: @name,
22
22
  crashed: @crashed,
23
23
  current: @current,
24
- stacktrace: @stacktrace&.to_hash
24
+ stacktrace: @stacktrace&.to_h
25
25
  }
26
26
  ]
27
27
  }
@@ -1,129 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "sentry/utils/telemetry_attributes"
4
+
3
5
  module Sentry
4
6
  # Event type that represents a log entry with its attributes
5
7
  #
6
8
  # @see https://develop.sentry.dev/sdk/telemetry/logs/#log-envelope-item-payload
7
9
  class LogEvent
10
+ include Sentry::Utils::TelemetryAttributes
11
+
8
12
  TYPE = "log"
9
13
 
10
14
  DEFAULT_PARAMETERS = [].freeze
11
- DEFAULT_ATTRIBUTES = {}.freeze
12
-
13
- SERIALIZEABLE_ATTRIBUTES = %i[
14
- level
15
- body
16
- timestamp
17
- environment
18
- release
19
- server_name
20
- trace_id
21
- attributes
22
- contexts
23
- ]
24
-
25
- SENTRY_ATTRIBUTES = {
26
- "sentry.trace.parent_span_id" => :parent_span_id,
27
- "sentry.environment" => :environment,
28
- "sentry.release" => :release,
29
- "sentry.address" => :server_name,
30
- "sentry.sdk.name" => :sdk_name,
31
- "sentry.sdk.version" => :sdk_version,
32
- "sentry.message.template" => :template
33
- }
34
-
35
- USER_ATTRIBUTES = {
36
- "user.id" => :user_id,
37
- "user.name" => :user_username,
38
- "user.email" => :user_email
39
- }
15
+
16
+ PARAMETER_PREFIX = "sentry.message.parameter"
40
17
 
41
18
  LEVELS = %i[trace debug info warn error fatal].freeze
42
19
 
43
- attr_accessor :level, :body, :template, :attributes, :user
44
-
45
- attr_reader :configuration, *SERIALIZEABLE_ATTRIBUTES
46
-
47
- SERIALIZERS = %i[
48
- attributes
49
- body
50
- level
51
- parent_span_id
52
- sdk_name
53
- sdk_version
54
- timestamp
55
- trace_id
56
- user_id
57
- user_username
58
- user_email
59
- ].map { |name| [name, :"serialize_#{name}"] }.to_h
60
-
61
- VALUE_TYPES = Hash.new("string").merge!({
62
- TrueClass => "boolean",
63
- FalseClass => "boolean",
64
- Integer => "integer",
65
- Float => "double"
66
- }).freeze
20
+ attr_accessor :level, :body, :template, :attributes, :origin, :trace_id, :span_id
21
+ attr_reader :timestamp
67
22
 
68
23
  TOKEN_REGEXP = /%\{(\w+)\}/
69
24
 
70
- def initialize(configuration: Sentry.configuration, **options)
71
- @configuration = configuration
25
+ def initialize(**options)
72
26
  @type = TYPE
73
- @server_name = configuration.server_name
74
- @environment = configuration.environment
75
- @release = configuration.release
76
27
  @timestamp = Sentry.utc_now
77
28
  @level = options.fetch(:level)
78
29
  @body = options[:body]
79
30
  @template = @body if is_template?
80
- @attributes = options[:attributes] || DEFAULT_ATTRIBUTES
81
- @user = options[:user] || {}
82
- @contexts = {}
31
+ @attributes = options[:attributes] || {}
32
+ @origin = options[:origin]
33
+ @trace_id = nil
34
+ @span_id = nil
83
35
  end
84
36
 
85
- def to_hash
86
- SERIALIZEABLE_ATTRIBUTES.each_with_object({}) do |name, memo|
87
- memo[name] = serialize(name)
88
- end
37
+ def to_h
38
+ {
39
+ level: level.to_s,
40
+ timestamp: timestamp.to_f,
41
+ trace_id: @trace_id,
42
+ span_id: @span_id,
43
+ body: serialize_body,
44
+ attributes: serialize_attributes
45
+ }.compact
89
46
  end
90
47
 
91
48
  private
92
49
 
93
- def serialize(name)
94
- serializer = SERIALIZERS[name]
95
-
96
- if serializer
97
- __send__(serializer)
98
- else
99
- public_send(name)
100
- end
101
- end
102
-
103
- def serialize_level
104
- level.to_s
105
- end
106
-
107
- def serialize_sdk_name
108
- Sentry.sdk_meta["name"]
109
- end
110
-
111
- def serialize_sdk_version
112
- Sentry.sdk_meta["version"]
113
- end
114
-
115
- def serialize_timestamp
116
- timestamp.to_f
117
- end
118
-
119
- def serialize_trace_id
120
- contexts.dig(:trace, :trace_id)
121
- end
122
-
123
- def serialize_parent_span_id
124
- contexts.dig(:trace, :parent_span_id)
125
- end
126
-
127
50
  def serialize_body
128
51
  if parameters.empty?
129
52
  body
@@ -134,46 +57,14 @@ module Sentry
134
57
  end
135
58
  end
136
59
 
137
- def serialize_user_id
138
- user[:id]
139
- end
140
-
141
- def serialize_user_username
142
- user[:username]
143
- end
144
-
145
- def serialize_user_email
146
- user[:email]
147
- end
148
-
149
60
  def serialize_attributes
150
- hash = {}
151
-
152
- attributes.each do |key, value|
153
- hash[key] = attribute_hash(value)
154
- end
155
-
156
- SENTRY_ATTRIBUTES.each do |key, name|
157
- if (value = serialize(name))
158
- hash[key] = attribute_hash(value)
159
- end
160
- end
161
-
162
- USER_ATTRIBUTES.each do |key, name|
163
- if (value = serialize(name))
164
- hash[key] = value
165
- end
166
- end
167
-
168
- hash
169
- end
170
-
171
- def attribute_hash(value)
172
- { value: value, type: value_type(value) }
61
+ populate_sentry_attributes!
62
+ @attributes.transform_values! { |v| attribute_hash(v) }
173
63
  end
174
64
 
175
- def value_type(value)
176
- VALUE_TYPES[value.class]
65
+ def populate_sentry_attributes!
66
+ @attributes["sentry.origin"] ||= @origin if @origin
67
+ @attributes["sentry.message.template"] ||= template if has_parameters?
177
68
  end
178
69
 
179
70
  def parameters
@@ -185,11 +76,11 @@ module Sentry
185
76
 
186
77
  if parameters.is_a?(Hash)
187
78
  parameters.each do |key, value|
188
- attributes["sentry.message.parameter.#{key}"] = value
79
+ attributes["#{PARAMETER_PREFIX}.#{key}"] = value
189
80
  end
190
81
  else
191
82
  parameters.each_with_index do |param, index|
192
- attributes["sentry.message.parameter.#{index}"] = param
83
+ attributes["#{PARAMETER_PREFIX}.#{index}"] = param
193
84
  end
194
85
  end
195
86
  end
@@ -202,5 +93,9 @@ module Sentry
202
93
  def is_template?
203
94
  body.include?("%s") || TOKEN_REGEXP.match?(body)
204
95
  end
96
+
97
+ def has_parameters?
98
+ attributes.keys.any? { |key| key.start_with?(PARAMETER_PREFIX) }
99
+ end
205
100
  end
206
101
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "sentry/threaded_periodic_worker"
3
+ require "sentry/telemetry_event_buffer"
4
4
 
5
5
  module Sentry
6
6
  # LogEventBuffer buffers log events and sends them to Sentry in a single envelope.
@@ -8,68 +8,21 @@ module Sentry
8
8
  # This is used internally by the `Sentry::Client`.
9
9
  #
10
10
  # @!visibility private
11
- class LogEventBuffer < ThreadedPeriodicWorker
12
- FLUSH_INTERVAL = 5 # seconds
11
+ class LogEventBuffer < TelemetryEventBuffer
13
12
  DEFAULT_MAX_EVENTS = 100
14
-
15
- # @!visibility private
16
- attr_reader :pending_events
13
+ MAX_EVENTS_BEFORE_DROP = 1000
17
14
 
18
15
  def initialize(configuration, client)
19
- super(configuration.sdk_logger, FLUSH_INTERVAL)
20
-
21
- @client = client
22
- @pending_events = []
23
- @max_events = configuration.max_log_events || DEFAULT_MAX_EVENTS
24
- @mutex = Mutex.new
25
-
26
- log_debug("[Logging] Initialized buffer with max_events=#{@max_events}, flush_interval=#{FLUSH_INTERVAL}s")
27
- end
28
-
29
- def start
30
- ensure_thread
31
- self
32
- end
33
-
34
- def flush
35
- @mutex.synchronize do
36
- return if empty?
37
-
38
- log_debug("[LogEventBuffer] flushing #{size} log events")
39
-
40
- send_events
41
- end
42
-
43
- log_debug("[LogEventBuffer] flushed #{size} log events")
44
-
45
- self
46
- end
47
- alias_method :run, :flush
48
-
49
- def add_event(event)
50
- raise ArgumentError, "expected a LogEvent, got #{event.class}" unless event.is_a?(LogEvent)
51
-
52
- @mutex.synchronize do
53
- @pending_events << event
54
- send_events if size >= @max_events
55
- end
56
-
57
- self
58
- end
59
-
60
- def empty?
61
- @pending_events.empty?
62
- end
63
-
64
- def size
65
- @pending_events.size
66
- end
67
-
68
- private
69
-
70
- def send_events
71
- @client.send_logs(@pending_events)
72
- @pending_events.clear
16
+ super(
17
+ configuration,
18
+ client,
19
+ event_class: LogEvent,
20
+ max_items: configuration.max_log_events || DEFAULT_MAX_EVENTS,
21
+ max_items_before_drop: MAX_EVENTS_BEFORE_DROP,
22
+ envelope_type: "log",
23
+ envelope_content_type: "application/vnd.sentry.items.log+json",
24
+ before_send: configuration.before_send_log
25
+ )
73
26
  end
74
27
  end
75
28
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sentry/utils/telemetry_attributes"
4
+
5
+ module Sentry
6
+ class MetricEvent
7
+ include Sentry::Utils::TelemetryAttributes
8
+
9
+ attr_reader :name, :type, :value, :unit, :timestamp, :trace_id, :span_id, :attributes
10
+ attr_writer :trace_id, :span_id, :attributes
11
+
12
+ def initialize(
13
+ name:,
14
+ type:,
15
+ value:,
16
+ unit: nil,
17
+ attributes: nil
18
+ )
19
+ @name = name
20
+ @type = type
21
+ @value = value
22
+ @unit = unit
23
+ @attributes = attributes || {}
24
+
25
+ @timestamp = Sentry.utc_now
26
+ @trace_id = nil
27
+ @span_id = nil
28
+ end
29
+
30
+ def to_h
31
+ {
32
+ name: @name,
33
+ type: @type,
34
+ value: @value,
35
+ unit: @unit,
36
+ timestamp: @timestamp,
37
+ trace_id: @trace_id,
38
+ span_id: @span_id,
39
+ attributes: serialize_attributes
40
+ }.compact
41
+ end
42
+
43
+ private
44
+
45
+ def serialize_attributes
46
+ @attributes.transform_values! { |v| attribute_hash(v) }
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sentry/telemetry_event_buffer"
4
+
5
+ module Sentry
6
+ # MetricEventBuffer buffers metric events and sends them to Sentry in a single envelope.
7
+ #
8
+ # This is used internally by the `Sentry::Client`.
9
+ #
10
+ # @!visibility private
11
+ class MetricEventBuffer < TelemetryEventBuffer
12
+ DEFAULT_MAX_METRICS = 1000
13
+ MAX_METRICS_BEFORE_DROP = 10_000
14
+
15
+ def initialize(configuration, client)
16
+ super(
17
+ configuration,
18
+ client,
19
+ event_class: MetricEvent,
20
+ max_items: configuration.max_metric_events || DEFAULT_MAX_METRICS,
21
+ max_items_before_drop: MAX_METRICS_BEFORE_DROP,
22
+ envelope_type: "trace_metric",
23
+ envelope_content_type: "application/vnd.sentry.items.trace-metric+json",
24
+ before_send: configuration.before_send_metric
25
+ )
26
+ end
27
+ end
28
+ end