metrics: literal text "undefined" printed by the metrics endpoint
Bug Description:
For the first ten seconds after the backend starts, the /metrics endpoint renders a section consisting of the literal text undefined, which is not valid Prometheus exposition format.
PluginMetricsContribution declares its accumulator without an initializer and only assigns it from the interval callback installed by startCollecting():
// packages/plugin-metrics/src/node/plugin-metrics.ts
private metrics: string;
getMetrics(): string {
return this.metrics;
}
startCollecting(): void {
setInterval(() => {
const reconciledMetrics = this.metricsContributor.reconcile();
this.metrics = this.stringGenerator.getMetricsString(reconciledMetrics);
}, METRICS_TIMEOUT);
}METRICS_TIMEOUT is 10000 ms, so until the first tick getMetrics() returns undefined rather than a string. MetricsBackendApplicationContribution.fetchMetricsFromProviders() concatenates the contributions with total += contribution.getMetrics() + '\n', which stringifies that undefined into the response. @theia/plugin-metrics registers its contribution after @theia/metrics, so the offending section is the last one.
Two changes would address it:
- initialize the field to
'', so that a contribution that has not collected anything yet reports nothing rather thanundefined, and - skip contributions with an empty result in
fetchMetricsFromProviders(), so that a latentundefinedin any contribution, including third-party ones, cannot corrupt the endpoint, and so that a contribution with nothing to report does not leave a blank separator line behind.
Steps to Reproduce:
- Start the browser example with
npm run start:browser. - Within ten seconds of the backend being ready, request the endpoint:
curl http://localhost:3000/metrics | tail -5. The last line of the output isundefined. - Request it again after ten seconds have elapsed. The
undefinedline is gone, because the interval has run and assigned a string.
Additional Information
The blank line preceding undefined is the separator appended for the section before it. It is easiest to see when that preceding section is empty, for example with "telemetry.filters": { "theia/measurements": [] } configured, which suppresses the theia_measurements samples.
- Operating System: macOS (the code path is platform independent)
- Theia Version: 1.75.0 (
master, 69805e32)
Source: eclipse-theia/theia