Skip to content

feat: add getClusterMetricsAsJSON to cluster registries (#470) - #849

Open
amasen02 wants to merge 3 commits into
prometheus:mainfrom
amasen02:feat/cluster-metrics-as-json-470
Open

feat: add getClusterMetricsAsJSON to cluster registries (#470)#849
amasen02 wants to merge 3 commits into
prometheus:mainfrom
amasen02:feat/cluster-metrics-as-json-470

Conversation

@amasen02

@amasen02 amasen02 commented Sep 4, 2026

Copy link
Copy Markdown

Summary

  • Adds \getClusterMetricsAsJSON(aggregator?: string)\ to \AggregatorRegistry\ and \ClusterRegistry\ to expose aggregated cluster metrics as parsed JSON objects, mirroring \Registry#getMetricsAsJSON().
  • Refactors #gather()\ and collection coordination into #aggregateMetrics(transform)\ so that both \clusterMetrics()\ and \getClusterMetricsAsJSON()\ share identical collection and worker lifecycle logic without duplicating code.
  • Ensures \shutdown()\ continues to cleanly track and await in-flight aggregated metrics requests through completion before exiting.
  • Updates TypeScript definitions in \index.d.ts\ for both \ClusterRegistry\ and \AggregatorRegistry.
  • Adds comprehensive unit test coverage in \ est/clusterTest.js\ verifying empty cluster state, multi-worker JSON aggregation ordering, and aggregator filtering (\sum/\omit), as well as compile-time type verification in \ est/typescript.ts.
  • Updates \README.md\ documentation with usage example.

Closes #470.

Verification


  • pm run lint\ (clean, 0 warnings/errors)

  • pm run check-prettier\ (all files formatted)

  • pm run compile-typescript\ (clean compilation)

  • pm run test-unit -- --coverage\ (31 suites passed, 603 tests passed, 34 snapshots passed)

Signed-off-by: amasen02 <amasen02@users.noreply.github.com>
@amasen02
amasen02 force-pushed the feat/cluster-metrics-as-json-470 branch from 68c7829 to 22f37a4 Compare September 4, 2026 09:52
Comment thread lib/cluster.js Outdated
this.contentType,
).metrics();
);
return transform(registry);

@jdmarshall jdmarshall Sep 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the reasons I ended up contributing to Prometheus over OpenTelemetry is that it doesn't use inordinate levels of indirection for everything that make the code 1) slow as hell and 2) very very difficult to follow.

This indirection is unnecessary for a private function call. And a Rule of 3 violation. Just return the populated Registry and call the appropriate function.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback @jdmarshall! Completely agree — updated in commit 4d4424b to remove the ransform parameter and indirection entirely. #gather now simply aggregates and returns the populated Registry directly.

…rometheus#470)

* Remove transform parameter and indirection from #gather, returning
  populated Registry directly.
* Address review feedback from @jdmarshall on prometheus#849.

Signed-off-by: amasen02 <amasen02@users.noreply.github.com>
@amasen02

amasen02 commented Sep 9, 2026

Copy link
Copy Markdown
Author

Gentle ping on getClusterMetricsAsJSON (603 tests passing). Glad to align with any registry API direction the maintainers prefer.

Comment thread lib/cluster.js Outdated
* metrics.
*/
async clusterMetrics() {
return this.#collect(registry => registry.metrics());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You moved the Rule of Three violation one call up the tree, which is actually worse here because of the need for the thenable, which helps me understand how you were intending this before but it's still effectively the same problem.

  const registry = await this.#collect();
  return registry.metrics();

@amasen02

amasen02 commented Sep 9, 2026

Copy link
Copy Markdown
Author

You're right — the thenable hop was the same indirection one level up. Reworked in 1e6aec7: #collect() now takes no callback and resolves the aggregated Registry; clusterMetrics() and getClusterMetricsAsJSON() await it and call .metrics() / .getMetricsAsJSON() directly, exactly your suggested shape.

One note: removing the extra .then(fn) hop shifts promise resolution by one microtask, which broke the ordering assumption in the two upstream "waits for pending requests" tests (results asserted as strict [1, 2]). I made that test assert the actual guarantee deterministically instead: after draining the microtask queue via setImmediate, the orderly-stop wait must still be pending while the worker response is outstanding, and both settle once it arrives.

Verification: npx jest --testPathPatterns=cluster → 31/31 passed; npm run lint clean; npm run check-prettier clean.

Comment thread test/clusterTest.js
await Promise.all([promise, shutdown]);

expect(results).toEqual([1, 2]);
expect(results.sort()).toEqual([1, 2]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only proves that both fire and not in what order. If this needs to be changed then it's not ensuring that pending work is being retired prior to shutdown.

So something else needs to be asserted here instead. What we don't want is overlapping aggregate calls. So that's probably the thing to check instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Please consider adding a getClusterMetricsAsJSON funtion

2 participants