statful-client
Advanced tools
Comparing version 5.0.0 to 6.0.0
'use strict'; | ||
var dgram = require('dgram'); | ||
var blocked = require('blocked'); | ||
var merge = require('merge'); | ||
@@ -58,56 +58,2 @@ var configHelper = require('./config-helper'); | ||
/** | ||
* Puts a system stats metric into the system stats buffer ready to be sent. | ||
* | ||
* @param self A self statful client. | ||
* @param metricTypeConf A configuration for each metric type (counter, gauge, timer). Can be null if it a custom metric. | ||
* @param name A metric name. | ||
* @param value A metric value. | ||
* @param aggregation The aggregation with which metric was aggregated. | ||
* @param aggregationFreq The aggregation frequency with which metric was aggregated. | ||
* @param parameters An object with metric para meters: tags, agg, aggFreq, namespace and timestamp. | ||
*/ | ||
function putSystemStatsMetrics (self, name, value, parameters) { | ||
var metricParams = parameters || {}; | ||
var tags = metricParams.tags, | ||
agg = metricParams.agg, | ||
aggFreq = metricParams.aggFreq, | ||
namespace = metricParams.namespace, | ||
timestamp = metricParams.timestamp, | ||
sampleRate = metricParams.sampleRate; | ||
putSystemStats(self, name, value, { | ||
tags: tags, | ||
agg: agg, | ||
aggFreq: aggFreq, | ||
namespace: namespace, | ||
timestamp: timestamp, | ||
sampleRate: sampleRate | ||
}); | ||
} | ||
function sendFlushStats (self) { | ||
if (self.systemStats) { | ||
var aggregations = ['avg', 'sum']; | ||
if (self.aggregatedBuffer.bufferSize > 0 && self.transport === 'api') { | ||
putSystemStatsMetrics(self, 'buffer.flush_length', self.aggregatedBuffer.bufferSize, { | ||
agg: aggregations, | ||
tags: { buffer_type: 'aggregated' } | ||
}); | ||
} | ||
if (self.nonAggregatedBuffer.bufferSize > 0) { | ||
putSystemStatsMetrics(self, 'buffer.flush_length', self.nonAggregatedBuffer.bufferSize, { | ||
agg: aggregations, | ||
tags: { buffer_type: 'non-aggregated' } | ||
}); | ||
} | ||
if (self.systemStatsBuffer.bufferSize > 0) { | ||
putSystemStatsMetrics(self, 'buffer.flush_length', self.systemStatsBuffer.bufferSize, { | ||
agg: aggregations, | ||
tags: { buffer_type: 'system-stats' } | ||
}); | ||
} | ||
} | ||
} | ||
/** | ||
* Logs all the metrics to the logger | ||
@@ -142,7 +88,17 @@ * | ||
} | ||
if (self.systemStatsBuffer.bufferSize > 0) { | ||
self.logger.debug('Flushing metrics (system stats): ' + self.systemStatsBuffer.buffer); | ||
if (pluginsBuffersSize(self.pluginBuffers) > 0) { | ||
self.logger.debug('Flushing plugins metrics'); | ||
} | ||
} | ||
function pluginsBuffersSize (buffers) { | ||
var size = 0; | ||
for (var i in buffers) { | ||
size += buffers[i].bufferSize; | ||
} | ||
return size; | ||
} | ||
/** | ||
@@ -169,4 +125,4 @@ * Sends the non aggregated and system stats metrics using UDP transport | ||
if (self.systemStatsBuffer.bufferSize > 0) { | ||
buffer = new Buffer(self.systemStatsBuffer.buffer); | ||
for (var i in self.pluginBuffers) { | ||
buffer = new Buffer(self.pluginBuffers[i].buffer); | ||
self.socket.send(buffer, 0, buffer.length, self.port, self.host); | ||
@@ -239,18 +195,21 @@ } | ||
if (self.systemStatsBuffer.bufferSize > 0) { | ||
var nonAggregatedStatsOptions = transport.buildRequestOptions( | ||
self.protocol, | ||
self.host, | ||
self.port, | ||
self.basePath, | ||
self.token, | ||
self.timeout | ||
); | ||
for (var i in self.pluginBuffers) { | ||
var element = self.pluginBuffers[i]; | ||
if(element.bufferSize > 0) { | ||
var nonAggregatedStatsOptions = transport.buildRequestOptions( | ||
self.protocol, | ||
self.host, | ||
self.port, | ||
self.basePath, | ||
self.token, | ||
self.timeout | ||
); | ||
self.logger.debug('Flushing to ' + nonAggregatedStatsOptions.url + ' system stats metrics'); | ||
self.logger.debug('Flushing to ' + nonAggregatedStatsOptions.url + ' system stats metrics'); | ||
if (self.compression) { | ||
transport.sendCompressedMessage(nonAggregatedStatsOptions, self.systemStatsBuffer.buffer, self.logger); | ||
} else { | ||
transport.sendUncompressedMessage(nonAggregatedStatsOptions, self.systemStatsBuffer.buffer, self.logger); | ||
if (self.compression) { | ||
transport.sendCompressedMessage(nonAggregatedStatsOptions, element.buffer, self.logger); | ||
} else { | ||
transport.sendUncompressedMessage(nonAggregatedStatsOptions, element.buffer, self.logger); | ||
} | ||
} | ||
@@ -266,5 +225,10 @@ } | ||
function flush (self) { | ||
sendFlushStats(self); | ||
for (var index = 0; index < self.plugins.length; index++) { | ||
if(typeof self.plugins[index].onFlush === 'function') { | ||
self.plugins[index].onFlush(self); | ||
} | ||
} | ||
var metricsCounter = | ||
self.aggregatedBuffer.bufferSize + self.nonAggregatedBuffer.bufferSize + self.systemStatsBuffer.bufferSize; | ||
self.aggregatedBuffer.bufferSize + self.nonAggregatedBuffer.bufferSize + pluginsBuffersSize(self.pluginBuffers); | ||
@@ -288,4 +252,7 @@ if (metricsCounter > 0) { | ||
self.nonAggregatedBuffer.bufferSize = 0; | ||
self.systemStatsBuffer.buffer = ''; | ||
self.systemStatsBuffer.bufferSize = 0; | ||
for (var i in self.pluginBuffers) { | ||
self.pluginBuffers[i].buffer = ''; | ||
self.pluginBuffers[i].bufferSize = 0; | ||
} | ||
} | ||
@@ -326,3 +293,3 @@ } | ||
self.nonAggregatedBuffer.bufferSize + | ||
self.systemStatsBuffer.bufferSize >= | ||
pluginsBuffersSize(self.pluginBuffers) >= | ||
self.flushSize | ||
@@ -340,23 +307,2 @@ ) { | ||
/** | ||
* Adds raw metrics directly into the flush buffer. Use this method with caution. | ||
* | ||
* @param self A self client instance. | ||
* @param metricLines The metrics, in valid line protocol, to push to the buffer. | ||
*/ | ||
function addToStatsBuffer (self, metricLines) { | ||
if (typeof metricLines !== 'undefined') { | ||
var targetBuffer = self.systemStatsBuffer; | ||
if (targetBuffer.bufferSize > 0) { | ||
targetBuffer.buffer += '\n'; | ||
} | ||
targetBuffer.buffer += metricLines; | ||
targetBuffer.bufferSize++; | ||
} else { | ||
self.logger.error('addToStatsBuffer: Invalid metric lines: ' + metricLines); | ||
} | ||
} | ||
/** | ||
* Adds a new metric to the in-memory buffer. | ||
@@ -421,56 +367,2 @@ * | ||
/** | ||
* Adds a new system stats metric to the in-memory system stats buffer. | ||
* | ||
* @param self A self client instance. | ||
* @param metric Name metric such as 'response_time'. | ||
* @param value. | ||
* @param parameters An object with metric para meters: tags, agg, aggFreq, namespace and timestamp. | ||
* - tags: Tags to associate this value with, for example {from: 'serviceA', to: 'serviceB', method: 'login'}. | ||
* - agg: List of aggregations to be applied by Statful. Ex: ['avg', 'p90', 'min']. | ||
* - aggFreq: Aggregation frequency in seconds. One of: 10, 30, 60 ,120, 180, 300. Default: 10. | ||
* - namespace: Define the metric namespace. Default: application. | ||
* - timestamp: Defines the metrics timestamp. Default: current timestamp. | ||
*/ | ||
function putSystemStats (self, metric, value, parameters) { | ||
var metricParams = parameters || {}; | ||
var tags = metricParams.tags, | ||
agg = metricParams.agg, | ||
aggFreq = metricParams.aggFreq, | ||
namespace = metricParams.namespace, | ||
timestamp = metricParams.timestamp, | ||
sampleRate = parameters.sampleRate || self.sampleRate; | ||
// Vars to Put | ||
var putNamespace = namespace || self.namespace; | ||
var putAggFreq = aggFreq || 10; | ||
var putTags = merge(self.app ? merge({ app: self.app }, tags) : tags, self.tags); | ||
var metricName = putNamespace + '.' + metric, | ||
flushLine = metricName, | ||
sampleRateNormalized = (sampleRate || 100) / 100; | ||
if (Math.random() <= sampleRateNormalized) { | ||
flushLine = Object.keys(putTags).reduce(function (previousValue, tag) { | ||
return previousValue + ',' + tag + '=' + putTags[tag]; | ||
}, flushLine); | ||
flushLine += ' ' + value + ' ' + (timestamp || Math.round(new Date().getTime() / 1000)); | ||
if (agg) { | ||
agg.push(putAggFreq); | ||
flushLine += ' ' + agg.join(','); | ||
if (sampleRate && sampleRate < 100) { | ||
flushLine += ' ' + sampleRate; | ||
} | ||
} | ||
addToStatsBuffer(self, [flushLine]); | ||
} else { | ||
self.logger.debug('Metric was discarded due to sample rate.'); | ||
} | ||
} | ||
/** | ||
* Calls put metric with an aggregated metric. | ||
@@ -544,3 +436,2 @@ * | ||
this.tags = config.tags || {}; | ||
this.systemStats = config.systemStats !== undefined ? config.systemStats : true; | ||
this.sampleRate = config.sampleRate || 100; | ||
@@ -572,16 +463,5 @@ this.flushInterval = config.flushInterval || 3000; | ||
this.systemStatsBuffer = { | ||
buffer: '', | ||
bufferSize: 0 | ||
}; | ||
this.plugins = []; | ||
this.pluginBuffers = {}; | ||
if (this.systemStats) { | ||
blocked(function (ms) { | ||
putSystemStatsMetrics(self, 'timer.event_loop', ms, { | ||
agg: ['avg', 'p90', 'count'], | ||
tags: { unit: 'ms' } | ||
}); | ||
}); | ||
} | ||
setInterval( | ||
@@ -753,2 +633,14 @@ function (obj) { | ||
Client.prototype.use = function (plugin) { | ||
if (!plugin || typeof plugin !== 'object') { | ||
throw 'Invalid plugin'; | ||
} | ||
if(typeof plugin.onInit === 'function') { | ||
plugin.onInit(this); | ||
} | ||
this.plugins.push(plugin); | ||
}; | ||
module.exports = Client; |
@@ -10,3 +10,3 @@ { | ||
}, | ||
"version": "5.0.0", | ||
"version": "6.0.0", | ||
"engines": { | ||
@@ -13,0 +13,0 @@ "node": ">=4.4.0" |
@@ -22,4 +22,5 @@ Statful Client for NodeJS | ||
|:---|:---| | ||
| 4.x.x | `4.4.0`, `5.12.0`, `6.9.2`, `7.10.1`, `8.2.0` | | ||
| 5.x.x | `6.9.2`, `7.10.1`, `8.2.0`, `10.9.0` | | ||
| 4.x.x | `4.4.0`, `5.12.0`, `6.9.2`, `7.10.1`, `8.2.0` | | ||
| 5.x.x | `6.9.2`, `7.10.1`, `8.2.0`, `10.9.0` | | ||
| 6.x.x | `8.2.0`, `8.12.0`, `10.12.0`, `11.0.0` | | ||
@@ -204,3 +205,2 @@ ## Installation | ||
| _dryRun_ | Defines if metrics should be output to the logger instead of being send. | `boolean` | `false` | **NO** | | ||
| _systemStats_ | Enables sending metrics with flush stats. | `boolean` | `true` | **NO** | | ||
| _flushInterval_ | Defines the periodicity of buffer flushes in **miliseconds**. | `number` | `3000` | **NO** | | ||
@@ -242,3 +242,3 @@ | _flushSize_ | Defines the maximum buffer size before performing a flush. | `number` | `1000` | **NO** | | ||
|:---|:---|:---|:---|:---|:---| | ||
| **_agg_** (`array`) - Defines the aggregations to be executed. These aggregations are merged with the ones configured globally, including method defaults.<br><br> **Valid Aggregations:** `avg, count, sum, first, last, p90, p95, min, max` | `['avg', 'p90']` | `[last]` | `['avg', 'p90', 'count']` | `[]` | **NO** | | ||
| **_agg_** (`array`) - Defines the aggregations to be executed. These aggregations are merged with the ones configured globally, including method defaults.<br><br> **Valid Aggregations:** `avg, count, sum, first, last, p90, p95, min, max` | `['sum', 'count']` | `[last]` | `['avg', 'p90', 'count']` | `[]` | **NO** | | ||
| **_aggFreq_** (`number`) - Defines the aggregation frequency in **seconds**. It overrides the global aggregation frequency configuration.<br><br> **Valid Aggregation Frequencies:** `10, 30, 60, 120, 180, 300` | `10` | `10` | `10` | `10`' | **NO** | | ||
@@ -249,2 +249,31 @@ | **_namespace_** (`string`) - Defines the namespace of the metric. It overrides the global namespace configuration. | `application` | `application` | `application` | `application` | **YES** | | ||
## Plugins | ||
It is possible to use plugin with the client. | ||
```javascript | ||
var SystemStatsPlugin = require('statful-client').systemStatsPlugin; | ||
var statful = new Statful(config, log); | ||
statful.use(new SystemStatsPlugin()); | ||
``` | ||
### System Stats Plugin | ||
This plugin allows the client to send system-related metrics and/or enrich the user metrics with system tags. | ||
#### System Stats Plugin Configuration | ||
The custom options that can be set on config param are detailed below. | ||
| Option | Description | Type | Default | Required | | ||
|:---|:---|:---|:---|:---| | ||
| _bufferFlushLength_ | Defines the application global name. If specified sets a global tag `app=setValue`. | `metric` | true | **NO** | | ||
| _timerEventLoop_ | Object to set methods options. | `metric` | true | **NO** | | ||
| _processUptime_ | Uptime of the process in **miliseconds**. | `metric` | true | **NO** | | ||
| _processMemoryUsage_ | Process memory usage in **bytes**. | `metric` | true | **NO** | | ||
| _processMemoryUsagePerc_ | Process memory usage **percentage**. (compared to total OS memory) | `metric` | true | **NO** | | ||
| _osUptime_ | OS uptime in **miliseconds**. | `metric` | true | **NO** | | ||
| _osTotalMemory_ | OS total memory in **bytes**. | `metric` | true | **NO** | | ||
| _osFreeMemory_ | OS free memory in **bytes**. | `metric` | true | **NO** | | ||
| _tagHostname_ | Hostname. | `tag` | true | **NO** | | ||
| _tagPlatform_ | Platform. | `tag` | true | **NO** | | ||
| _tagArchitecture_ | Architecture. | `tag` | true | **NO** | | ||
| _tagNodeVersion_ | NodeJS Version | `tag` | true | **NO** | | ||
## Authors | ||
@@ -251,0 +280,0 @@ |
module.exports = require('./lib/client'); | ||
module.exports.systemStatsPlugin = require('./plugins/system-stats'); |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
57058
12
1147
285