Skip to content

Commit 4c92546

Browse files
committed
Add new config.profiles_sample_interval
1 parent 3de3190 commit 4c92546

File tree

7 files changed

+70
-6
lines changed

7 files changed

+70
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
config.trace_ignore_status_codes = [404, (501..503)]
4343
end
4444
```
45+
- Add `config.profiles_sample_interval` to control sampling frequency ([#2745](https://github.com/getsentry/sentry-ruby/pull/2745))
46+
- Both `stackprof` and `vernier` now get sampled at a default frequency of 101 Hz.
4547

4648
### Internal
4749

sentry-ruby/lib/sentry/configuration.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,15 @@ class Configuration
319319
# @return [Float, nil]
320320
attr_reader :profiles_sample_rate
321321

322+
# Interval in microseconds at which to take samples.
323+
# The default is 1e6 / 101, or 101Hz.
324+
# Note that the 101 is intentional to avoid lockstep sampling.
325+
#
326+
# @example
327+
# config.profiles_sample_interval = 1e5 / 101
328+
# @return [Float]
329+
attr_accessor :profiles_sample_interval
330+
322331
# Array of patches to apply.
323332
# Default is {DEFAULT_PATCHES}
324333
# @return [Array<Symbol>]
@@ -373,6 +382,9 @@ class Configuration
373382

374383
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/
375384

385+
# 101 Hz in microseconds
386+
DEFAULT_PROFILES_SAMPLE_INTERVAL = 1e6 / 101
387+
376388
class << self
377389
# Post initialization callbacks are called at the end of initialization process
378390
# allowing extending the configuration of sentry-ruby by multiple extensions
@@ -492,6 +504,7 @@ def initialize
492504
self.enable_logs = false
493505

494506
self.profiler_class = Sentry::Profiler
507+
self.profiles_sample_interval = DEFAULT_PROFILES_SAMPLE_INTERVAL
495508

496509
@transport = Transport::Configuration.new
497510
@cron = Cron::Configuration.new

sentry-ruby/lib/sentry/profiler.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ class Profiler
1010

1111
VERSION = "1"
1212
PLATFORM = "ruby"
13-
# 101 Hz in microseconds
14-
DEFAULT_INTERVAL = 1e6 / 101
1513
MICRO_TO_NANO_SECONDS = 1e3
1614
MIN_SAMPLES_REQUIRED = 2
1715

@@ -24,6 +22,7 @@ def initialize(configuration)
2422

2523
@profiling_enabled = defined?(StackProf) && configuration.profiling_enabled?
2624
@profiles_sample_rate = configuration.profiles_sample_rate
25+
@profiles_sample_interval = configuration.profiles_sample_interval
2726
@project_root = configuration.project_root
2827
@app_dirs_pattern = configuration.app_dirs_pattern
2928
@in_app_pattern = Regexp.new("^(#{@project_root}/)?#{@app_dirs_pattern}")
@@ -32,7 +31,7 @@ def initialize(configuration)
3231
def start
3332
return unless @sampled
3433

35-
@started = StackProf.start(interval: DEFAULT_INTERVAL,
34+
@started = StackProf.start(interval: @profiles_sample_interval,
3635
mode: :wall,
3736
raw: true,
3837
aggregate: false)

sentry-ruby/lib/sentry/vernier/profiler.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def initialize(configuration)
2020

2121
@profiling_enabled = defined?(Vernier) && configuration.profiling_enabled?
2222
@profiles_sample_rate = configuration.profiles_sample_rate
23+
@profiles_sample_interval = configuration.profiles_sample_interval
2324
@project_root = configuration.project_root
2425
@app_dirs_pattern = configuration.app_dirs_pattern
2526
@in_app_pattern = Regexp.new("^(#{@project_root}/)?#{@app_dirs_pattern}")
@@ -56,7 +57,7 @@ def start
5657
return unless @sampled
5758
return if @started
5859

59-
@started = ::Vernier.start_profile
60+
@started = ::Vernier.start_profile(interval: @profiles_sample_interval)
6061

6162
log("Started")
6263

sentry-ruby/spec/sentry/configuration_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@
194194
end
195195
end
196196

197+
describe "#profiles_sample_interval" do
198+
it "defaults to 101 Hz" do
199+
expect(subject.profiles_sample_interval).to eq(1e6 / 101)
200+
end
201+
end
202+
197203
describe "#transport" do
198204
it "returns an initialized Transport::Configuration object" do
199205
transport_config = subject.transport

sentry-ruby/spec/sentry/profiler_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,30 @@
7474
expect(subject.started).to eq(false)
7575
end
7676
end
77+
78+
context 'with custom profiles_sample_interval' do
79+
before do
80+
perform_basic_setup do |config|
81+
config.traces_sample_rate = 1.0
82+
config.profiles_sample_rate = 1.0
83+
config.profiles_sample_interval = 1e5 / 101
84+
end
85+
end
86+
87+
it 'starts StackProf with custom interval' do
88+
subject.set_initial_sample_decision(true)
89+
90+
expect(StackProf).to receive(:start).with(
91+
interval: 1e5 / 101,
92+
mode: :wall,
93+
raw: true,
94+
aggregate: false
95+
).and_call_original
96+
97+
subject.start
98+
expect(subject.started).to eq(true)
99+
end
100+
end
77101
end
78102

79103
describe '#stop' do

sentry-ruby/spec/sentry/vernier/profiler_spec.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@
7474
end
7575

7676
it 'starts Vernier if sampled' do
77-
expect(Vernier).to receive(:start_profile).and_return(true)
77+
expect(Vernier).to receive(:start_profile).with(interval: 1e6 / 101).and_return(true)
7878

7979
profiler.start
8080

8181
expect(profiler.started).to eq(true)
8282
end
8383

8484
it 'does not start Vernier again if already started' do
85-
expect(Vernier).to receive(:start_profile).and_return(true).once
85+
expect(Vernier).to receive(:start_profile).with(interval: 1e6 / 101).and_return(true).once
8686

8787
profiler.start
8888
profiler.start
@@ -110,6 +110,25 @@
110110
expect(profiler.started).to eq(false)
111111
end
112112
end
113+
114+
context 'with custom profiles_sample_interval' do
115+
before do
116+
perform_basic_setup do |config|
117+
config.traces_sample_rate = 1.0
118+
config.profiles_sample_rate = 1.0
119+
config.profiles_sample_interval = 1e5 / 101
120+
end
121+
end
122+
123+
it 'starts Vernier with custom interval' do
124+
expect(Vernier).to receive(:start_profile).with(interval: 1e5 / 101).and_return(true)
125+
126+
profiler.set_initial_sample_decision(true)
127+
profiler.start
128+
129+
expect(profiler.started).to eq(true)
130+
end
131+
end
113132
end
114133

115134
describe '#stop' do

0 commit comments

Comments
 (0)