Skip to content

Commit 50fa94d

Browse files
committed
perf(webapp): add event loop utilization metric
1 parent 436d951 commit 50fa94d

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

apps/webapp/app/v3/tracer.server.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import { flattenAttributes } from "@trigger.dev/core/v3";
5757
import { prisma } from "~/db.server";
5858
import { metricsRegister } from "~/metrics.server";
5959
import type { Prisma } from "@trigger.dev/database";
60+
import { performance } from "node:perf_hooks";
6061

6162
export const SEMINTATTRS_FORCE_RECORDING = "forceRecording";
6263

@@ -602,10 +603,17 @@ function configureNodejsMetrics({ meter }: { meter: Meter }) {
602603
description: "Event loop 99th percentile delay",
603604
unit: "s",
604605
});
606+
// ELU observable gauge (unit is a ratio, 0..1)
607+
const eluGauge = meter.createObservableGauge("nodejs.event_loop.utilization", {
608+
description: "Event loop utilization over the last collection interval",
609+
unit: "1", // OpenTelemetry convention for ratios
610+
});
605611

606612
// Get UV threadpool size (defaults to 4 if not set)
607613
const uvThreadpoolSize = parseInt(process.env.UV_THREADPOOL_SIZE || "4", 10);
608614

615+
let lastEventLoopUtilization = performance.eventLoopUtilization();
616+
609617
// Single helper to read metrics from prom-client
610618
async function readNodeMetrics() {
611619
const metrics = await metricsRegister.getMetricsAsJSON();
@@ -648,6 +656,16 @@ function configureNodejsMetrics({ meter }: { meter: Meter }) {
648656
}
649657
}
650658

659+
const currentEventLoopUtilization = performance.eventLoopUtilization();
660+
// Diff over [lastSnapshot, current]
661+
const diff = performance.eventLoopUtilization(
662+
currentEventLoopUtilization,
663+
lastEventLoopUtilization
664+
);
665+
666+
// diff.utilization is between 0 and 1 (fraction of time "active")
667+
const utilization = Number.isFinite(diff.utilization) ? diff.utilization : 0;
668+
651669
return {
652670
threadpoolSize: uvThreadpoolSize,
653671
handlesByType,
@@ -661,6 +679,7 @@ function configureNodejsMetrics({ meter }: { meter: Meter }) {
661679
p50: eventLoopLagP50?.values?.[0]?.value ?? 0,
662680
p90: eventLoopLagP90?.values?.[0]?.value ?? 0,
663681
p99: eventLoopLagP99?.values?.[0]?.value ?? 0,
682+
utilization,
664683
},
665684
};
666685
}
@@ -698,6 +717,7 @@ function configureNodejsMetrics({ meter }: { meter: Meter }) {
698717
res.observe(eventLoopLagP50Gauge, eventLoop.p50);
699718
res.observe(eventLoopLagP90Gauge, eventLoop.p90);
700719
res.observe(eventLoopLagP99Gauge, eventLoop.p99);
720+
res.observe(eluGauge, eventLoop.utilization);
701721
},
702722
[
703723
uvThreadpoolSizeGauge,
@@ -711,6 +731,7 @@ function configureNodejsMetrics({ meter }: { meter: Meter }) {
711731
eventLoopLagP50Gauge,
712732
eventLoopLagP90Gauge,
713733
eventLoopLagP99Gauge,
734+
eluGauge,
714735
]
715736
);
716737
}

0 commit comments

Comments
 (0)