Skip to content

Commit 780f84a

Browse files
authored
feat: Removed ability to specify profiling.sample_interval (#3844)
1 parent 6d8d5b5 commit 780f84a

File tree

10 files changed

+33
-45
lines changed

10 files changed

+33
-45
lines changed

lib/agent.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ function Agent(config) {
309309
config,
310310
delay: config.profiling.delay,
311311
duration: config.profiling.duration,
312-
periodMs: config.profiling.sample_interval,
312+
periodMs: DEFAULT_HARVEST_INTERVAL_MS,
313313
method: 'pprof_data',
314314
isAsync: !config.serverless_mode.enabled,
315315
enabled: (config) => config.profiling.enabled && config.serverless_mode.enabled === false

lib/aggregators/profiling-aggregator.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class ProfilingAggregator extends BaseAggregator {
2828
opts.method = opts.method || 'pprof_data'
2929
super(opts, collector, harvester)
3030
this.agent = agent
31-
this.profilingManager = new ProfilingManager(agent)
31+
this.profilingManager = new ProfilingManager({ agent, samplingInterval: opts.periodMs })
3232
this.pprofData = null
3333
}
3434

@@ -77,7 +77,7 @@ class ProfilingAggregator extends BaseAggregator {
7777
try {
7878
profilingData = await this.profilingManager.collect()
7979
} catch (err) {
80-
logger.error(err, 'Failed to collect profiilng data')
80+
logger.error(err, 'Failed to collect profiling data')
8181
}
8282

8383
for (const pprofData of profilingData) {

lib/config/default.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,13 +1261,6 @@ defaultConfig.definition = () => {
12611261
formatter: boolean,
12621262
default: false
12631263
},
1264-
/**
1265-
* Harvest and ingest profile data every n milliseconds
1266-
*/
1267-
sample_interval: {
1268-
formatter: int,
1269-
default: 100
1270-
},
12711264
/**
12721265
* List of profile type names to enable. Only cpu and heap profiles are currently supported
12731266
*/

lib/profiling/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ const defaultLogger = require('#agentlib/logger.js').child({ component: 'profili
88
const { createProfilingDurationMetric } = require('./metrics')
99

1010
class ProfilingManager {
11-
constructor(agent, { logger = defaultLogger } = {}) {
11+
constructor({ agent, samplingInterval }, { logger = defaultLogger } = {}) {
1212
this.logger = logger
1313
this.metrics = agent.metrics
1414
this.config = agent.config.profiling
15+
this.samplingInterval = samplingInterval
1516
this.profilers = new Map()
1617
this.startTime = null
1718
}
@@ -24,7 +25,7 @@ class ProfilingManager {
2425

2526
if (this.config.include.includes('cpu') && !this.profilers.has('CpuProfiler')) {
2627
const { CpuProfiler } = require('./profilers')
27-
this.profilers.set('CpuProfiler', new CpuProfiler({ logger: this.logger }))
28+
this.profilers.set('CpuProfiler', new CpuProfiler({ logger: this.logger, samplingInterval: this.samplingInterval }))
2829
}
2930
}
3031

lib/profiling/profilers/cpu.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ const BaseProfiler = require('./base')
88

99
class CpuProfiler extends BaseProfiler {
1010
#pprof
11-
constructor({ logger }) {
11+
#durationMillis
12+
#intervalMicros = (1e3 / 99) * 1000 // samples at 99hz(99 times per second)
13+
constructor({ logger, samplingInterval }) {
1214
super({ logger })
1315
this.#pprof = require('@datadog/pprof')
16+
this.#durationMillis = samplingInterval
1417
}
1518

1619
start() {
@@ -19,9 +22,10 @@ class CpuProfiler extends BaseProfiler {
1922
return
2023
}
2124

25+
this.logger.trace(`Starting CpuProfiler, sample every ${this.#intervalMicros}hz for ${this.#durationMillis} ms.`)
2226
this.#pprof.time.start({
23-
durationMillis: 60 * 1e3, // 1 min
24-
intervalMicros: (1e3 / 99) * 1000
27+
durationMillis: this.#durationMillis,
28+
intervalMicros: this.#intervalMicros
2529
})
2630
}
2731

lib/profiling/profilers/heap.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const BaseProfiler = require('../profilers/base')
99

1010
class HeapProfiler extends BaseProfiler {
1111
#pprof
12-
#intervalBytes = 524288
12+
#intervalBytes = 524288 // captures stack trace every 512 kb of allocated memory
1313
#stackDepth = 64
1414
constructor({ logger }) {
1515
super({ logger })
@@ -18,6 +18,7 @@ class HeapProfiler extends BaseProfiler {
1818

1919
start() {
2020
try {
21+
this.logger.trace(`Starting HeapProfiler, sample every ${this.#intervalBytes} bytes with a stack depth of ${this.#stackDepth}`)
2122
this.#pprof.heap.start(this.#intervalBytes, this.#stackDepth)
2223
} catch (error) {
2324
this.logger.error({ error }, 'Failed to start HeapProfiler')

test/unit/agent/agent.test.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,6 @@ test('should set up delay + duration for profilingAggregator', async (t) => {
959959
profiling: {
960960
enabled: true,
961961
duration: 300,
962-
sample_interval: 50,
963962
delay: 50
964963
},
965964
...collector.agentConfig,
@@ -972,6 +971,10 @@ test('should set up delay + duration for profilingAggregator', async (t) => {
972971
}
973972
}
974973
const agent = helper.loadMockedAgent(config, false)
974+
// change period of profiling aggregator as faking timers is a pain for this
975+
// and the default is 1 min
976+
const profilingAggregator = agent.harvester.aggregators.find((aggregator) => aggregator.constructor.name === 'ProfilingAggregator')
977+
profilingAggregator.periodMs = 50
975978

976979
t.after(() => {
977980
helper.unloadAgent(agent)

test/unit/config/config-defaults.test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,6 @@ test('with default properties', async (t) => {
350350
assert.equal(configuration.profiling.enabled, false)
351351
assert.equal(configuration.profiling.delay, 0)
352352
assert.equal(configuration.profiling.duration, 0)
353-
assert.equal(configuration.profiling.sample_interval, 100)
354353
assert.deepEqual(configuration.profiling.include, ['cpu', 'heap'])
355354
})
356355

test/unit/config/config-env.test.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,15 +485,13 @@ test('when overriding configuration values via environment variables', async (t)
485485
NEW_RELIC_PROFILING_INCLUDE: ['heap'],
486486
NEW_RELIC_PROFILING_DELAY: 100,
487487
NEW_RELIC_PROFILING_DURATION: 20000,
488-
NEW_RELIC_PROFILING_SAMPLE_INTERVAL: 150
489488
}
490489

491490
idempotentEnv(env, (tc) => {
492491
assert(tc.profiling.enabled, true)
493492
assert.deepStrictEqual(tc.profiling.include, ['heap'])
494493
assert.equal(tc.profiling.delay, 100)
495494
assert.equal(tc.profiling.duration, 20000)
496-
assert.equal(tc.profiling.sample_interval, 150)
497495
end()
498496
})
499497
})

test/unit/lib/profiling/index.test.js

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ test.beforeEach((ctx) => {
2525

2626
const cpuProfiler = createProfiler({ sandbox, name: 'cpu' })
2727
const heapProfiler = createProfiler({ sandbox, name: 'heap' })
28+
const profilingManager = new ProfilingManager({ agent, samplingInterval: 60_000 }, { logger })
2829
ctx.nr = {
2930
agent,
3031
cpuProfiler,
3132
heapProfiler,
3233
logger,
34+
profilingManager,
3335
sandbox
3436
}
3537
})
@@ -41,34 +43,29 @@ test.afterEach((ctx) => {
4143

4244
describe('constructor', () => {
4345
test('should initialize with agent config', (t) => {
44-
const { agent } = t.nr
45-
const profilingManager = new ProfilingManager(agent)
46+
const { profilingManager } = t.nr
4647

4748
assert.ok(profilingManager.config, 'should have config')
4849
assert.deepStrictEqual(profilingManager.config, t.nr.agent.config.profiling, 'should store agent config')
4950
})
5051

5152
test('should initialize empty profilers map', (t) => {
52-
const { agent } = t.nr
53-
const profilingManager = new ProfilingManager(agent)
53+
const { profilingManager } = t.nr
5454

5555
assert.strictEqual(profilingManager.profilers.size, 0, 'profilers map should be empty')
5656
})
5757
})
5858

5959
describe('register', () => {
6060
test('should be a no-op by default', (t) => {
61-
const { agent } = t.nr
62-
const profilingManager = new ProfilingManager(agent)
63-
61+
const { profilingManager } = t.nr
6462
profilingManager.register()
6563

6664
assert.strictEqual(profilingManager.profilers.size, 0, 'should not add any profilers')
6765
})
6866

6967
test('should register the heap and cpu profilers only once', (t) => {
70-
const { agent } = t.nr
71-
const profilingManager = new ProfilingManager(agent)
68+
const { profilingManager } = t.nr
7269
profilingManager.config.include = ['heap']
7370

7471
profilingManager.register()
@@ -85,8 +82,7 @@ describe('register', () => {
8582

8683
describe('start', () => {
8784
test('should warn when no profilers are registered', (t) => {
88-
const { agent, logger } = t.nr
89-
const profilingManager = new ProfilingManager(agent, { logger })
85+
const { profilingManager, logger } = t.nr
9086

9187
const started = profilingManager.start()
9288
assert.equal(started, false)
@@ -100,8 +96,7 @@ describe('start', () => {
10096
})
10197

10298
test('should start all registered profilers', (t) => {
103-
const { agent, cpuProfiler, heapProfiler, logger } = t.nr
104-
const profilingManager = new ProfilingManager(agent, { logger })
99+
const { cpuProfiler, heapProfiler, profilingManager, logger } = t.nr
105100
profilingManager.profilers.set('cpu', cpuProfiler)
106101
profilingManager.profilers.set('heap', heapProfiler)
107102
const started = profilingManager.start()
@@ -122,8 +117,7 @@ describe('start', () => {
122117

123118
describe('stop', () => {
124119
test('should warn when no profilers are registered', (t) => {
125-
const { agent, logger } = t.nr
126-
const profilingManager = new ProfilingManager(agent, { logger })
120+
const { logger, profilingManager } = t.nr
127121
profilingManager.stop()
128122

129123
assert.equal(logger.warn.callCount, 1)
@@ -135,8 +129,7 @@ describe('stop', () => {
135129
})
136130

137131
test('should stop all registered profilers', (t) => {
138-
const { agent, cpuProfiler, heapProfiler, logger } = t.nr
139-
const profilingManager = new ProfilingManager(agent, { logger })
132+
const { cpuProfiler, heapProfiler, logger, profilingManager } = t.nr
140133
profilingManager.profilers.set('cpu', cpuProfiler)
141134
profilingManager.profilers.set('heap', heapProfiler)
142135
profilingManager.stop()
@@ -148,8 +141,7 @@ describe('stop', () => {
148141
})
149142

150143
test('should log supportability metric for profiling duration', (t) => {
151-
const { agent, cpuProfiler, heapProfiler, logger, sandbox } = t.nr
152-
const profilingManager = new ProfilingManager(agent, { logger })
144+
const { agent, profilingManager, cpuProfiler, heapProfiler, sandbox } = t.nr
153145
profilingManager.profilers.set('cpu', cpuProfiler)
154146
profilingManager.profilers.set('heap', heapProfiler)
155147

@@ -168,8 +160,7 @@ describe('stop', () => {
168160

169161
describe('collect', (t) => {
170162
test('should warn and return empty array when no profilers are registered', async (t) => {
171-
const { agent, logger } = t.nr
172-
const profilingManager = new ProfilingManager(agent, { logger })
163+
const { profilingManager, logger } = t.nr
173164

174165
const results = await profilingManager.collect()
175166
assert.equal(results.length, 0, 'should return empty array')
@@ -182,8 +173,7 @@ describe('collect', (t) => {
182173
})
183174

184175
test('should collect data from all registered profilers', async (t) => {
185-
const { agent, cpuProfiler, heapProfiler, logger } = t.nr
186-
const profilingManager = new ProfilingManager(agent, { logger })
176+
const { profilingManager, cpuProfiler, heapProfiler, logger } = t.nr
187177

188178
const expectedCpuData = { type: 'cpu', data: Buffer.from('cpu-profile-data') }
189179
const expectedHeapData = { type: 'heap', data: Buffer.from('heap-profile-data') }
@@ -203,8 +193,7 @@ describe('collect', (t) => {
203193
})
204194

205195
test('should handle profilers returning undefined or null', async (t) => {
206-
const { agent, cpuProfiler, heapProfiler, logger } = t.nr
207-
const profilingManager = new ProfilingManager(agent, { logger })
196+
const { profilingManager, cpuProfiler, heapProfiler, logger } = t.nr
208197

209198
const expectedCpuData = undefined
210199
const expectedHeapData = null

0 commit comments

Comments
 (0)