fix(smartmetrics): Refactor metrics calculation and update Prometheus integration documentation
This commit is contained in:
32
changelog.md
Normal file
32
changelog.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-06-09 - 2.0.8 - fix(smartmetrics)
|
||||
Refactor metrics calculation and update Prometheus integration documentation
|
||||
|
||||
- Removed dependency on registry.getMetricsAsJSON by directly calculating Node.js metrics
|
||||
- Updated getMetrics to compute CPU time, heap size, and set default values for deprecated metrics
|
||||
- Enhanced documentation with comprehensive Prometheus integration examples
|
||||
- Improved logging on shutdown of the Prometheus endpoint
|
||||
|
||||
## 2025-06-09 - 2.0.7 - Prometheus Metrics Integration
|
||||
feat: Implement Prometheus metrics exposure in SmartMetrics
|
||||
|
||||
- Added Prometheus gauges for CPU and memory metrics.
|
||||
- Implemented HTTP server to expose metrics at the /metrics endpoint.
|
||||
- Created methods to enable and disable the Prometheus endpoint.
|
||||
- Updated getMetrics() to set gauge values.
|
||||
- Added tests for Prometheus metrics functionality.
|
||||
- Updated documentation plan for Prometheus integration.
|
||||
|
||||
## 2023-07-02 to 2023-08-08 - 2.0.0 to 2.0.6 - Maintenance Updates
|
||||
Over this period several releases were published with iterative fixes and minor organizational changes.
|
||||
|
||||
- Applied multiple core fixes and routine maintenance updates.
|
||||
- Switched to new organization scheme (recorded on 2023-07-10).
|
||||
- Performed several version bumps and configuration updates.
|
||||
|
||||
## 2021-08-12 to 2022-07-27 - 1.0.1 to 1.0.17 - Maintenance and Breaking Changes
|
||||
During this interval a series of minor fixes were combined with a significant breaking change.
|
||||
|
||||
- BREAKING CHANGE: Switched to ESM in 1.0.17 (2022-07-27).
|
||||
- Numerous maintenance updates and core fixes were applied.
|
@ -1 +1,30 @@
|
||||
|
||||
# SmartMetrics Implementation Hints
|
||||
|
||||
## Prometheus Integration
|
||||
|
||||
The package now supports exposing metrics in Prometheus format through two mechanisms:
|
||||
|
||||
1. **Direct Export**: `getPrometheusFormattedMetrics()` returns metrics in Prometheus text exposition format
|
||||
2. **HTTP Endpoint**: `enablePrometheusEndpoint(port)` starts an HTTP server that exposes metrics on `/metrics`
|
||||
|
||||
### Architecture Decisions
|
||||
|
||||
- We use the prom-client library's default collectors for standard Node.js metrics
|
||||
- Custom gauges are created for our calculated metrics (CPU percentage, memory percentage, memory bytes)
|
||||
- The `getMetrics()` method calculates values directly rather than parsing the Prometheus registry JSON
|
||||
- For metrics like `nodejs_active_handles_total` and `nodejs_active_requests_total`, we return 0 in `getMetrics()` since these require deprecated Node.js APIs, but the Prometheus collectors still track the real values
|
||||
|
||||
### Consolidation Approach
|
||||
|
||||
Initially, we were mixing two approaches:
|
||||
1. Extracting values from the Prometheus registry JSON for default metrics
|
||||
2. Creating custom gauges for calculated metrics
|
||||
|
||||
We consolidated by:
|
||||
- Calculating all values directly in `getMetrics()` where possible
|
||||
- Only using the Prometheus registry for the text exposition format
|
||||
- This eliminates the dependency on parsing registry JSON and makes the code cleaner
|
||||
|
||||
### Memory Calculation
|
||||
|
||||
The package tracks memory usage across the main process and all child processes using `pidtree` and `pidusage`. This provides a more comprehensive view than just the main process memory.
|
27
readme.md
27
readme.md
@ -96,6 +96,33 @@ The `getMetrics` method returns a snapshot of various system metrics, including
|
||||
- `memoryUsageBytes`: Total memory used in bytes.
|
||||
- `memoryUsageText`: Readable string representation of memory usage.
|
||||
|
||||
### Prometheus Integration
|
||||
|
||||
`smartmetrics` can expose metrics in Prometheus format for scraping:
|
||||
|
||||
```typescript
|
||||
// Enable Prometheus endpoint on port 9090 (default)
|
||||
smartMetrics.enablePrometheusEndpoint();
|
||||
|
||||
// Or specify a custom port
|
||||
smartMetrics.enablePrometheusEndpoint(3000);
|
||||
|
||||
// The metrics will be available at http://localhost:9090/metrics
|
||||
|
||||
// To get Prometheus-formatted metrics programmatically
|
||||
const prometheusMetrics = await smartMetrics.getPrometheusFormattedMetrics();
|
||||
console.log(prometheusMetrics);
|
||||
|
||||
// Disable the endpoint when done
|
||||
smartMetrics.disablePrometheusEndpoint();
|
||||
```
|
||||
|
||||
The Prometheus endpoint exposes both default Node.js metrics (via prom-client) and custom calculated metrics:
|
||||
- `smartmetrics_cpu_percentage` - Current CPU usage percentage
|
||||
- `smartmetrics_memory_percentage` - Current memory usage percentage
|
||||
- `smartmetrics_memory_usage_bytes` - Current memory usage in bytes
|
||||
- Plus all default Node.js metrics collected by prom-client
|
||||
|
||||
### Conclusion
|
||||
|
||||
`@push.rocks/smartmetrics` offers a straightforward and efficient way to monitor essential system metrics of your Node.js application. By integrating it, you gain valuable insights into the performance and health of your system, aiding in diagnosis and optimization efforts.
|
||||
|
@ -71,8 +71,8 @@ Add Prometheus metrics exposure functionality to SmartMetrics while maintaining
|
||||
- [x] Clean up by calling `disablePrometheusEndpoint()`
|
||||
|
||||
### 10. Update Documentation
|
||||
- [ ] Add usage example in readme.md for Prometheus integration
|
||||
- [ ] Document the new methods in code comments
|
||||
- [x] Add usage example in readme.md for Prometheus integration
|
||||
- [x] Document the new methods in code comments
|
||||
|
||||
## Notes
|
||||
- Using Node.js built-in `http` module to avoid adding unnecessary dependencies
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* autocreated commitinfo by @pushrocks/commitinfo
|
||||
* autocreated commitinfo by @push.rocks/commitinfo
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartmetrics',
|
||||
version: '2.0.7',
|
||||
description: 'easy system metrics'
|
||||
version: '2.0.8',
|
||||
description: 'A package for easy collection and reporting of system and process metrics.'
|
||||
}
|
||||
|
@ -104,7 +104,6 @@ export class SmartMetrics {
|
||||
}
|
||||
|
||||
public async getMetrics() {
|
||||
const originalMetrics = await this.registry.getMetricsAsJSON();
|
||||
const pids = await plugins.pidtree(process.pid);
|
||||
const stats = await plugins.pidusage([process.pid, ...pids]);
|
||||
|
||||
@ -140,23 +139,23 @@ export class SmartMetrics {
|
||||
this.memoryUsageBytesGauge.set(memoryUsageBytes);
|
||||
}
|
||||
|
||||
// Calculate Node.js metrics directly
|
||||
const cpuUsage = process.cpuUsage();
|
||||
const process_cpu_seconds_total = (cpuUsage.user + cpuUsage.system) / 1000000; // Convert from microseconds to seconds
|
||||
|
||||
const heapStats = plugins.v8.getHeapStatistics();
|
||||
const nodejs_heap_size_total_bytes = heapStats.total_heap_size;
|
||||
|
||||
// Note: Active handles and requests are internal Node.js metrics that require deprecated APIs
|
||||
// We return 0 here, but the Prometheus default collectors will track the real values
|
||||
const nodejs_active_handles_total = 0;
|
||||
const nodejs_active_requests_total = 0;
|
||||
|
||||
const returnMetrics: interfaces.IMetricsSnapshot = {
|
||||
process_cpu_seconds_total: (
|
||||
originalMetrics.find((metricSet) => metricSet.name === 'process_cpu_seconds_total') as any
|
||||
).values[0].value,
|
||||
nodejs_active_handles_total: (
|
||||
originalMetrics.find((metricSet) => metricSet.name === 'nodejs_active_handles_total') as any
|
||||
).values[0].value,
|
||||
nodejs_active_requests_total: (
|
||||
originalMetrics.find(
|
||||
(metricSet) => metricSet.name === 'nodejs_active_requests_total'
|
||||
) as any
|
||||
).values[0].value,
|
||||
nodejs_heap_size_total_bytes: (
|
||||
originalMetrics.find(
|
||||
(metricSet) => metricSet.name === 'nodejs_heap_size_total_bytes'
|
||||
) as any
|
||||
).values[0].value,
|
||||
process_cpu_seconds_total,
|
||||
nodejs_active_handles_total,
|
||||
nodejs_active_requests_total,
|
||||
nodejs_heap_size_total_bytes,
|
||||
cpuPercentage,
|
||||
cpuUsageText,
|
||||
memoryPercentage,
|
||||
@ -208,8 +207,9 @@ export class SmartMetrics {
|
||||
return;
|
||||
}
|
||||
|
||||
const port = this.prometheusPort;
|
||||
this.prometheusServer.close(() => {
|
||||
this.logger.log('info', `Prometheus metrics endpoint on port ${this.prometheusPort} has been shut down`);
|
||||
this.logger.log('info', `Prometheus metrics endpoint on port ${port} has been shut down`);
|
||||
});
|
||||
|
||||
this.prometheusServer = undefined;
|
||||
|
Reference in New Issue
Block a user