newrelic_rpm 10.8.0 → 10.9.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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/hooks/check_comments.sh +31 -12
  3. data/.claude/hooks/check_rubocop.sh +3 -1
  4. data/CHANGELOG.md +31 -0
  5. data/lib/new_relic/agent/agent.rb +48 -0
  6. data/lib/new_relic/agent/audit_logger.rb +13 -6
  7. data/lib/new_relic/agent/commands/agent_command_router.rb +10 -0
  8. data/lib/new_relic/agent/configuration/default_source.rb +115 -0
  9. data/lib/new_relic/agent/configuration/high_security_source.rb +1 -0
  10. data/lib/new_relic/agent/continuous_profiling/profile_encoder.rb +350 -0
  11. data/lib/new_relic/agent/continuous_profiling/proto/common.proto +154 -0
  12. data/lib/new_relic/agent/continuous_profiling/proto/common_pb.rb +31 -0
  13. data/lib/new_relic/agent/continuous_profiling/proto/profiles.proto +537 -0
  14. data/lib/new_relic/agent/continuous_profiling/proto/profiles_pb.rb +42 -0
  15. data/lib/new_relic/agent/continuous_profiling/proto/profiles_service.proto +82 -0
  16. data/lib/new_relic/agent/continuous_profiling/proto/profiles_service_pb.rb +30 -0
  17. data/lib/new_relic/agent/continuous_profiling/proto/resource.proto +45 -0
  18. data/lib/new_relic/agent/continuous_profiling/proto/resource_pb.rb +28 -0
  19. data/lib/new_relic/agent/continuous_profiling/session.rb +534 -0
  20. data/lib/new_relic/agent/continuous_profiling/stack_prof_sampler.rb +77 -0
  21. data/lib/new_relic/agent/event_listener.rb +13 -2
  22. data/lib/new_relic/agent/instrumentation/continuous_profiler.rb +23 -0
  23. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +6 -2
  24. data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +5 -1
  25. data/lib/new_relic/agent/new_relic_service.rb +144 -2
  26. data/lib/new_relic/agent/pipe_service.rb +4 -0
  27. data/lib/new_relic/agent/transaction.rb +4 -0
  28. data/lib/new_relic/version.rb +1 -1
  29. data/lib/tasks/continuous_profiling_proto.rake +77 -0
  30. data/newrelic.yml +27 -0
  31. metadata +14 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4d18bdc5c32826f29d700b466f49c1cf0995dfcfd34bcde0d9152d8d1021def
4
- data.tar.gz: 8ff19da678ccce6796918d3b420bcb8d69123e04b615cffefb69d049cc25b522
3
+ metadata.gz: fbb51c8f4559d8bb50f88a7e3fcd47d63de49fbe5ec974e9c4ec48b277e28049
4
+ data.tar.gz: 129662fccdead351c98519c957172412b20a917e79350960875b53a5ff2d4dcd
5
5
  SHA512:
6
- metadata.gz: 8bcb3c02bbc6e4510dcb85926f73aa394083d2a7cc43d6f7cb3989b1fbaef6605c0d4298e7f7596c77e6396f296ae2f01f812dfd73fb030e7e98317da83c0822
7
- data.tar.gz: cb84c5756c4e7398cbad79d1c01e5d8097538787c1d1e193c806226022eefa12d440efe201800fc76ea0363bfe8b633a31fbe6abdb92b213d4d4ff3d2b5e0b72
6
+ metadata.gz: 630af5f3ffd009f852384cae072cb42d6f0b293c5ca4b13d096d442bbc2f51ab52d12af348e72bdbccfee60549a45ad4e449e45c0ee401aabc8efb58342e61ad
7
+ data.tar.gz: 429d5e818a9ec3ece5838b30882fc9ae56dc717916ce423c1bde6e928f4bc672f3eaeb77f26ea608206c203f0db03bec52bc8d9b406822e4646ad0f807a781f3
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env bash
2
2
  # Stop hook: judges every comment line added during this session against this repo's
3
- # CLAUDE.md comment-discipline rule (WHY only, never WHAT, 1-2 lines). Blocks the turn from
4
- # ending if a fresh, context-free `claude -p` review finds anything to fix.
3
+ # CLAUDE.md comment-discipline rule (WHY only, never WHAT, 1-2 lines), defaulting to removal
4
+ # rather than rewording. Blocks the turn from ending if a fresh, context-free `claude -p`
5
+ # review finds anything to fix.
5
6
  set -euo pipefail
6
7
 
7
8
  # Guard against the nested `claude -p` judge call below re-triggering this same hook.
@@ -30,17 +31,34 @@ if [ -z "$ADDED_COMMENTS" ]; then
30
31
  fi
31
32
 
32
33
  PROMPT="Review ONLY the added lines (prefixed with +) in this git diff for Ruby comments.
33
- Rule: a comment is only justified if it states a non-obvious WHY (a hidden constraint, a
34
- subtle invariant, a workaround, surprising behavior) that a reader could not get from the
35
- code itself. Never justified: restating WHAT the code does, referencing PR/issue numbers
36
- or task history, or exceeding 2 lines when a shorter version would do. If a comment doesn't
37
- need to be there, remove it.
38
- Ignore the standard 2-line license header and frozen_string_literal comment, and any yardoc
34
+
35
+ The default verdict is REMOVE. Deletion is the preferred fix; shortening is a distant second
36
+ and is right only for a comment that genuinely must stay but is wordy. Begin from the
37
+ assumption that every added comment should go, and spare one only if deleting it would
38
+ plausibly lead a competent reader of this code to make a mistake.
39
+
40
+ A comment survives only if it states a non-obvious WHY the code cannot state itself: a hidden
41
+ constraint, a cross-file or ordering dependency, a subtle invariant, a workaround for specific
42
+ behavior, or something whose breakage would be silent. \"Useful context\", \"helps the reader
43
+ follow along\", and \"explains the design\" are NOT survival reasons -- those are removals.
44
+
45
+ Report REMOVE (never merely shortening) when the comment:
46
+ - restates WHAT the code does, or narrates the obvious
47
+ - explains or justifies a change, or reads as commit-message, PR, issue, or task-history content
48
+ - repeats what a nearby existing comment, a method name, a constant name, or a test name says
49
+ - explains why code is defensive, redundant, or belt-and-braces
50
+ - labels or introduces the lines beneath it
51
+ - needs more than 2 lines to make its point -- treat the length as evidence it is narrating
52
+ rather than constraining, and remove it instead of compressing it
53
+
54
+ Ignore the standard 2-line license header, the frozen_string_literal comment, and yardoc
39
55
  comments for public documentation.
40
56
 
41
- For each added comment that violates the rule, report file, line (from the diff hunk
42
- header), the comment text, and a one-sentence reason. If every added comment is fine,
43
- say so explicitly.
57
+ For each added comment that should change, report file, line (from the diff hunk header), the
58
+ comment text, and a one-sentence reason that starts with the action: \"remove -- \" plus why it
59
+ fails, or, for the rare must-stay-but-wordy case, \"shorten -- \" plus what constraint makes it
60
+ load-bearing. When torn between the two, say remove. If every added comment is justified,
61
+ return an empty violations array.
44
62
 
45
63
  Respond with ONLY a JSON object, no markdown fences, no other text, matching exactly:
46
64
  {\"violations\": [{\"file\": \"...\", \"line\": ..., \"comment\": \"...\", \"reason\": \"...\"}]}
@@ -67,5 +85,6 @@ fi
67
85
 
68
86
  REASON="$(echo "$RESULT" | jq -r '.violations[] | "- \(.file):\(.line) — \(.comment | tostring) — \(.reason)"' 2>/dev/null || true)"
69
87
 
70
- jq -n --arg reason "Comment-discipline check found issues to fix before finishing:
88
+ jq -n --arg reason "Comment-discipline check found comments to fix before finishing. Prefer
89
+ deleting a flagged comment over rewording it; only shorten one that is genuinely load-bearing:
71
90
  $REASON" '{decision: "block", reason: $reason}'
@@ -18,7 +18,9 @@ if [ "${#EXISTING_FILES[@]}" -eq 0 ]; then
18
18
  fi
19
19
 
20
20
  set +e
21
- RESULT="$(bundle exec rubocop --format simple "${EXISTING_FILES[@]}" 2>&1)"
21
+ # --force-exclusion: rubocop ignores AllCops/Exclude when given explicit paths, which would
22
+ # otherwise lint generated files (e.g. the vendored *_pb.rb protobuf classes) the project excludes.
23
+ RESULT="$(bundle exec rubocop --format simple --force-exclusion "${EXISTING_FILES[@]}" 2>&1)"
22
24
  EXIT_CODE=$?
23
25
  set -e
24
26
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # New Relic Ruby Agent Release Notes
2
2
 
3
+ ## v10.9.0
4
+
5
+ - **Feature: Continuous Profiling (preview)**
6
+
7
+ Continuous Profiling is a new feature which is not yet generally available for use. The agent-side component code is now present in the agent but to actually use it ahead of the General Availability release, you will need to contact your New Relic sales representative to join the preview early.
8
+
9
+ Continuous Profiling repeatedly samples the Ruby call stacks of your running application and reports them to New Relic, so you can see which methods are consuming the most CPU time (or allocating the most objects) in production, without adding code to your app.
10
+
11
+ To turn it on, add the [`stackprof`](https://rubygems.org/gems/stackprof) and [`google-protobuf`](https://rubygems.org/gems/google-protobuf) gems to your application's `Gemfile`, then set `profiling.enabled` to `true`:
12
+
13
+ ```yaml
14
+ profiling.enabled: true
15
+ ```
16
+
17
+ With only `profiling.enabled` set, the agent samples CPU time every 10 milliseconds for the life of the process. These options let you tune that behavior:
18
+
19
+ | Configuration name | Default | Behavior |
20
+ | ------------------ | ------- | -------- |
21
+ | profiling.enabled | `false` | If `true`, the agent collects and reports continuous profiling data. |
22
+ | profiling.include | `cpu` | What to sample: `cpu` for CPU time, or `object` for object allocations. |
23
+ | profiling.sample_period | `0.01` | Seconds between stack samples. Only used when `profiling.include` is `cpu`. Must be between 0.000001 and 0.999999. |
24
+ | profiling.object_allocation_interval | `10000` | Object allocations between stack samples. Only used when `profiling.include` is `object`. Must be between 1000 and 999999. |
25
+ | profiling.delay | `0` | Milliseconds to wait before profiling starts. `0` starts immediately. |
26
+ | profiling.duration | `0` | Milliseconds to profile before stopping automatically. `0` profiles until the process exits. |
27
+
28
+ [PR#3617](https://github.com/newrelic/newrelic-ruby-agent/pull/3617)
29
+
30
+ - **Feature: Add support for Dalli 5.1.1**
31
+
32
+ Dalli 5.1.1 added arguments to some of the methods the agent instruments, which could raise an `ArgumentError` on multi-key operations or cause request options to be silently dropped. Now, the agent accepts and forwards a variable number of positional and keyword arguments for these methods. [PR#3683](https://github.com/newrelic/newrelic-ruby-agent/pull/3683)
33
+
3
34
  ## v10.8.0
4
35
 
5
36
  - **Feature: Report a unique hostname for Google Cloud Run Worker Pools and Jobs**
@@ -28,6 +28,7 @@ require 'new_relic/agent/transaction_event_recorder'
28
28
  require 'new_relic/agent/custom_event_aggregator'
29
29
  require 'new_relic/agent/span_event_aggregator'
30
30
  require 'new_relic/agent/log_event_aggregator'
31
+ require 'new_relic/agent/continuous_profiling/session'
31
32
  require 'new_relic/agent/sampler_collection'
32
33
  require 'new_relic/agent/javascript_instrumentor'
33
34
  require 'new_relic/agent/vm/monotonic_gc_profiler'
@@ -87,6 +88,8 @@ module NewRelic
87
88
  @wait_on_connect_mutex = Mutex.new
88
89
  @after_fork_lock = Mutex.new
89
90
  @wait_on_connect_condition = ConditionVariable.new
91
+ @profiles_forwarder_lock = Mutex.new
92
+ @profiles_forwarder_count = 0
90
93
  end
91
94
 
92
95
  def init_components
@@ -121,6 +124,7 @@ module NewRelic
121
124
  @custom_event_aggregator = CustomEventAggregator.new(@events)
122
125
  @span_event_aggregator = SpanEventAggregator.new(@events)
123
126
  @log_event_aggregator = LogEventAggregator.new(@events)
127
+ @continuous_profiling_session = ContinuousProfiling::Session.new(@events)
124
128
  end
125
129
 
126
130
  def setup_attribute_filter
@@ -149,6 +153,8 @@ module NewRelic
149
153
  # Holds all the methods defined on NewRelic::Agent::Agent
150
154
  # instances
151
155
  module InstanceMethods
156
+ MAX_CONCURRENT_PROFILES_FORWARDERS = 4
157
+
152
158
  # the agent control health check file generator
153
159
  attr_reader :health_check
154
160
  # the statistics engine that holds all the timeslice data
@@ -181,6 +187,7 @@ module NewRelic
181
187
  attr_reader :custom_event_aggregator
182
188
  attr_reader :span_event_aggregator
183
189
  attr_reader :log_event_aggregator
190
+ attr_reader :continuous_profiling_session
184
191
  attr_reader :transaction_event_recorder
185
192
  attr_reader :attribute_filter
186
193
  attr_reader :adaptive_sampler
@@ -231,6 +238,10 @@ module NewRelic
231
238
  reset_objects_with_locks
232
239
  drop_buffered_data
233
240
 
241
+ # Ahead of setup_and_start_agent: a connect on the worker thread it spawns applies
242
+ # server-side config, which can start a session this call would then tear down.
243
+ @continuous_profiling_session.after_fork
244
+
234
245
  setup_and_start_agent(options)
235
246
  end
236
247
 
@@ -319,6 +330,9 @@ module NewRelic
319
330
  # might be holding locks for background thread that aren't there anymore.
320
331
  def reset_objects_with_locks
321
332
  @stats_engine = StatsEngine.new
333
+ @continuous_profiling_session.reset_after_fork_from_parent_thread
334
+ @profiles_forwarder_lock = Mutex.new
335
+ @profiles_forwarder_count = 0
322
336
  end
323
337
 
324
338
  def flush_pipe_data # used only by resque
@@ -348,7 +362,41 @@ module NewRelic
348
362
  end
349
363
  end
350
364
 
365
+ # Forwarded off-thread so a slow export doesn't block other children's data; capped
366
+ # since forwarders serialize on NewRelicService's profiles request lock anyway.
367
+ def forward_profiles_data(data)
368
+ @profiles_forwarder_lock.synchronize do
369
+ if @profiles_forwarder_count >= MAX_CONCURRENT_PROFILES_FORWARDERS
370
+ NewRelic::Agent.increment_metric('Supportability/Ruby/Profiling/Forward/Dropped')
371
+ NewRelic::Agent.logger.debug(
372
+ 'Dropping a forwarded continuous profiling payload: too many exports already in flight'
373
+ )
374
+ return nil
375
+ end
376
+
377
+ @profiles_forwarder_count += 1
378
+ end
379
+
380
+ begin
381
+ Threading::AgentThread.create('Continuous Profiling Forwarder') do
382
+ @service.profiles_data(data)
383
+ ensure
384
+ @profiles_forwarder_lock.synchronize { @profiles_forwarder_count -= 1 }
385
+ end
386
+ rescue => e
387
+ # The block's ensure never runs if the thread was never created, and a count that
388
+ # can't come back down drops every later payload for the life of the process.
389
+ @profiles_forwarder_lock.synchronize { @profiles_forwarder_count -= 1 }
390
+ NewRelic::Agent.logger.error('Failed to start a continuous profiling forwarder thread', e)
391
+ nil
392
+ end
393
+ end
394
+
351
395
  def merge_data_for_endpoint(endpoint, data)
396
+ if endpoint == :profiles_data && data && !data.empty?
397
+ return forward_profiles_data(data)
398
+ end
399
+
352
400
  if data && !data.empty?
353
401
  container = container_for_endpoint(endpoint)
354
402
  if container.respond_to?(:has_metadata?) && container.has_metadata?
@@ -39,16 +39,23 @@ module NewRelic
39
39
  end
40
40
 
41
41
  def log_request(uri, data, marshaller)
42
+ log_request_body(uri) do
43
+ if marshaller.class.human_readable?
44
+ marshaller.dump(data, :encoder => @encoder)
45
+ else
46
+ marshaller.prepare(data, :encoder => @encoder).inspect
47
+ end
48
+ end
49
+ end
50
+
51
+ # Yielded, not passed: rendering a body eagerly would cost a marshal or protobuf decode on
52
+ # every request even when audit logging is off or the endpoint is filtered out.
53
+ def log_request_body(uri)
42
54
  return unless enabled? && allowed_endpoint?(uri)
43
55
 
44
56
  setup_logger unless setup?
45
- request_body = if marshaller.class.human_readable?
46
- marshaller.dump(data, :encoder => @encoder)
47
- else
48
- marshaller.prepare(data, :encoder => @encoder).inspect
49
- end
50
57
  @log.info("REQUEST: #{uri}")
51
- @log.info("REQUEST BODY: #{request_body}")
58
+ @log.info("REQUEST BODY: #{yield}")
52
59
  rescue StandardError, SystemStackError, SystemCallError => e
53
60
  ::NewRelic::Agent.logger.warn('Failed writing to audit log', e)
54
61
  rescue Exception => e
@@ -15,6 +15,9 @@ module NewRelic
15
15
  module Agent
16
16
  module Commands
17
17
  class AgentCommandRouter
18
+ START_CONTINUOUS_PROFILING_COMMAND = 'start_continuous_profiling'
19
+ STOP_CONTINUOUS_PROFILING_COMMAND = 'stop_continuous_profiling'
20
+
18
21
  attr_reader :handlers
19
22
 
20
23
  attr_accessor :thread_profiler_session, :backtrace_service
@@ -28,6 +31,8 @@ module NewRelic
28
31
 
29
32
  @handlers['start_profiler'] = proc { |cmd| thread_profiler_session.handle_start_command(cmd) }
30
33
  @handlers['stop_profiler'] = proc { |cmd| thread_profiler_session.handle_stop_command(cmd) }
34
+ @handlers[START_CONTINUOUS_PROFILING_COMMAND] = proc { |cmd| continuous_profiling_session.handle_start_command(cmd) }
35
+ @handlers[STOP_CONTINUOUS_PROFILING_COMMAND] = proc { |cmd| continuous_profiling_session.handle_stop_command(cmd) }
31
36
 
32
37
  event_listener&.subscribe(:before_shutdown, &method(:on_before_shutdown))
33
38
  end
@@ -36,6 +41,11 @@ module NewRelic
36
41
  NewRelic::Agent.instance.service
37
42
  end
38
43
 
44
+ def continuous_profiling_session
45
+ NewRelic::Agent.agent&.continuous_profiling_session ||
46
+ raise(AgentCommandError, 'Continuous profiling session unavailable; agent not fully started')
47
+ end
48
+
39
49
  def check_for_and_handle_agent_commands
40
50
  commands = get_agent_commands
41
51
 
@@ -216,6 +216,58 @@ module NewRelic
216
216
  constants.compact!
217
217
  constants
218
218
  end
219
+
220
+ OBJECT_ALLOCATION_INTERVAL_MINIMUM = 1000
221
+
222
+ # StackProf's C extension rejects any interval outside 1..999_999 (stackprof_start in
223
+ # stackprof.c), whether it's microseconds or a raw allocation count.
224
+ STACKPROF_INTERVAL_MAXIMUM = 999_999
225
+ SAMPLE_PERIOD_MINIMUM_SECONDS = 1 / 1_000_000.0
226
+ SAMPLE_PERIOD_MAXIMUM_SECONDS = STACKPROF_INTERVAL_MAXIMUM / 1_000_000.0
227
+
228
+ def self.enforce_object_allocation_interval_range(value)
229
+ return value if value.nil?
230
+
231
+ if value < OBJECT_ALLOCATION_INTERVAL_MINIMUM
232
+ NewRelic::Agent.logger.debug(
233
+ "profiling.object_allocation_interval is set to #{value.inspect}, which is below the minimum " \
234
+ "of #{OBJECT_ALLOCATION_INTERVAL_MINIMUM}. Using #{OBJECT_ALLOCATION_INTERVAL_MINIMUM} instead."
235
+ )
236
+ return OBJECT_ALLOCATION_INTERVAL_MINIMUM
237
+ end
238
+
239
+ if value > STACKPROF_INTERVAL_MAXIMUM
240
+ NewRelic::Agent.logger.debug(
241
+ "profiling.object_allocation_interval is set to #{value.inspect}, which is above the maximum " \
242
+ "of #{STACKPROF_INTERVAL_MAXIMUM}. Using #{STACKPROF_INTERVAL_MAXIMUM} instead."
243
+ )
244
+ return STACKPROF_INTERVAL_MAXIMUM
245
+ end
246
+
247
+ value
248
+ end
249
+
250
+ def self.enforce_sample_period_range(value)
251
+ return value if value.nil?
252
+
253
+ if value < SAMPLE_PERIOD_MINIMUM_SECONDS
254
+ NewRelic::Agent.logger.debug(
255
+ "profiling.sample_period is set to #{value.inspect}, which is below the minimum of " \
256
+ "#{SAMPLE_PERIOD_MINIMUM_SECONDS} seconds. Using #{SAMPLE_PERIOD_MINIMUM_SECONDS} instead."
257
+ )
258
+ return SAMPLE_PERIOD_MINIMUM_SECONDS
259
+ end
260
+
261
+ if value > SAMPLE_PERIOD_MAXIMUM_SECONDS
262
+ NewRelic::Agent.logger.debug(
263
+ "profiling.sample_period is set to #{value.inspect}, which is above the maximum of " \
264
+ "#{SAMPLE_PERIOD_MAXIMUM_SECONDS} seconds. Using #{SAMPLE_PERIOD_MAXIMUM_SECONDS} instead."
265
+ )
266
+ return SAMPLE_PERIOD_MAXIMUM_SECONDS
267
+ end
268
+
269
+ value
270
+ end
219
271
  end
220
272
 
221
273
  AUTOSTART_DENYLISTED_RAKE_TASKS = [
@@ -1054,6 +1106,69 @@ module NewRelic
1054
1106
  :description => "If `true`, the agent will report source code level metrics for traced methods.\n\tSee: " \
1055
1107
  'https://docs.newrelic.com/docs/apm/agents/ruby-agent/features/ruby-codestream-integration/'
1056
1108
  },
1109
+ # Continuous profiler
1110
+ :'profiling.enabled' => {
1111
+ :default => false,
1112
+ :public => true,
1113
+ :type => Boolean,
1114
+ :allowed_from_server => true,
1115
+ :description => 'If `true`, enables continuous profiling. Requires the `stackprof` and `google-protobuf` ' \
1116
+ 'gems to be present in the application. Not supported on JRuby. Automatically disabled when high ' \
1117
+ 'security mode is enabled.'
1118
+ },
1119
+ :'profiling.delay' => {
1120
+ :default => 0,
1121
+ :public => true,
1122
+ :type => Integer,
1123
+ :allowed_from_server => true,
1124
+ :description => 'The delay, in milliseconds, before continuous profiling starts after being enabled. ' \
1125
+ 'Defaults to `0`, meaning profiling starts immediately.'
1126
+ },
1127
+ :'profiling.duration' => {
1128
+ :default => 0,
1129
+ :public => true,
1130
+ :type => Integer,
1131
+ :allowed_from_server => true,
1132
+ :description => 'The duration, in milliseconds, that continuous profiling runs before automatically ' \
1133
+ 'stopping. Defaults to `0`, meaning profiling runs indefinitely until explicitly stopped.'
1134
+ },
1135
+ :'profiling.include' => {
1136
+ :default => 'cpu',
1137
+ :public => true,
1138
+ :type => String,
1139
+ :allowed_from_server => true,
1140
+ :allowlist => %w[cpu object],
1141
+ :description => 'The `stackprof` sampling mode to use for continuous profiling: `cpu` or `object`.'
1142
+ },
1143
+ :'profiling.sample_period' => {
1144
+ :default => 0.01,
1145
+ :public => true,
1146
+ :type => Float,
1147
+ :allowed_from_server => true,
1148
+ :transform => DefaultSource.method(:enforce_sample_period_range),
1149
+ :description => 'The interval, in seconds, between stack samples taken by the continuous profiler. ' \
1150
+ 'Only used when `profiling.include` is `cpu`. Must be between ' \
1151
+ "#{format('%.6f', DefaultSource::SAMPLE_PERIOD_MINIMUM_SECONDS)} and " \
1152
+ "#{format('%.6f', DefaultSource::SAMPLE_PERIOD_MAXIMUM_SECONDS)}."
1153
+ },
1154
+ :'profiling.object_allocation_interval' => {
1155
+ :default => 10000,
1156
+ :public => true,
1157
+ :type => Integer,
1158
+ :allowed_from_server => true,
1159
+ :transform => DefaultSource.method(:enforce_object_allocation_interval_range),
1160
+ :description => 'The number of object allocations between stack samples taken by the continuous ' \
1161
+ 'profiler. Only used when `profiling.include` is `object`. Must be between ' \
1162
+ "#{DefaultSource::OBJECT_ALLOCATION_INTERVAL_MINIMUM} and #{DefaultSource::STACKPROF_INTERVAL_MAXIMUM}."
1163
+ },
1164
+ :'profiling.harvest_period' => {
1165
+ :default => 10,
1166
+ :public => false,
1167
+ :type => Integer,
1168
+ :allowed_from_server => true,
1169
+ :description => 'The interval, in seconds, at which the continuous profiler converts and reports its ' \
1170
+ 'collected samples.'
1171
+ },
1057
1172
  # Custom attributes
1058
1173
  :'custom_attributes.enabled' => {
1059
1174
  :default => true,
@@ -20,6 +20,7 @@ module NewRelic
20
20
  :'transaction_tracer.record_redis_arguments' => false,
21
21
 
22
22
  :'ai_monitoring.enabled' => false,
23
+ :'profiling.enabled' => false,
23
24
  :'custom_insights_events.enabled' => false,
24
25
  :'strip_exception_messages.enabled' => true
25
26
  })