Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4a48ef0

Browse files
committedFeb 4, 2025·
Deprecate config.metrics and Sentry::Metrics
1 parent b5a4948 commit 4a48ef0

31 files changed

+73
-1535
lines changed
 

‎CHANGELOG.md

+22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,28 @@
66
- Revert "[rails] support string errors in error reporter (#2464)" ([#2533](https://github.com/getsentry/sentry-ruby/pull/2533))
77
- Removed unnecessary warning about missing `stackprof` when Vernier is configured as the profiler ([#2537](https://github.com/getsentry/sentry-ruby/pull/2537))
88

9+
### Miscellaneous
10+
11+
- Deprecate all Metrics related APIs [#2539](https://github.com/getsentry/sentry-ruby/pull/2539)
12+
13+
Sentry [no longer has the Metrics Beta offering](https://sentry.zendesk.com/hc/en-us/articles/26369339769883-Metrics-Beta-Ended-on-October-7th) so
14+
all the following APIs linked to Metrics have been deprecated and will be removed in the next major.
15+
16+
```ruby
17+
Sentry.init do |config|
18+
# ...
19+
config.metrics.enabled = true
20+
config.metrics.enable_code_locations = true
21+
config.metrics.before_emit = lambda {}
22+
end
23+
24+
Sentry::Metrics.increment('button_click')
25+
Sentry::Metrics.distribution('page_load', 15.0, unit: 'millisecond')
26+
Sentry::Metrics.gauge('page_load', 15.0, unit: 'millisecond')
27+
Sentry::Metrics.set('user_view', 'jane')
28+
Sentry::Metrics.timing('how_long') { sleep(1) }
29+
```
30+
931
## 5.22.3
1032

1133
### Bug Fixes

‎sentry-ruby/lib/sentry-ruby.rb

+3-8
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ def exception_locals_tp
8383
attr_reader :backpressure_monitor
8484

8585
# @!attribute [r] metrics_aggregator
86-
# @return [Metrics::Aggregator, nil]
86+
# @deprecated
87+
# @return [nil]
8788
attr_reader :metrics_aggregator
8889

8990
##### Patch Registration #####
@@ -241,7 +242,7 @@ def init(&block)
241242
@background_worker = Sentry::BackgroundWorker.new(config)
242243
@session_flusher = config.session_tracking? ? Sentry::SessionFlusher.new(config, client) : nil
243244
@backpressure_monitor = config.enable_backpressure_handling ? Sentry::BackpressureMonitor.new(config, client) : nil
244-
@metrics_aggregator = config.metrics.enabled ? Sentry::Metrics::Aggregator.new(config, client) : nil
245+
@metrics_aggregator = nil
245246
exception_locals_tp.enable if config.include_local_variables
246247
at_exit { close }
247248
end
@@ -262,12 +263,6 @@ def close
262263
@backpressure_monitor = nil
263264
end
264265

265-
if @metrics_aggregator
266-
@metrics_aggregator.flush(force: true)
267-
@metrics_aggregator.kill
268-
@metrics_aggregator = nil
269-
end
270-
271266
if client = get_current_client
272267
client.flush
273268

‎sentry-ruby/lib/sentry/configuration.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ def capture_exception_frame_locals=(value)
245245
attr_reader :cron
246246

247247
# Metrics related configuration.
248+
# @deprecated It will be removed in the next major release.
248249
# @return [Metrics::Configuration]
249250
attr_reader :metrics
250251

@@ -450,7 +451,7 @@ def initialize
450451

451452
@transport = Transport::Configuration.new
452453
@cron = Cron::Configuration.new
453-
@metrics = Metrics::Configuration.new
454+
@metrics = Metrics::Configuration.new(self.logger)
454455
@gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
455456

456457
run_post_initialization_callbacks

‎sentry-ruby/lib/sentry/cron/monitor_check_ins.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ def perform(*args, **opts)
1414
:in_progress,
1515
monitor_config: monitor_config)
1616

17-
start = Metrics::Timing.duration_start
17+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
1818

1919
begin
2020
# need to do this on ruby <= 2.6 sadly
2121
ret = method(:perform).super_method.arity == 0 ? super() : super
22-
duration = Metrics::Timing.duration_end(start)
22+
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
2323

2424
Sentry.capture_check_in(slug,
2525
:ok,
@@ -29,7 +29,7 @@ def perform(*args, **opts)
2929

3030
ret
3131
rescue Exception
32-
duration = Metrics::Timing.duration_end(start)
32+
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
3333

3434
Sentry.capture_check_in(slug,
3535
:error,

‎sentry-ruby/lib/sentry/interfaces/stacktrace_builder.rb

-8
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,6 @@ def build(backtrace:, &frame_callback)
7575
StacktraceInterface.new(frames: frames)
7676
end
7777

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-
8678
private
8779

8880
def convert_parsed_line_into_frame(line)

‎sentry-ruby/lib/sentry/metrics.rb

+4-45
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,14 @@
11
# frozen_string_literal: true
22

3-
require "sentry/metrics/metric"
4-
require "sentry/metrics/counter_metric"
5-
require "sentry/metrics/distribution_metric"
6-
require "sentry/metrics/gauge_metric"
7-
require "sentry/metrics/set_metric"
8-
require "sentry/metrics/timing"
9-
require "sentry/metrics/aggregator"
10-
113
module Sentry
124
module Metrics
13-
DURATION_UNITS = %w[nanosecond microsecond millisecond second minute hour day week]
14-
INFORMATION_UNITS = %w[bit byte kilobyte kibibyte megabyte mebibyte gigabyte gibibyte terabyte tebibyte petabyte pebibyte exabyte exbibyte]
15-
FRACTIONAL_UNITS = %w[ratio percent]
16-
17-
OP_NAME = "metric.timing"
18-
SPAN_ORIGIN = "auto.metric.timing"
19-
205
class << self
21-
def increment(key, value = 1.0, unit: "none", tags: {}, timestamp: nil)
22-
Sentry.metrics_aggregator&.add(:c, key, value, unit: unit, tags: tags, timestamp: timestamp)
23-
end
24-
25-
def distribution(key, value, unit: "none", tags: {}, timestamp: nil)
26-
Sentry.metrics_aggregator&.add(:d, key, value, unit: unit, tags: tags, timestamp: timestamp)
27-
end
28-
29-
def set(key, value, unit: "none", tags: {}, timestamp: nil)
30-
Sentry.metrics_aggregator&.add(:s, key, value, unit: unit, tags: tags, timestamp: timestamp)
31-
end
32-
33-
def gauge(key, value, unit: "none", tags: {}, timestamp: nil)
34-
Sentry.metrics_aggregator&.add(:g, key, value, unit: unit, tags: tags, timestamp: timestamp)
35-
end
36-
37-
def timing(key, unit: "second", tags: {}, timestamp: nil, &block)
38-
return unless block_given?
39-
return yield unless DURATION_UNITS.include?(unit)
6+
def method_missing(m, *args, &block)
7+
return unless Sentry.initialized?
408

41-
result, value = Sentry.with_child_span(op: OP_NAME, description: key, origin: SPAN_ORIGIN) do |span|
42-
tags.each { |k, v| span.set_tag(k, v.is_a?(Array) ? v.join(", ") : v.to_s) } if span
43-
44-
start = Timing.send(unit.to_sym)
45-
result = yield
46-
value = Timing.send(unit.to_sym) - start
47-
48-
[result, value]
9+
Sentry.logger.warn(LOGGER_PROGNAME) do
10+
"`Sentry::Metrics` is now deprecated and will be removed in the next major."
4911
end
50-
51-
Sentry.metrics_aggregator&.add(:d, key, value, unit: unit, tags: tags, timestamp: timestamp)
52-
result
5312
end
5413
end
5514
end

‎sentry-ruby/lib/sentry/metrics/aggregator.rb

-248
This file was deleted.

‎sentry-ruby/lib/sentry/metrics/configuration.rb

+7-34
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,16 @@
44
module Metrics
55
class Configuration
66
include ArgumentCheckingHelper
7+
include LoggingHelper
78

8-
# Enable metrics usage.
9-
# Starts a new {Sentry::Metrics::Aggregator} instance to aggregate metrics
10-
# and a thread to aggregate flush every 5 seconds.
11-
# @return [Boolean]
12-
attr_accessor :enabled
13-
14-
# Enable code location reporting.
15-
# Will be sent once per day.
16-
# True by default.
17-
# @return [Boolean]
18-
attr_accessor :enable_code_locations
19-
20-
# Optional Proc, called before emitting a metric to the aggregator.
21-
# Use it to filter keys (return false/nil) or update tags.
22-
# Make sure to return true at the end.
23-
#
24-
# @example
25-
# config.metrics.before_emit = lambda do |key, tags|
26-
# return nil if key == 'foo'
27-
# tags[:bar] = 42
28-
# tags.delete(:baz)
29-
# true
30-
# end
31-
#
32-
# @return [Proc, nil]
33-
attr_reader :before_emit
34-
35-
def initialize
36-
@enabled = false
37-
@enable_code_locations = true
9+
def initialize(logger)
10+
@logger = logger
3811
end
3912

40-
def before_emit=(value)
41-
check_callable!("metrics.before_emit", value)
42-
43-
@before_emit = value
13+
def method_missing(m, *args, &block)
14+
log_warn <<~MSG
15+
`config.metrics` is now deprecated and will be removed in the next major.
16+
MSG
4417
end
4518
end
4619
end

‎sentry-ruby/lib/sentry/metrics/counter_metric.rb

-25
This file was deleted.

‎sentry-ruby/lib/sentry/metrics/distribution_metric.rb

-25
This file was deleted.

‎sentry-ruby/lib/sentry/metrics/gauge_metric.rb

-35
This file was deleted.

‎sentry-ruby/lib/sentry/metrics/local_aggregator.rb

-53
This file was deleted.

‎sentry-ruby/lib/sentry/metrics/metric.rb

-19
This file was deleted.

‎sentry-ruby/lib/sentry/metrics/set_metric.rb

-28
This file was deleted.

‎sentry-ruby/lib/sentry/metrics/timing.rb

-51
This file was deleted.

‎sentry-ruby/lib/sentry/span.rb

-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# frozen_string_literal: true
22

33
require "securerandom"
4-
require "sentry/metrics/local_aggregator"
54

65
module Sentry
76
class Span
@@ -187,9 +186,6 @@ def to_hash
187186
origin: @origin
188187
}
189188

190-
summary = metrics_summary
191-
hash[:_metrics_summary] = summary if summary
192-
193189
hash
194190
end
195191

@@ -306,14 +302,5 @@ def set_tag(key, value)
306302
def set_origin(origin)
307303
@origin = origin
308304
end
309-
310-
# Collects gauge metrics on the span for metric summaries.
311-
def metrics_local_aggregator
312-
@metrics_local_aggregator ||= Sentry::Metrics::LocalAggregator.new
313-
end
314-
315-
def metrics_summary
316-
@metrics_local_aggregator&.to_hash
317-
end
318305
end
319306
end

‎sentry-ruby/lib/sentry/transaction_event.rb

+2-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ class TransactionEvent < Event
1717
# @return [Hash, nil]
1818
attr_accessor :profile
1919

20-
# @return [Hash, nil]
20+
# @return [nil]
21+
# @deprecated
2122
attr_accessor :metrics_summary
2223

2324
def initialize(transaction:, **options)
@@ -32,7 +33,6 @@ def initialize(transaction:, **options)
3233
self.tags = transaction.tags
3334
self.dynamic_sampling_context = transaction.get_baggage.dynamic_sampling_context
3435
self.measurements = transaction.measurements
35-
self.metrics_summary = transaction.metrics_summary
3636

3737
finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
3838
self.spans = finished_spans.map(&:to_hash)
@@ -53,7 +53,6 @@ def to_hash
5353
data[:spans] = @spans.map(&:to_hash) if @spans
5454
data[:start_timestamp] = @start_timestamp
5555
data[:measurements] = @measurements
56-
data[:_metrics_summary] = @metrics_summary if @metrics_summary
5756
data
5857
end
5958

‎sentry-ruby/spec/sentry/client_spec.rb

-10
Original file line numberDiff line numberDiff line change
@@ -276,16 +276,6 @@ def sentry_context
276276
event = subject.event_from_transaction(transaction)
277277
expect(event.contexts).to include({ foo: { bar: 42 } })
278278
end
279-
280-
it 'adds metric summary on transaction if any' do
281-
key = [:c, 'incr', 'none', []]
282-
transaction.metrics_local_aggregator.add(key, 10)
283-
hash = subject.event_from_transaction(transaction).to_hash
284-
285-
expect(hash[:_metrics_summary]).to eq({
286-
'c:incr@none' => { count: 1, max: 10.0, min: 10.0, sum: 10.0, tags: {} }
287-
})
288-
end
289279
end
290280

291281
describe "#event_from_exception" do

‎sentry-ruby/spec/sentry/interfaces/stacktrace_builder_spec.rb

-13
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,4 @@
9999
end
100100
end
101101
end
102-
103-
describe '#metrics_code_location' do
104-
it 'builds metrics code location hash for line' do
105-
hash = subject.metrics_code_location(backtrace.first)
106-
107-
expect(hash[:filename]).to match(/stacktrace_test_fixture.rb/)
108-
expect(hash[:function]).to eq("bar")
109-
expect(hash[:lineno]).to eq(8)
110-
expect(hash[:pre_context]).to eq(["end\n", "\n", "def bar\n"])
111-
expect(hash[:context_line]).to eq(" baz\n")
112-
expect(hash[:post_context]).to eq(["end\n", nil, nil])
113-
end
114-
end
115102
end

‎sentry-ruby/spec/sentry/metrics/aggregator_spec.rb

-487
This file was deleted.

‎sentry-ruby/spec/sentry/metrics/configuration_spec.rb

+12-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33
require 'spec_helper'
44

55
RSpec.describe Sentry::Metrics::Configuration do
6-
describe '#before_emit=' do
7-
it 'raises error when setting before_emit to anything other than callable or nil' do
8-
subject.before_emit = -> { }
9-
subject.before_emit = nil
10-
expect { subject.before_emit = true }.to raise_error(ArgumentError, 'metrics.before_emit must be callable (or nil to disable)')
6+
let(:stringio) { StringIO.new }
7+
subject { described_class.new(::Logger.new(stringio)) }
8+
9+
%i[enabled enable_code_locations before_emit].each do |method|
10+
describe "#{method}=" do
11+
it 'logs deprecation warning' do
12+
subject.send("#{method}=", true)
13+
14+
expect(stringio.string).to include(
15+
"WARN -- sentry: `config.metrics` is now deprecated and will be removed in the next major."
16+
)
17+
end
1118
end
1219
end
1320
end

‎sentry-ruby/spec/sentry/metrics/counter_metric_spec.rb

-27
This file was deleted.

‎sentry-ruby/spec/sentry/metrics/distribution_metric_spec.rb

-27
This file was deleted.

‎sentry-ruby/spec/sentry/metrics/gauge_metric_spec.rb

-31
This file was deleted.

‎sentry-ruby/spec/sentry/metrics/local_aggregator_spec.rb

-85
This file was deleted.

‎sentry-ruby/spec/sentry/metrics/metric_spec.rb

-23
This file was deleted.

‎sentry-ruby/spec/sentry/metrics/set_metric_spec.rb

-32
This file was deleted.

‎sentry-ruby/spec/sentry/metrics/timing_spec.rb

-56
This file was deleted.

‎sentry-ruby/spec/sentry/metrics_spec.rb

+18-122
Original file line numberDiff line numberDiff line change
@@ -3,136 +3,32 @@
33
require 'spec_helper'
44

55
RSpec.describe Sentry::Metrics do
6+
let(:stringio) { StringIO.new }
7+
68
before do
79
perform_basic_setup do |config|
8-
config.metrics.enabled = true
10+
config.logger = ::Logger.new(stringio)
911
end
1012
end
1113

1214
let(:aggregator) { Sentry.metrics_aggregator }
1315
let(:fake_time) { Time.new(2024, 1, 1, 1, 1, 3) }
1416

15-
describe '.increment' do
16-
it 'passes default value of 1.0 with only key' do
17-
expect(aggregator).to receive(:add).with(
18-
:c,
19-
'foo',
20-
1.0,
21-
unit: 'none',
22-
tags: {},
23-
timestamp: nil
24-
)
25-
26-
described_class.increment('foo')
27-
end
28-
29-
it 'passes through args to aggregator' do
30-
expect(aggregator).to receive(:add).with(
31-
:c,
32-
'foo',
33-
5.0,
34-
unit: 'second',
35-
tags: { fortytwo: 42 },
36-
timestamp: fake_time
37-
)
38-
39-
described_class.increment('foo', 5.0, unit: 'second', tags: { fortytwo: 42 }, timestamp: fake_time)
40-
end
41-
end
42-
43-
describe '.distribution' do
44-
it 'passes through args to aggregator' do
45-
expect(aggregator).to receive(:add).with(
46-
:d,
47-
'foo',
48-
5.0,
49-
unit: 'second',
50-
tags: { fortytwo: 42 },
51-
timestamp: fake_time
52-
)
53-
54-
described_class.distribution('foo', 5.0, unit: 'second', tags: { fortytwo: 42 }, timestamp: fake_time)
55-
end
56-
end
57-
58-
describe '.set' do
59-
it 'passes through args to aggregator' do
60-
expect(aggregator).to receive(:add).with(
61-
:s,
62-
'foo',
63-
'jane',
64-
unit: 'none',
65-
tags: { fortytwo: 42 },
66-
timestamp: fake_time
67-
)
68-
69-
described_class.set('foo', 'jane', tags: { fortytwo: 42 }, timestamp: fake_time)
70-
end
71-
end
72-
73-
describe '.gauge' do
74-
it 'passes through args to aggregator' do
75-
expect(aggregator).to receive(:add).with(
76-
:g,
77-
'foo',
78-
5.0,
79-
unit: 'second',
80-
tags: { fortytwo: 42 },
81-
timestamp: fake_time
82-
)
83-
84-
described_class.gauge('foo', 5.0, unit: 'second', tags: { fortytwo: 42 }, timestamp: fake_time)
85-
end
86-
end
87-
88-
describe '.timing' do
89-
it 'does nothing without a block' do
90-
expect(aggregator).not_to receive(:add)
91-
described_class.timing('foo')
92-
end
93-
94-
it 'does nothing with a non-duration unit' do
95-
expect(aggregator).not_to receive(:add)
96-
result = described_class.timing('foo', unit: 'ratio') { 42 }
97-
expect(result).to eq(42)
98-
end
99-
100-
it 'measures time taken as distribution and passes through args to aggregator' do
101-
expect(aggregator).to receive(:add).with(
102-
:d,
103-
'foo',
104-
an_instance_of(Integer),
105-
unit: 'millisecond',
106-
tags: { fortytwo: 42 },
107-
timestamp: fake_time
108-
)
109-
110-
result = described_class.timing('foo', unit: 'millisecond', tags: { fortytwo: 42 }, timestamp: fake_time) { sleep(0.1); 42 }
111-
expect(result).to eq(42)
112-
end
113-
114-
context 'with running transaction' do
115-
let(:transaction) { transaction = Sentry.start_transaction(name: 'metrics') }
116-
117-
before do
118-
perform_basic_setup do |config|
119-
config.enable_tracing = true
120-
config.metrics.enabled = true
121-
end
122-
123-
Sentry.get_current_scope.set_span(transaction)
124-
end
125-
126-
it 'starts a span' do
127-
expect(Sentry).to receive(:with_child_span).with(op: Sentry::Metrics::OP_NAME, description: 'foo', origin: Sentry::Metrics::SPAN_ORIGIN).and_call_original
128-
129-
described_class.timing('foo') { sleep(0.1) }
130-
end
131-
132-
it 'has the correct tags on the new span' do
133-
described_class.timing('foo', tags: { a: 42, b: [1, 2] }) { sleep(0.1) }
134-
span = transaction.span_recorder.spans.last
135-
expect(span.tags).to eq(a: '42', b: '1, 2')
17+
%i[increment distribution set gauge timing distribution].each do |method|
18+
describe ".#{method}" do
19+
it 'logs deprecation warning' do
20+
described_class.send(
21+
method,
22+
'foo',
23+
5.0,
24+
unit: 'second',
25+
tags: { fortytwo: 42 },
26+
timestamp: fake_time
27+
)
28+
29+
expect(stringio.string).to include(
30+
"WARN -- sentry: `Sentry::Metrics` is now deprecated and will be removed in the next major."
31+
)
13632
end
13733
end
13834
end

‎sentry-ruby/spec/sentry/span_spec.rb

-10
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,6 @@
7777
expect(hash[:span_id].length).to eq(16)
7878
expect(hash[:origin]).to eq('manual')
7979
end
80-
81-
it 'has metric summary if present' do
82-
key = [:c, 'incr', 'none', []]
83-
subject.metrics_local_aggregator.add(key, 10)
84-
85-
hash = subject.to_hash
86-
expect(hash[:_metrics_summary]).to eq({
87-
'c:incr@none' => { count: 1, max: 10.0, min: 10.0, sum: 10.0, tags: {} }
88-
})
89-
end
9080
end
9181

9282
describe "#to_sentry_trace" do

‎sentry-ruby/spec/sentry_spec.rb

-8
Original file line numberDiff line numberDiff line change
@@ -1139,14 +1139,6 @@
11391139
expect(described_class.backpressure_monitor).to eq(nil)
11401140
end
11411141

1142-
it "flushes and kills metrics aggregator" do
1143-
perform_basic_setup { |c| c.metrics.enabled = true }
1144-
expect(described_class.metrics_aggregator).to receive(:flush).with(force: true)
1145-
expect(described_class.metrics_aggregator).to receive(:kill)
1146-
described_class.close
1147-
expect(described_class.metrics_aggregator).to eq(nil)
1148-
end
1149-
11501142
it "flushes transport" do
11511143
expect(described_class.get_current_client).to receive(:flush)
11521144
described_class.close

0 commit comments

Comments
 (0)
Please sign in to comment.