Skip to content

Commit 4490d1d

Browse files
committed
test(instr-runtime-node): add tests for gcDurationBuckets config
Add tests verifying that the GC duration histogram is created correctly with both default and custom bucket boundaries.
1 parent c627f76 commit 4490d1d

File tree

1 file changed

+128
-0
lines changed
  • packages/instrumentation-runtime-node/test

1 file changed

+128
-0
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as assert from 'assert';
18+
import { MeterProvider, DataPointType } from '@opentelemetry/sdk-metrics';
19+
import { RuntimeNodeInstrumentation } from '../src';
20+
import { TestMetricReader } from './testMetricsReader';
21+
import { METRIC_V8JS_GC_DURATION } from '../src/semconv';
22+
23+
const MEASUREMENT_INTERVAL = 10;
24+
25+
// Helper to trigger GC by allocating memory
26+
function triggerGC() {
27+
const arrays = [];
28+
for (let i = 0; i < 100; i++) {
29+
arrays.push(new Array(10000).fill(i));
30+
}
31+
// Allow garbage collection by clearing references
32+
arrays.length = 0;
33+
if (global.gc) {
34+
global.gc();
35+
}
36+
}
37+
38+
describe('v8js.gc.duration', function () {
39+
let metricReader: TestMetricReader;
40+
let meterProvider: MeterProvider;
41+
let instrumentation: RuntimeNodeInstrumentation;
42+
43+
beforeEach(() => {
44+
metricReader = new TestMetricReader();
45+
meterProvider = new MeterProvider({
46+
readers: [metricReader],
47+
});
48+
});
49+
50+
afterEach(() => {
51+
instrumentation.disable();
52+
});
53+
54+
it('should create histogram with default gcDurationBuckets', async function () {
55+
// arrange
56+
instrumentation = new RuntimeNodeInstrumentation({
57+
monitoringPrecision: MEASUREMENT_INTERVAL,
58+
});
59+
instrumentation.setMeterProvider(meterProvider);
60+
61+
// act - trigger GC
62+
triggerGC();
63+
await new Promise(resolve => setTimeout(resolve, MEASUREMENT_INTERVAL * 10));
64+
triggerGC();
65+
await new Promise(resolve => setTimeout(resolve, MEASUREMENT_INTERVAL * 5));
66+
67+
const { resourceMetrics, errors } = await metricReader.collect();
68+
69+
// assert
70+
assert.deepEqual(
71+
errors,
72+
[],
73+
'expected no errors from the callback during collection'
74+
);
75+
const scopeMetrics = resourceMetrics.scopeMetrics;
76+
const metric = scopeMetrics[0]?.metrics.find(
77+
x => x.descriptor.name === METRIC_V8JS_GC_DURATION
78+
);
79+
80+
assert.notEqual(metric, undefined, `${METRIC_V8JS_GC_DURATION} not found`);
81+
assert.strictEqual(
82+
metric!.dataPointType,
83+
DataPointType.HISTOGRAM,
84+
'expected histogram'
85+
);
86+
assert.strictEqual(
87+
metric!.descriptor.unit,
88+
's',
89+
'expected unit to be seconds'
90+
);
91+
});
92+
93+
it('should allow custom gcDurationBuckets configuration', async function () {
94+
// arrange
95+
const customBuckets = [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1];
96+
instrumentation = new RuntimeNodeInstrumentation({
97+
monitoringPrecision: MEASUREMENT_INTERVAL,
98+
gcDurationBuckets: customBuckets,
99+
});
100+
instrumentation.setMeterProvider(meterProvider);
101+
102+
// act - trigger GC
103+
triggerGC();
104+
await new Promise(resolve => setTimeout(resolve, MEASUREMENT_INTERVAL * 10));
105+
triggerGC();
106+
await new Promise(resolve => setTimeout(resolve, MEASUREMENT_INTERVAL * 5));
107+
108+
const { resourceMetrics, errors } = await metricReader.collect();
109+
110+
// assert
111+
assert.deepEqual(
112+
errors,
113+
[],
114+
'expected no errors from the callback during collection'
115+
);
116+
const scopeMetrics = resourceMetrics.scopeMetrics;
117+
const metric = scopeMetrics[0]?.metrics.find(
118+
x => x.descriptor.name === METRIC_V8JS_GC_DURATION
119+
);
120+
121+
assert.notEqual(metric, undefined, `${METRIC_V8JS_GC_DURATION} not found`);
122+
assert.strictEqual(
123+
metric!.dataPointType,
124+
DataPointType.HISTOGRAM,
125+
'expected histogram'
126+
);
127+
});
128+
});

0 commit comments

Comments
 (0)