in projects/alloydb-autoscaler/src/autoscaler-core/common/open-telemetry-meter-provider.ts [182:272]
async tryFlush() {
if (OpenTelemetryMeterProvider.pendingInit) {
await OpenTelemetryMeterProvider.pendingInit.promise;
}
if (
!OpenTelemetryMeterProvider.isTryFlushEnabled ||
!OpenTelemetryMeterProvider.exporterParams?.FLUSH_ENABLED
) {
// Flushing disabled, do nothing!
return;
}
// Avoid simultaneous flushing.
if (OpenTelemetryMeterProvider.pendingFlush) {
await OpenTelemetryMeterProvider.pendingFlush.promise;
return;
}
OpenTelemetryMeterProvider.pendingFlush = promiseWithResolvers();
if (
!OpenTelemetryMeterProvider.exporterParams ||
!OpenTelemetryMeterProvider.meterProvider
) {
// This should not happen since we are awaiting the init.
// Done to avoid typing issues.
throw new Error('Counters have not been initialized.');
}
try {
await OpenTelemetryMeterProvider.waitUntilNextFlushTime();
// OpenTelemetry's forceFlush() will always succeed, even if the backend
// fails and reports an error...
//
// So we use the OpenTelemetry Global Error Handler installed above
// to keep a count of the number of errors reported, and if an error
// is reported during a flush, we wait a while and try again.
// Not perfect, but the best we can do.
//
// To avoid end-users seeing these errors, we supress error messages
// until the very last flush attempt.
//
// Note that if the OpenTelemetry metrics are exported to Google Cloud
// Monitoring, the first time a counter is used, it will fail to be
// exported and will need to be retried.
let attempts =
OpenTelemetryMeterProvider.exporterParams.FLUSH_MAX_ATTEMPTS;
while (attempts > 0) {
const beforeFlushErrorCount =
OpenTelemetryMeterProvider.openTelemetryErrorCount;
// Suppress OTEL Diag error messages on all but the last flush attempt.
OpenTelemetryMeterProvider.diagPinoLogger.suppressErrors = attempts > 1;
await OpenTelemetryMeterProvider.meterProvider.forceFlush();
OpenTelemetryMeterProvider.diagPinoLogger.suppressErrors = false;
OpenTelemetryMeterProvider.lastForceFlushTime = Date.now();
const afterFlushErrorCount =
OpenTelemetryMeterProvider.openTelemetryErrorCount;
if (beforeFlushErrorCount === afterFlushErrorCount) {
// Success!
return;
}
OpenTelemetryMeterProvider.diagPinoLogger.warn(
'Opentelemetry reported errors during flushing, retrying.'
);
await sleep(
OpenTelemetryMeterProvider.exporterParams.FLUSH_MIN_INTERVAL
);
attempts--;
}
if (attempts <= 0) {
OpenTelemetryMeterProvider.diagPinoLogger.error(
'Failed to flush counters after ' +
OpenTelemetryMeterProvider.exporterParams.FLUSH_MAX_ATTEMPTS +
'attempts - see OpenTelemetry logging'
);
}
} catch (e) {
OpenTelemetryMeterProvider.diagPinoLogger.error(
`Error while flushing counters: ${e}`
);
} finally {
OpenTelemetryMeterProvider.pendingFlush.resolve(null);
OpenTelemetryMeterProvider.pendingFlush = null;
}
}