Skip to content

Commit 304fec6

Browse files
committed
Add some nodejs metrics
1 parent 6b7b235 commit 304fec6

File tree

4 files changed

+73
-0
lines changed

4 files changed

+73
-0
lines changed

packages/cli-v3/src/entryPoints/dev-run-worker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ async function doBootstrap() {
213213
forceFlushTimeoutMillis: 30_000,
214214
resource: config.telemetry?.resource,
215215
hostMetrics: true,
216+
nodejsRuntimeMetrics: true,
216217
// Drop all system metrics from dev metrics export
217218
droppedMetrics: ["system.*"],
218219
});

packages/cli-v3/src/entryPoints/managed-run-worker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ async function doBootstrap() {
192192
metricReaders: config.telemetry?.metricReaders ?? [],
193193
resource: config.telemetry?.resource,
194194
hostMetrics: true,
195+
nodejsRuntimeMetrics: true,
195196
});
196197

197198
const otelTracer: Tracer = tracingSDK.getTracer("trigger-dev-worker", VERSION);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { type MeterProvider } from "@opentelemetry/sdk-metrics";
2+
import { performance, monitorEventLoopDelay } from "node:perf_hooks";
3+
4+
export function startNodejsRuntimeMetrics(meterProvider: MeterProvider) {
5+
const meter = meterProvider.getMeter("nodejs-runtime", "1.0.0");
6+
7+
// Event loop utilization (diff between collection intervals)
8+
let lastElu = performance.eventLoopUtilization();
9+
10+
const eluGauge = meter.createObservableGauge("nodejs.event_loop.utilization", {
11+
description: "Event loop utilization over the last collection interval",
12+
unit: "1",
13+
});
14+
15+
// Event loop delay histogram (from perf_hooks)
16+
const eld = monitorEventLoopDelay({ resolution: 20 });
17+
eld.enable();
18+
19+
const eldP50 = meter.createObservableGauge("nodejs.event_loop.delay.p50", {
20+
description: "Median event loop delay",
21+
unit: "s",
22+
});
23+
const eldP99 = meter.createObservableGauge("nodejs.event_loop.delay.p99", {
24+
description: "p99 event loop delay",
25+
unit: "s",
26+
});
27+
const eldMax = meter.createObservableGauge("nodejs.event_loop.delay.max", {
28+
description: "Max event loop delay",
29+
unit: "s",
30+
});
31+
32+
// Heap metrics
33+
const heapUsed = meter.createObservableGauge("nodejs.heap.used", {
34+
description: "V8 heap used",
35+
unit: "By",
36+
});
37+
const heapTotal = meter.createObservableGauge("nodejs.heap.total", {
38+
description: "V8 heap total allocated",
39+
unit: "By",
40+
});
41+
42+
// Single batch callback for all metrics
43+
meter.addBatchObservableCallback(
44+
(obs) => {
45+
// ELU
46+
const currentElu = performance.eventLoopUtilization();
47+
const diff = performance.eventLoopUtilization(currentElu, lastElu);
48+
lastElu = currentElu;
49+
obs.observe(eluGauge, diff.utilization);
50+
51+
// Event loop delay (nanoseconds -> seconds)
52+
obs.observe(eldP50, eld.percentile(50) / 1e9);
53+
obs.observe(eldP99, eld.percentile(99) / 1e9);
54+
obs.observe(eldMax, eld.max / 1e9);
55+
eld.reset();
56+
57+
// Heap
58+
const mem = process.memoryUsage();
59+
obs.observe(heapUsed, mem.heapUsed);
60+
obs.observe(heapTotal, mem.heapTotal);
61+
},
62+
[eluGauge, eldP50, eldP99, eldMax, heapUsed, heapTotal]
63+
);
64+
}

packages/core/src/v3/otel/tracingSDK.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import {
6363
import { traceContext } from "../trace-context-api.js";
6464
import { getEnvVar } from "../utils/getEnv.js";
6565
import { machineId } from "./machineId.js";
66+
import { startNodejsRuntimeMetrics } from "./nodejsRuntimeMetrics.js";
6667

6768
export type TracingDiagnosticLogLevel =
6869
| "none"
@@ -84,6 +85,8 @@ export type TracingSDKConfig = {
8485
diagLogLevel?: TracingDiagnosticLogLevel;
8586
resource?: Resource;
8687
hostMetrics?: boolean;
88+
/** Enable Node.js runtime metrics (event loop utilization, heap usage, etc.) */
89+
nodejsRuntimeMetrics?: boolean;
8790
/** Metric instrument name patterns to drop (supports wildcards, e.g. "system.cpu.*") */
8891
droppedMetrics?: string[];
8992
};
@@ -326,6 +329,10 @@ export class TracingSDK {
326329
hostMetrics.start();
327330
}
328331

332+
if (config.nodejsRuntimeMetrics) {
333+
startNodejsRuntimeMetrics(meterProvider);
334+
}
335+
329336
this.getLogger = loggerProvider.getLogger.bind(loggerProvider);
330337
this.getTracer = traceProvider.getTracer.bind(traceProvider);
331338
}

0 commit comments

Comments
 (0)