Skip to content

Commit e22a9dc

Browse files
committed
fix(sdk-metrics): collect metrics when periodic exporting metric reader flushes
1 parent 1c3af6c commit e22a9dc

File tree

2 files changed

+45
-28
lines changed

2 files changed

+45
-28
lines changed

packages/sdk-metrics/src/export/PeriodicExportingMetricReader.ts

+22-15
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,25 @@ export class PeriodicExportingMetricReader extends MetricReader {
9090
}
9191

9292
private async _runOnce(): Promise<void> {
93-
const { resourceMetrics, errors } = await this.collect({});
93+
try {
94+
await callWithTimeout(this._doRun(), this._exportTimeout);
95+
} catch (err) {
96+
if (err instanceof TimeoutError) {
97+
api.diag.error(
98+
'Export took longer than %s milliseconds and timed out.',
99+
this._exportTimeout
100+
);
101+
return;
102+
}
103+
104+
globalErrorHandler(err);
105+
}
106+
}
107+
108+
private async _doRun(): Promise<void> {
109+
const { resourceMetrics, errors } = await this.collect({
110+
timeoutMillis: this._exportTimeout,
111+
});
94112

95113
if (errors.length > 0) {
96114
api.diag.error(
@@ -109,25 +127,14 @@ export class PeriodicExportingMetricReader extends MetricReader {
109127

110128
protected override onInitialized(): void {
111129
// start running the interval as soon as this reader is initialized and keep handle for shutdown.
112-
this._interval = setInterval(async () => {
113-
try {
114-
await callWithTimeout(this._runOnce(), this._exportTimeout);
115-
} catch (err) {
116-
if (err instanceof TimeoutError) {
117-
api.diag.error(
118-
'Export took longer than %s milliseconds and timed out.',
119-
this._exportTimeout
120-
);
121-
return;
122-
}
123-
124-
globalErrorHandler(err);
125-
}
130+
this._interval = setInterval(() => {
131+
this._runOnce();
126132
}, this._exportInterval);
127133
unrefTimer(this._interval);
128134
}
129135

130136
protected async onForceFlush(): Promise<void> {
137+
await this._runOnce();
131138
await this._exporter.forceFlush();
132139
}
133140

packages/sdk-metrics/test/export/PeriodicExportingMetricReader.test.ts

+23-13
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ const MAX_32_BIT_INT = 2 ** 31 - 1;
3838
class TestMetricExporter implements PushMetricExporter {
3939
public exportTime = 0;
4040
public forceFlushTime = 0;
41-
public throwException = false;
42-
public failureResult = false;
41+
public throwExport = false;
42+
public throwFlush = false;
43+
public rejectExport = false;
4344
private _batches: ResourceMetrics[] = [];
4445
private _shutdown: boolean = false;
4546

@@ -49,11 +50,11 @@ class TestMetricExporter implements PushMetricExporter {
4950
): void {
5051
this._batches.push(metrics);
5152

52-
if (this.throwException) {
53+
if (this.throwExport) {
5354
throw new Error('Error during export');
5455
}
5556
setTimeout(() => {
56-
if (this.failureResult) {
57+
if (this.rejectExport) {
5758
resultCallback({
5859
code: ExportResultCode.FAILED,
5960
error: new Error('some error'),
@@ -72,7 +73,7 @@ class TestMetricExporter implements PushMetricExporter {
7273
}
7374

7475
async forceFlush(): Promise<void> {
75-
if (this.throwException) {
76+
if (this.throwFlush) {
7677
throw new Error('Error during forceFlush');
7778
}
7879

@@ -91,6 +92,10 @@ class TestMetricExporter implements PushMetricExporter {
9192
}
9293
return this._batches.slice(0, numberOfExports);
9394
}
95+
96+
getExports(): ResourceMetrics[] {
97+
return this._batches.slice(0);
98+
}
9499
}
95100

96101
class TestDeltaMetricExporter extends TestMetricExporter {
@@ -203,7 +208,7 @@ describe('PeriodicExportingMetricReader', () => {
203208
describe('periodic export', () => {
204209
it('should keep running on export errors', async () => {
205210
const exporter = new TestMetricExporter();
206-
exporter.throwException = true;
211+
exporter.throwExport = true;
207212
const reader = new PeriodicExportingMetricReader({
208213
exporter: exporter,
209214
exportIntervalMillis: 30,
@@ -218,13 +223,13 @@ describe('PeriodicExportingMetricReader', () => {
218223
emptyResourceMetrics,
219224
]);
220225

221-
exporter.throwException = false;
226+
exporter.throwExport = false;
222227
await reader.shutdown();
223228
});
224229

225230
it('should keep running on export failure', async () => {
226231
const exporter = new TestMetricExporter();
227-
exporter.failureResult = true;
232+
exporter.rejectExport = true;
228233
const reader = new PeriodicExportingMetricReader({
229234
exporter: exporter,
230235
exportIntervalMillis: 30,
@@ -239,7 +244,7 @@ describe('PeriodicExportingMetricReader', () => {
239244
emptyResourceMetrics,
240245
]);
241246

242-
exporter.failureResult = false;
247+
exporter.rejectExport = false;
243248
await reader.shutdown();
244249
});
245250

@@ -261,7 +266,7 @@ describe('PeriodicExportingMetricReader', () => {
261266
emptyResourceMetrics,
262267
]);
263268

264-
exporter.throwException = false;
269+
exporter.throwExport = false;
265270
await reader.shutdown();
266271
});
267272
});
@@ -271,7 +276,7 @@ describe('PeriodicExportingMetricReader', () => {
271276
sinon.restore();
272277
});
273278

274-
it('should forceFlush exporter', async () => {
279+
it('should collect and forceFlush exporter', async () => {
275280
const exporter = new TestMetricExporter();
276281
const exporterMock = sinon.mock(exporter);
277282
exporterMock.expects('forceFlush').calledOnceWithExactly();
@@ -284,6 +289,10 @@ describe('PeriodicExportingMetricReader', () => {
284289
reader.setMetricProducer(new TestMetricProducer());
285290
await reader.forceFlush();
286291
exporterMock.verify();
292+
293+
const exports = exporter.getExports();
294+
assert.strictEqual(exports.length, 1);
295+
287296
await reader.shutdown();
288297
});
289298

@@ -307,12 +316,13 @@ describe('PeriodicExportingMetricReader', () => {
307316

308317
it('should throw when exporter throws', async () => {
309318
const exporter = new TestMetricExporter();
310-
exporter.throwException = true;
319+
exporter.throwFlush = true;
311320
const reader = new PeriodicExportingMetricReader({
312321
exporter: exporter,
313322
exportIntervalMillis: MAX_32_BIT_INT,
314323
exportTimeoutMillis: 80,
315324
});
325+
reader.setMetricProducer(new TestMetricProducer());
316326

317327
await assertRejects(() => reader.forceFlush(), /Error during forceFlush/);
318328
});
@@ -454,7 +464,7 @@ describe('PeriodicExportingMetricReader', () => {
454464

455465
it('should throw on non-initialized instance.', async () => {
456466
const exporter = new TestMetricExporter();
457-
exporter.throwException = true;
467+
exporter.throwFlush = true;
458468
const reader = new PeriodicExportingMetricReader({
459469
exporter: exporter,
460470
exportIntervalMillis: MAX_32_BIT_INT,

0 commit comments

Comments
 (0)