@platformatic/metrics
Advanced tools
+21
-190
@@ -6,17 +6,2 @@ import collectHttpMetrics from '@platformatic/http-metrics' | ||
| // Import individual metric collectors from prom-client | ||
| import processCpuTotal from '@platformatic/prom-client/lib/metrics/processCpuTotal.js' | ||
| import processStartTime from '@platformatic/prom-client/lib/metrics/processStartTime.js' | ||
| import osMemoryHeap from '@platformatic/prom-client/lib/metrics/osMemoryHeap.js' | ||
| import processOpenFileDescriptors from '@platformatic/prom-client/lib/metrics/processOpenFileDescriptors.js' | ||
| import processMaxFileDescriptors from '@platformatic/prom-client/lib/metrics/processMaxFileDescriptors.js' | ||
| import eventLoopLag from '@platformatic/prom-client/lib/metrics/eventLoopLag.js' | ||
| import processHandles from '@platformatic/prom-client/lib/metrics/processHandles.js' | ||
| import processRequests from '@platformatic/prom-client/lib/metrics/processRequests.js' | ||
| import processResources from '@platformatic/prom-client/lib/metrics/processResources.js' | ||
| import heapSizeAndUsed from '@platformatic/prom-client/lib/metrics/heapSizeAndUsed.js' | ||
| import heapSpacesSizeAndUsed from '@platformatic/prom-client/lib/metrics/heapSpacesSizeAndUsed.js' | ||
| import version from '@platformatic/prom-client/lib/metrics/version.js' | ||
| import gc from '@platformatic/prom-client/lib/metrics/gc.js' | ||
| export * as client from '@platformatic/prom-client' | ||
@@ -29,45 +14,2 @@ | ||
| // Process-level metrics (same across all workers, collect once in main thread) | ||
| export const PROCESS_LEVEL_METRICS = [ | ||
| 'process_cpu_user_seconds_total', | ||
| 'process_cpu_system_seconds_total', | ||
| 'process_cpu_seconds_total', | ||
| 'process_start_time_seconds', | ||
| 'process_resident_memory_bytes', | ||
| 'process_open_fds', | ||
| 'process_max_fds', | ||
| 'nodejs_version_info', | ||
| 'process_cpu_percent_usage' | ||
| ] | ||
| // Thread/isolate-specific metrics (different per worker) | ||
| export const THREAD_LEVEL_METRICS = [ | ||
| 'nodejs_heap_size_total_bytes', | ||
| 'nodejs_heap_size_used_bytes', | ||
| 'nodejs_external_memory_bytes', | ||
| 'nodejs_heap_space_size_total_bytes', | ||
| 'nodejs_heap_space_size_used_bytes', | ||
| 'nodejs_heap_space_size_available_bytes', | ||
| 'nodejs_eventloop_lag_seconds', | ||
| 'nodejs_eventloop_lag_min_seconds', | ||
| 'nodejs_eventloop_lag_max_seconds', | ||
| 'nodejs_eventloop_lag_mean_seconds', | ||
| 'nodejs_eventloop_lag_stddev_seconds', | ||
| 'nodejs_eventloop_lag_p50_seconds', | ||
| 'nodejs_eventloop_lag_p90_seconds', | ||
| 'nodejs_eventloop_lag_p99_seconds', | ||
| 'nodejs_eventloop_utilization', | ||
| 'nodejs_gc_duration_seconds', | ||
| 'nodejs_active_handles', | ||
| 'nodejs_active_handles_total', | ||
| 'nodejs_active_requests', | ||
| 'nodejs_active_requests_total', | ||
| 'nodejs_active_resources', | ||
| 'nodejs_active_resources_total', | ||
| 'thread_cpu_user_system_seconds_total', | ||
| 'thread_cpu_system_seconds_total', | ||
| 'thread_cpu_seconds_total', | ||
| 'thread_cpu_percent_usage' | ||
| ] | ||
| export function registerMetricsGroup (registry, group) { | ||
@@ -156,8 +98,21 @@ registry[kMetricsGroups] ??= new Set() | ||
| // Collect system CPU usage metric (based on os.cpus(), process-level) | ||
| export function collectSystemCpuMetric (registry) { | ||
| if (ensureMetricsGroup(registry, 'systemCpu')) { | ||
| export function collectEluMetric (registry) { | ||
| if (ensureMetricsGroup(registry, 'elu')) { | ||
| return | ||
| } | ||
| let startELU = eventLoopUtilization() | ||
| const eluMetric = new Gauge({ | ||
| name: 'nodejs_eventloop_utilization', | ||
| help: 'The event loop utilization as a fraction of the loop time. 1 is fully utilized, 0 is fully idle.', | ||
| collect: () => { | ||
| const endELU = eventLoopUtilization() | ||
| const result = eventLoopUtilization(endELU, startELU).utilization | ||
| eluMetric.set(result) | ||
| startELU = endELU | ||
| }, | ||
| registers: [registry] | ||
| }) | ||
| registry.registerMetric(eluMetric) | ||
| let previousIdleTime = 0 | ||
@@ -173,12 +128,10 @@ let previousTotalTime = 0 | ||
| for (let i = 0; i < cpus.length; i++) { | ||
| const cpu = cpus[i] | ||
| const times = cpu.times | ||
| for (const type in times) { | ||
| totalTime += times[type] | ||
| cpus.forEach(cpu => { | ||
| for (const type in cpu.times) { | ||
| totalTime += cpu.times[type] | ||
| if (type === 'idle') { | ||
| idleTime += times[type] | ||
| idleTime += cpu.times[type] | ||
| } | ||
| } | ||
| } | ||
| }) | ||
@@ -200,123 +153,2 @@ const idleDiff = idleTime - previousIdleTime | ||
| // Collect only the ELU metric (thread-specific) | ||
| export function collectEluMetric (registry) { | ||
| if (ensureMetricsGroup(registry, 'elu')) { | ||
| return | ||
| } | ||
| let startELU = eventLoopUtilization() | ||
| const eluMetric = new Gauge({ | ||
| name: 'nodejs_eventloop_utilization', | ||
| help: 'The event loop utilization as a fraction of the loop time. 1 is fully utilized, 0 is fully idle.', | ||
| collect: () => { | ||
| const endELU = eventLoopUtilization() | ||
| const result = eventLoopUtilization(endELU, startELU).utilization | ||
| eluMetric.set(result) | ||
| startELU = endELU | ||
| }, | ||
| registers: [registry] | ||
| }) | ||
| registry.registerMetric(eluMetric) | ||
| } | ||
| // Legacy function that collects both ELU and system CPU (for backward compatibility) | ||
| export function collectEluAndSystemCpuMetrics (registry) { | ||
| collectEluMetric(registry) | ||
| collectSystemCpuMetric(registry) | ||
| } | ||
| // Collect process-level metrics (same across all workers, should run in main thread only) | ||
| export function collectProcessMetrics (registry) { | ||
| if (ensureMetricsGroup(registry, 'process-level')) { | ||
| return | ||
| } | ||
| const config = {} | ||
| // Process CPU metrics | ||
| processCpuTotal(registry, config) | ||
| // Process start time | ||
| processStartTime(registry, config) | ||
| // Resident memory (RSS) | ||
| osMemoryHeap(registry, config) | ||
| // Open file descriptors (Linux) | ||
| processOpenFileDescriptors(registry, config) | ||
| // Max file descriptors (Linux) | ||
| processMaxFileDescriptors(registry, config) | ||
| // Node.js version info | ||
| version(registry, config) | ||
| // System CPU percent usage (os.cpus() based) | ||
| collectSystemCpuMetric(registry) | ||
| } | ||
| // Collect thread-specific metrics (different per worker) | ||
| export async function collectThreadMetrics (applicationId, workerId, metricsConfig = {}, registry = undefined) { | ||
| if (!registry) { | ||
| registry = new Registry() | ||
| } | ||
| const labels = { ...metricsConfig.labels } | ||
| // Use the configured label name | ||
| const labelName = metricsConfig.idLabel || 'applicationId' | ||
| labels[labelName] = applicationId | ||
| if (workerId >= 0) { | ||
| labels.workerId = workerId | ||
| } | ||
| registry.setDefaultLabels(labels) | ||
| if (metricsConfig.defaultMetrics) { | ||
| if (!ensureMetricsGroup(registry, 'thread-level')) { | ||
| const config = { eventLoopMonitoringPrecision: 10 } | ||
| // Thread-specific metrics only | ||
| heapSizeAndUsed(registry, config) | ||
| heapSpacesSizeAndUsed(registry, config) | ||
| eventLoopLag(registry, config) | ||
| gc(registry, config) | ||
| processHandles(registry, config) | ||
| processRequests(registry, config) | ||
| if (typeof process.getActiveResourcesInfo === 'function') { | ||
| processResources(registry, config) | ||
| } | ||
| } | ||
| // Event loop utilization (thread-specific) | ||
| collectEluMetric(registry) | ||
| // Thread CPU metrics | ||
| await collectThreadCpuMetrics(registry) | ||
| } | ||
| if (metricsConfig.httpMetrics && !ensureMetricsGroup(registry, 'http')) { | ||
| collectHttpMetrics(registry, { | ||
| customLabels: ['telemetry_id'], | ||
| getCustomLabels: req => { | ||
| const telemetryId = req.headers?.['x-plt-telemetry-id'] ?? 'unknown' | ||
| return { telemetry_id: telemetryId } | ||
| }, | ||
| histogram: { | ||
| name: 'http_request_all_duration_seconds', | ||
| help: 'request duration in seconds summary for all requests', | ||
| collect: function () { | ||
| process.nextTick(() => this.reset()) | ||
| } | ||
| }, | ||
| summary: { | ||
| name: 'http_request_all_summary_seconds', | ||
| help: 'request duration in seconds histogram for all requests', | ||
| collect: function () { | ||
| process.nextTick(() => this.reset()) | ||
| } | ||
| } | ||
| }) | ||
| } | ||
| return { | ||
| registry, | ||
| otlpBridge: null | ||
| } | ||
| } | ||
| // Original function for backward compatibility (collects all metrics) | ||
| export async function collectMetrics (applicationId, workerId, metricsConfig = {}, registry = undefined) { | ||
@@ -344,3 +176,2 @@ if (!registry) { | ||
| collectEluMetric(registry) | ||
| collectSystemCpuMetric(registry) | ||
| await collectThreadCpuMetrics(registry) | ||
@@ -347,0 +178,0 @@ } |
+1
-1
| { | ||
| "name": "@platformatic/metrics", | ||
| "version": "3.31.0", | ||
| "version": "3.32.0-alpha.0", | ||
| "description": "Platformatic Capability Metrics", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
34528
-14.77%588
-20.54%1
Infinity%