Skip to content

Add event loop utilization to default metrics#785

Open
bugprone wants to merge 3 commits into
prometheus:mainfrom
bugprone:port-elu-metric
Open

Add event loop utilization to default metrics#785
bugprone wants to merge 3 commits into
prometheus:mainfrom
bugprone:port-elu-metric

Conversation

@bugprone

Copy link
Copy Markdown
Contributor

Replacement for #518 as discussed there, keeping Ivan Tymoshenko credited as commit co-author.

Adds nodejs_eventloop_utilization_summary and nodejs_eventloop_utilization_histogram to the default metrics, sampled on an unref'd interval so a blocked event loop is still accounted for (the interval, buckets, percentiles, and summary window are configurable via collectDefaultMetrics options).

Beyond the rebase of #518 onto current main:

  • aligned the config key name eventLoopUtilizationPercentiles across code, types, and README (the code previously read eventLoopUtilizationSummaryPercentiles while docs and types said otherwise)
  • dropped the perf_hooks availability guard and the Node 10 test skip, both dead code now that Node.js >= 22 is required
  • fixed the stale node/no-unsupported-features eslint disable that no longer resolves under the current lint setup

Full suite passes locally: 544 tests across 29 suites, lint and TypeScript compile clean.

Closes #518

Comment thread lib/metrics/eventLoopUtilization.js Outdated
module.exports = (registry, config = {}) => {
const eventLoopUtilization = performance.eventLoopUtilization;

const namePrefix = config.prefix ? config.prefix : '';

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.

These should be nullish checks, which will avoid problems with things being initialized to falsey values. and avoid profligate use of ternaries.

	const namePrefix = config.prefix ?? '';

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in e36e847 — switched all the config defaults in this file to ?? (the two you flagged plus ageBuckets/maxAgeSeconds/percentiles/buckets, which had the same falsey-override problem). One note: ?? now lets an explicit 0 timeout through, which would make timeMs / intervalTimeout infinite in the sampling loop — happy to clamp it if you'd like.

Comment thread lib/metrics/eventLoopUtilization.js Outdated
});

async function blockEventLoop(ratio, ms) {
const frameMs = 1000;

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 is a long time for a unit test. Can we make it 100ms slices and still get the sort of fidelity we are looking for? I don't really want to see an unit test go above 1 second, and ideally they are a half a millisecond apiece.

If you've ever done code flow using the watch feature you know that slow tests throw your groove off once you have more than a handful.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in e36e847 — 100ms slices, 800ms total. Ran it 10 times in a row to check fidelity: all passed with the ELU delta well inside the 0.05 tolerance, and the test now finishes in ~0.8s.

@jdmarshall

Copy link
Copy Markdown
Contributor

Oh boy. This is already covered by lib/metrics/eventLoopLag.js but using different metric types.

And confusingly, this metric is much older than the associated ticket. Why do we want both? And if some people want both, perhaps the feature to eliminate unwanted defaults should also land with this feature.

@jdmarshall jdmarshall added this to the v1 milestone Jul 24, 2026
@bugprone

Copy link
Copy Markdown
Contributor Author

As I understand it, ELU and lag complement each other. ELU shows how busy the loop is before lag starts to spike. That was also the motivation in #506. But you know this project much better than I do. If you think lag is enough, I'm fine closing this. If you want the exclude option first, I can work on that.

@jdmarshall

Copy link
Copy Markdown
Contributor

I have few opinions at present on the default metrics and am mostly going on feedback from others.

Oh, you’re right. I talked myself into this one and then talked myself back out again. They both do an immediate call and measure the latency but they are reporting separate metrics otherwise.

bugprone and others added 3 commits July 24, 2026 12:21
Ports prometheus#518 onto the current main: adds nodejs_eventloop_utilization_summary
and nodejs_eventloop_utilization_histogram, sampled on an unref'd interval
so a blocked event loop is still accounted for.

Beyond the rebase, aligns the config key name (eventLoopUtilizationPercentiles)
across code, types, and README, and drops the perf_hooks availability guard
that is dead code now that Node.js >= 22 is required.

Co-authored-by: Ivan Tymoshenko <ivan@tymoshenko.me>
Signed-off-by: Jace <bugprone@gmail.com>
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.

2 participants