sentry-ruby 5.28.1 → 6.3.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +25 -1
  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 +57 -135
  11. data/lib/sentry/configuration.rb +117 -75
  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/envelope/item.rb +3 -3
  16. data/lib/sentry/error_event.rb +3 -3
  17. data/lib/sentry/event.rb +4 -10
  18. data/lib/sentry/hub.rb +26 -4
  19. data/lib/sentry/interface.rb +1 -1
  20. data/lib/sentry/interfaces/exception.rb +2 -2
  21. data/lib/sentry/interfaces/request.rb +2 -0
  22. data/lib/sentry/interfaces/single_exception.rb +4 -4
  23. data/lib/sentry/interfaces/stacktrace.rb +3 -3
  24. data/lib/sentry/interfaces/stacktrace_builder.rb +0 -8
  25. data/lib/sentry/interfaces/threads.rb +2 -2
  26. data/lib/sentry/log_event.rb +24 -142
  27. data/lib/sentry/log_event_buffer.rb +13 -60
  28. data/lib/sentry/metric_event.rb +49 -0
  29. data/lib/sentry/metric_event_buffer.rb +28 -0
  30. data/lib/sentry/metrics.rb +47 -54
  31. data/lib/sentry/profiler.rb +4 -5
  32. data/lib/sentry/rack/capture_exceptions.rb +5 -1
  33. data/lib/sentry/rspec.rb +1 -1
  34. data/lib/sentry/scope.rb +50 -18
  35. data/lib/sentry/sequel.rb +35 -0
  36. data/lib/sentry/span.rb +2 -17
  37. data/lib/sentry/std_lib_logger.rb +4 -0
  38. data/lib/sentry/telemetry_event_buffer.rb +130 -0
  39. data/lib/sentry/test_helper.rb +8 -0
  40. data/lib/sentry/transaction.rb +52 -103
  41. data/lib/sentry/transaction_event.rb +4 -9
  42. data/lib/sentry/transport.rb +2 -5
  43. data/lib/sentry/utils/encoding_helper.rb +6 -0
  44. data/lib/sentry/utils/logging_helper.rb +25 -9
  45. data/lib/sentry/utils/telemetry_attributes.rb +30 -0
  46. data/lib/sentry/vernier/profiler.rb +4 -3
  47. data/lib/sentry/version.rb +1 -1
  48. data/lib/sentry-ruby.rb +53 -30
  49. data/sentry-ruby-core.gemspec +1 -1
  50. data/sentry-ruby.gemspec +2 -1
  51. metadata +27 -16
  52. data/lib/sentry/metrics/aggregator.rb +0 -248
  53. data/lib/sentry/metrics/configuration.rb +0 -57
  54. data/lib/sentry/metrics/counter_metric.rb +0 -25
  55. data/lib/sentry/metrics/distribution_metric.rb +0 -25
  56. data/lib/sentry/metrics/gauge_metric.rb +0 -35
  57. data/lib/sentry/metrics/local_aggregator.rb +0 -53
  58. data/lib/sentry/metrics/metric.rb +0 -19
  59. data/lib/sentry/metrics/set_metric.rb +0 -28
  60. data/lib/sentry/metrics/timing.rb +0 -51
data/lib/sentry-ruby.rb CHANGED
@@ -26,8 +26,8 @@ require "sentry/threaded_periodic_worker"
26
26
  require "sentry/session_flusher"
27
27
  require "sentry/backpressure_monitor"
28
28
  require "sentry/cron/monitor_check_ins"
29
- require "sentry/metrics"
30
29
  require "sentry/vernier/profiler"
30
+ require "sentry/metrics"
31
31
 
32
32
  [
33
33
  "sentry/rake",
@@ -59,7 +59,6 @@ module Sentry
59
59
  logger
60
60
  session_flusher
61
61
  backpressure_monitor
62
- metrics_aggregator
63
62
  exception_locals_tp
64
63
  ].freeze
65
64
 
@@ -93,10 +92,6 @@ module Sentry
93
92
  # @return [BackpressureMonitor, nil]
94
93
  attr_reader :backpressure_monitor
95
94
 
96
- # @!attribute [r] metrics_aggregator
97
- # @return [Metrics::Aggregator, nil]
98
- attr_reader :metrics_aggregator
99
-
100
95
  ##### Patch Registration #####
101
96
 
102
97
  # @!visibility private
@@ -252,7 +247,6 @@ module Sentry
252
247
  @background_worker = Sentry::BackgroundWorker.new(config)
253
248
  @session_flusher = config.session_tracking? ? Sentry::SessionFlusher.new(config, client) : nil
254
249
  @backpressure_monitor = config.enable_backpressure_handling ? Sentry::BackpressureMonitor.new(config, client) : nil
255
- @metrics_aggregator = config.metrics.enabled ? Sentry::Metrics::Aggregator.new(config, client) : nil
256
250
  exception_locals_tp.enable if config.include_local_variables
257
251
  at_exit { close }
258
252
  end
@@ -273,12 +267,6 @@ module Sentry
273
267
  @backpressure_monitor = nil
274
268
  end
275
269
 
276
- if @metrics_aggregator
277
- @metrics_aggregator.flush(force: true)
278
- @metrics_aggregator.kill
279
- @metrics_aggregator = nil
280
- end
281
-
282
270
  if client = get_current_client
283
271
  client.flush
284
272
 
@@ -635,24 +623,27 @@ module Sentry
635
623
  #
636
624
  # @see https://develop.sentry.dev/sdk/telemetry/logs/ Sentry SDK Telemetry Logs Protocol
637
625
  #
638
- # @return [StructuredLogger, nil] The structured logger instance or nil if logs are disabled
626
+ # @return [StructuredLogger] The structured logger instance or nil if logs are disabled
639
627
  def logger
640
- @logger ||=
641
- if configuration.enable_logs
642
- # Initialize the public-facing Structured Logger if logs are enabled
643
- # Use configured structured logger class or default to StructuredLogger
644
- # @see https://develop.sentry.dev/sdk/telemetry/logs/
645
- configuration.structured_logging.logger_class.new(configuration)
646
- else
647
- warn <<~STR
648
- [sentry] `Sentry.logger` will no longer be used as internal SDK logger when `enable_logs` feature is turned on.
649
- Use Sentry.configuration.sdk_logger for SDK-specific logging needs."
650
-
651
- Caller: #{caller.first}
652
- STR
653
-
654
- configuration.sdk_logger
655
- end
628
+ @logger ||= configuration.structured_logging.logger_class.new(configuration)
629
+ end
630
+
631
+ # Returns the metrics API for capturing custom metrics.
632
+ #
633
+ # @example Enable metrics
634
+ # Sentry.init do |config|
635
+ # config.dsn = "YOUR_DSN"
636
+ # config.enable_metrics = true
637
+ # end
638
+ #
639
+ # @example Usage
640
+ # Sentry.metrics.count("button.click", 1, attributes: { button_id: "submit" })
641
+ # Sentry.metrics.distribution("response.time", 120.5, unit: "millisecond")
642
+ # Sentry.metrics.gauge("cpu.usage", 75.2, unit: "percent")
643
+ #
644
+ # @return [Metrics] The metrics API
645
+ def metrics
646
+ Metrics
656
647
  end
657
648
 
658
649
  ##### Helpers #####
@@ -675,6 +666,38 @@ module Sentry
675
666
  META
676
667
  end
677
668
 
669
+ # Registers a callback function that retrieves the current external propagation context.
670
+ # This is used by OpenTelemetry integration to provide trace_id and span_id from OTel context.
671
+ #
672
+ # @param callback [Proc, nil] A callable that returns [trace_id, span_id] or nil
673
+ # @return [void]
674
+ #
675
+ # @example
676
+ # Sentry.register_external_propagation_context do
677
+ # span_context = OpenTelemetry::Trace.current_span.context
678
+ # return nil unless span_context.valid?
679
+ # [span_context.hex_trace_id, span_context.hex_span_id]
680
+ # end
681
+ def register_external_propagation_context(&callback)
682
+ @external_propagation_context_callback = callback
683
+ end
684
+
685
+ # Returns the external propagation context (trace_id, span_id) if a callback is registered.
686
+ #
687
+ # @return [Array<String>, nil] A tuple of [trace_id, span_id] or nil if no context is available
688
+ def get_external_propagation_context
689
+ return nil unless @external_propagation_context_callback
690
+
691
+ @external_propagation_context_callback.call
692
+ rescue => e
693
+ sdk_logger&.debug(LOGGER_PROGNAME) { "Error getting external propagation context: #{e.message}" } if initialized?
694
+ nil
695
+ end
696
+
697
+ def clear_external_propagation_context
698
+ @external_propagation_context_callback = nil
699
+ end
700
+
678
701
  # @!visibility private
679
702
  def utc_now
680
703
  Time.now.utc
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = "https://github.com/getsentry/sentry-ruby"
13
13
 
14
14
  spec.platform = Gem::Platform::RUBY
15
- spec.required_ruby_version = '>= 2.4'
15
+ spec.required_ruby_version = '>= 2.7'
16
16
  spec.extra_rdoc_files = ["README.md", "LICENSE.txt"]
17
17
  spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n")
18
18
 
data/sentry-ruby.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.license = 'MIT'
12
12
 
13
13
  spec.platform = Gem::Platform::RUBY
14
- spec.required_ruby_version = '>= 2.4'
14
+ spec.required_ruby_version = '>= 2.7'
15
15
  spec.extra_rdoc_files = ["README.md", "LICENSE.txt"]
16
16
  spec.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples|\.rubocop\.yml)'`.split("\n")
17
17
 
@@ -30,4 +30,5 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2"
32
32
  spec.add_dependency "bigdecimal"
33
+ spec.add_dependency "logger"
33
34
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.28.1
4
+ version: 6.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
@@ -43,6 +43,20 @@ dependencies:
43
43
  - - ">="
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: logger
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
46
60
  description: A gem that provides a client interface for the Sentry error logger
47
61
  email: accounts@sentry.io
48
62
  executables: []
@@ -67,6 +81,7 @@ files:
67
81
  - lib/sentry/background_worker.rb
68
82
  - lib/sentry/backpressure_monitor.rb
69
83
  - lib/sentry/backtrace.rb
84
+ - lib/sentry/backtrace/line.rb
70
85
  - lib/sentry/baggage.rb
71
86
  - lib/sentry/breadcrumb.rb
72
87
  - lib/sentry/breadcrumb/sentry_logger.rb
@@ -105,16 +120,9 @@ files:
105
120
  - lib/sentry/log_event.rb
106
121
  - lib/sentry/log_event_buffer.rb
107
122
  - lib/sentry/logger.rb
123
+ - lib/sentry/metric_event.rb
124
+ - lib/sentry/metric_event_buffer.rb
108
125
  - lib/sentry/metrics.rb
109
- - lib/sentry/metrics/aggregator.rb
110
- - lib/sentry/metrics/configuration.rb
111
- - lib/sentry/metrics/counter_metric.rb
112
- - lib/sentry/metrics/distribution_metric.rb
113
- - lib/sentry/metrics/gauge_metric.rb
114
- - lib/sentry/metrics/local_aggregator.rb
115
- - lib/sentry/metrics/metric.rb
116
- - lib/sentry/metrics/set_metric.rb
117
- - lib/sentry/metrics/timing.rb
118
126
  - lib/sentry/net/http.rb
119
127
  - lib/sentry/profiler.rb
120
128
  - lib/sentry/profiler/helpers.rb
@@ -127,11 +135,13 @@ files:
127
135
  - lib/sentry/release_detector.rb
128
136
  - lib/sentry/rspec.rb
129
137
  - lib/sentry/scope.rb
138
+ - lib/sentry/sequel.rb
130
139
  - lib/sentry/session.rb
131
140
  - lib/sentry/session_flusher.rb
132
141
  - lib/sentry/span.rb
133
142
  - lib/sentry/std_lib_logger.rb
134
143
  - lib/sentry/structured_logger.rb
144
+ - lib/sentry/telemetry_event_buffer.rb
135
145
  - lib/sentry/test_helper.rb
136
146
  - lib/sentry/threaded_periodic_worker.rb
137
147
  - lib/sentry/transaction.rb
@@ -152,21 +162,22 @@ files:
152
162
  - lib/sentry/utils/real_ip.rb
153
163
  - lib/sentry/utils/request_id.rb
154
164
  - lib/sentry/utils/sample_rand.rb
165
+ - lib/sentry/utils/telemetry_attributes.rb
155
166
  - lib/sentry/utils/uuid.rb
156
167
  - lib/sentry/vernier/output.rb
157
168
  - lib/sentry/vernier/profiler.rb
158
169
  - lib/sentry/version.rb
159
170
  - sentry-ruby-core.gemspec
160
171
  - sentry-ruby.gemspec
161
- homepage: https://github.com/getsentry/sentry-ruby/tree/5.28.1/sentry-ruby
172
+ homepage: https://github.com/getsentry/sentry-ruby/tree/6.3.1/sentry-ruby
162
173
  licenses:
163
174
  - MIT
164
175
  metadata:
165
- homepage_uri: https://github.com/getsentry/sentry-ruby/tree/5.28.1/sentry-ruby
166
- source_code_uri: https://github.com/getsentry/sentry-ruby/tree/5.28.1/sentry-ruby
167
- changelog_uri: https://github.com/getsentry/sentry-ruby/blob/5.28.1/CHANGELOG.md
176
+ homepage_uri: https://github.com/getsentry/sentry-ruby/tree/6.3.1/sentry-ruby
177
+ source_code_uri: https://github.com/getsentry/sentry-ruby/tree/6.3.1/sentry-ruby
178
+ changelog_uri: https://github.com/getsentry/sentry-ruby/blob/6.3.1/CHANGELOG.md
168
179
  bug_tracker_uri: https://github.com/getsentry/sentry-ruby/issues
169
- documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/5.28.1
180
+ documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/6.3.1
170
181
  rdoc_options: []
171
182
  require_paths:
172
183
  - lib
@@ -174,7 +185,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
174
185
  requirements:
175
186
  - - ">="
176
187
  - !ruby/object:Gem::Version
177
- version: '2.4'
188
+ version: '2.7'
178
189
  required_rubygems_version: !ruby/object:Gem::Requirement
179
190
  requirements:
180
191
  - - ">="
@@ -1,248 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sentry
4
- module Metrics
5
- class Aggregator < ThreadedPeriodicWorker
6
- FLUSH_INTERVAL = 5
7
- ROLLUP_IN_SECONDS = 10
8
-
9
- # this is how far removed from user code in the backtrace we are
10
- # when we record code locations
11
- DEFAULT_STACKLEVEL = 4
12
-
13
- KEY_SANITIZATION_REGEX = /[^a-zA-Z0-9_\-.]+/
14
- UNIT_SANITIZATION_REGEX = /[^a-zA-Z0-9_]+/
15
- TAG_KEY_SANITIZATION_REGEX = /[^a-zA-Z0-9_\-.\/]+/
16
-
17
- TAG_VALUE_SANITIZATION_MAP = {
18
- "\n" => "\\n",
19
- "\r" => "\\r",
20
- "\t" => "\\t",
21
- "\\" => "\\\\",
22
- "|" => "\\u{7c}",
23
- "," => "\\u{2c}"
24
- }
25
-
26
- METRIC_TYPES = {
27
- c: CounterMetric,
28
- d: DistributionMetric,
29
- g: GaugeMetric,
30
- s: SetMetric
31
- }
32
-
33
- # exposed only for testing
34
- attr_reader :client, :thread, :buckets, :flush_shift, :code_locations
35
-
36
- def initialize(configuration, client)
37
- super(configuration.sdk_logger, FLUSH_INTERVAL)
38
- @client = client
39
- @before_emit = configuration.metrics.before_emit
40
- @enable_code_locations = configuration.metrics.enable_code_locations
41
- @stacktrace_builder = configuration.stacktrace_builder
42
-
43
- @default_tags = {}
44
- @default_tags["release"] = configuration.release if configuration.release
45
- @default_tags["environment"] = configuration.environment if configuration.environment
46
-
47
- @mutex = Mutex.new
48
-
49
- # a nested hash of timestamp -> bucket keys -> Metric instance
50
- @buckets = {}
51
-
52
- # the flush interval needs to be shifted once per startup to create jittering
53
- @flush_shift = Random.rand * ROLLUP_IN_SECONDS
54
-
55
- # a nested hash of timestamp (start of day) -> meta keys -> frame
56
- @code_locations = {}
57
- end
58
-
59
- def add(type,
60
- key,
61
- value,
62
- unit: "none",
63
- tags: {},
64
- timestamp: nil,
65
- stacklevel: nil)
66
- return unless ensure_thread
67
- return unless METRIC_TYPES.keys.include?(type)
68
-
69
- updated_tags = get_updated_tags(tags)
70
- return if @before_emit && !@before_emit.call(key, updated_tags)
71
-
72
- timestamp ||= Sentry.utc_now
73
-
74
- # this is integer division and thus takes the floor of the division
75
- # and buckets into 10 second intervals
76
- bucket_timestamp = (timestamp.to_i / ROLLUP_IN_SECONDS) * ROLLUP_IN_SECONDS
77
-
78
- serialized_tags = serialize_tags(updated_tags)
79
- bucket_key = [type, key, unit, serialized_tags]
80
-
81
- added = @mutex.synchronize do
82
- record_code_location(type, key, unit, timestamp, stacklevel: stacklevel) if @enable_code_locations
83
- process_bucket(bucket_timestamp, bucket_key, type, value)
84
- end
85
-
86
- # for sets, we pass on if there was a new entry to the local gauge
87
- local_value = type == :s ? added : value
88
- process_span_aggregator(bucket_key, local_value)
89
- end
90
-
91
- def flush(force: false)
92
- flushable_buckets = get_flushable_buckets!(force)
93
- code_locations = get_code_locations!
94
- return if flushable_buckets.empty? && code_locations.empty?
95
-
96
- envelope = Envelope.new
97
-
98
- unless flushable_buckets.empty?
99
- payload = serialize_buckets(flushable_buckets)
100
- envelope.add_item(
101
- { type: "statsd", length: payload.bytesize },
102
- payload
103
- )
104
- end
105
-
106
- unless code_locations.empty?
107
- code_locations.each do |timestamp, locations|
108
- payload = serialize_locations(timestamp, locations)
109
- envelope.add_item(
110
- { type: "metric_meta", content_type: "application/json" },
111
- payload
112
- )
113
- end
114
- end
115
-
116
- @client.capture_envelope(envelope)
117
- end
118
-
119
- alias_method :run, :flush
120
-
121
- private
122
-
123
- # important to sort for key consistency
124
- def serialize_tags(tags)
125
- tags.flat_map do |k, v|
126
- if v.is_a?(Array)
127
- v.map { |x| [k.to_s, x.to_s] }
128
- else
129
- [[k.to_s, v.to_s]]
130
- end
131
- end.sort
132
- end
133
-
134
- def get_flushable_buckets!(force)
135
- @mutex.synchronize do
136
- flushable_buckets = {}
137
-
138
- if force
139
- flushable_buckets = @buckets
140
- @buckets = {}
141
- else
142
- cutoff = Sentry.utc_now.to_i - ROLLUP_IN_SECONDS - @flush_shift
143
- flushable_buckets = @buckets.select { |k, _| k <= cutoff }
144
- @buckets.reject! { |k, _| k <= cutoff }
145
- end
146
-
147
- flushable_buckets
148
- end
149
- end
150
-
151
- def get_code_locations!
152
- @mutex.synchronize do
153
- code_locations = @code_locations
154
- @code_locations = {}
155
- code_locations
156
- end
157
- end
158
-
159
- # serialize buckets to statsd format
160
- def serialize_buckets(buckets)
161
- buckets.map do |timestamp, timestamp_buckets|
162
- timestamp_buckets.map do |metric_key, metric|
163
- type, key, unit, tags = metric_key
164
- values = metric.serialize.join(":")
165
- sanitized_tags = tags.map { |k, v| "#{sanitize_tag_key(k)}:#{sanitize_tag_value(v)}" }.join(",")
166
-
167
- "#{sanitize_key(key)}@#{sanitize_unit(unit)}:#{values}|#{type}|\##{sanitized_tags}|T#{timestamp}"
168
- end
169
- end.flatten.join("\n")
170
- end
171
-
172
- def serialize_locations(timestamp, locations)
173
- mapping = locations.map do |meta_key, location|
174
- type, key, unit = meta_key
175
- mri = "#{type}:#{sanitize_key(key)}@#{sanitize_unit(unit)}"
176
-
177
- # note this needs to be an array but it really doesn't serve a purpose right now
178
- [mri, [location.merge(type: "location")]]
179
- end.to_h
180
-
181
- { timestamp: timestamp, mapping: mapping }
182
- end
183
-
184
- def sanitize_key(key)
185
- key.gsub(KEY_SANITIZATION_REGEX, "_")
186
- end
187
-
188
- def sanitize_unit(unit)
189
- unit.gsub(UNIT_SANITIZATION_REGEX, "")
190
- end
191
-
192
- def sanitize_tag_key(key)
193
- key.gsub(TAG_KEY_SANITIZATION_REGEX, "")
194
- end
195
-
196
- def sanitize_tag_value(value)
197
- value.chars.map { |c| TAG_VALUE_SANITIZATION_MAP[c] || c }.join
198
- end
199
-
200
- def get_transaction_name
201
- scope = Sentry.get_current_scope
202
- return nil unless scope && scope.transaction_name
203
- return nil if scope.transaction_source_low_quality?
204
-
205
- scope.transaction_name
206
- end
207
-
208
- def get_updated_tags(tags)
209
- updated_tags = @default_tags.merge(tags)
210
-
211
- transaction_name = get_transaction_name
212
- updated_tags["transaction"] = transaction_name if transaction_name
213
-
214
- updated_tags
215
- end
216
-
217
- def process_span_aggregator(key, value)
218
- scope = Sentry.get_current_scope
219
- return nil unless scope && scope.span
220
- return nil if scope.transaction_source_low_quality?
221
-
222
- scope.span.metrics_local_aggregator.add(key, value)
223
- end
224
-
225
- def process_bucket(timestamp, key, type, value)
226
- @buckets[timestamp] ||= {}
227
-
228
- if (metric = @buckets[timestamp][key])
229
- old_weight = metric.weight
230
- metric.add(value)
231
- metric.weight - old_weight
232
- else
233
- metric = METRIC_TYPES[type].new(value)
234
- @buckets[timestamp][key] = metric
235
- metric.weight
236
- end
237
- end
238
-
239
- def record_code_location(type, key, unit, timestamp, stacklevel: nil)
240
- meta_key = [type, key, unit]
241
- start_of_day = Time.utc(timestamp.year, timestamp.month, timestamp.day).to_i
242
-
243
- @code_locations[start_of_day] ||= {}
244
- @code_locations[start_of_day][meta_key] ||= @stacktrace_builder.metrics_code_location(caller[stacklevel || DEFAULT_STACKLEVEL])
245
- end
246
- end
247
- end
248
- end
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sentry
4
- module Metrics
5
- class Configuration
6
- include ArgumentCheckingHelper
7
- include LoggingHelper
8
-
9
- # Enable metrics usage.
10
- # Starts a new {Sentry::Metrics::Aggregator} instance to aggregate metrics
11
- # and a thread to aggregate flush every 5 seconds.
12
- # @return [Boolean]
13
- attr_reader :enabled
14
-
15
- # Enable code location reporting.
16
- # Will be sent once per day.
17
- # True by default.
18
- # @return [Boolean]
19
- attr_accessor :enable_code_locations
20
-
21
- # Optional Proc, called before emitting a metric to the aggregator.
22
- # Use it to filter keys (return false/nil) or update tags.
23
- # Make sure to return true at the end.
24
- #
25
- # @example
26
- # config.metrics.before_emit = lambda do |key, tags|
27
- # return nil if key == 'foo'
28
- # tags[:bar] = 42
29
- # tags.delete(:baz)
30
- # true
31
- # end
32
- #
33
- # @return [Proc, nil]
34
- attr_reader :before_emit
35
-
36
- def initialize(sdk_logger)
37
- @sdk_logger = sdk_logger
38
- @enabled = false
39
- @enable_code_locations = true
40
- end
41
-
42
- def enabled=(value)
43
- log_warn <<~MSG
44
- `config.metrics` is now deprecated and will be removed in the next major.
45
- MSG
46
-
47
- @enabled = value
48
- end
49
-
50
- def before_emit=(value)
51
- check_callable!("metrics.before_emit", value)
52
-
53
- @before_emit = value
54
- end
55
- end
56
- end
57
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sentry
4
- module Metrics
5
- class CounterMetric < Metric
6
- attr_reader :value
7
-
8
- def initialize(value)
9
- @value = value.to_f
10
- end
11
-
12
- def add(value)
13
- @value += value.to_f
14
- end
15
-
16
- def serialize
17
- [value]
18
- end
19
-
20
- def weight
21
- 1
22
- end
23
- end
24
- end
25
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sentry
4
- module Metrics
5
- class DistributionMetric < Metric
6
- attr_reader :value
7
-
8
- def initialize(value)
9
- @value = [value.to_f]
10
- end
11
-
12
- def add(value)
13
- @value << value.to_f
14
- end
15
-
16
- def serialize
17
- value
18
- end
19
-
20
- def weight
21
- value.size
22
- end
23
- end
24
- end
25
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sentry
4
- module Metrics
5
- class GaugeMetric < Metric
6
- attr_reader :last, :min, :max, :sum, :count
7
-
8
- def initialize(value)
9
- value = value.to_f
10
- @last = value
11
- @min = value
12
- @max = value
13
- @sum = value
14
- @count = 1
15
- end
16
-
17
- def add(value)
18
- value = value.to_f
19
- @last = value
20
- @min = [@min, value].min
21
- @max = [@max, value].max
22
- @sum += value
23
- @count += 1
24
- end
25
-
26
- def serialize
27
- [last, min, max, sum, count]
28
- end
29
-
30
- def weight
31
- 5
32
- end
33
- end
34
- end
35
- end