Comparing version 5.4.1 to 5.5.0
CHANGELOG | ||
========= | ||
## 5.5.0 (2018-5-30) | ||
* @drewen Split up single file, add code coverage capabilities | ||
## 5.4.1 (2018-5-12) | ||
@@ -5,0 +8,0 @@ * @jasonsack Fixups for new useDefaultRoute option |
"use strict"; | ||
var dgram = require('dgram'), | ||
util = require('util'), | ||
dns = require('dns'), | ||
fs = require('fs'); | ||
var dgram = require('dgram'), | ||
util = require('util'), | ||
dns = require('dns'), | ||
helpers = require('./helpers'), | ||
applyStatsFns = require('./statsFunctions'); | ||
@@ -57,3 +58,4 @@ /** | ||
this.mock = options.mock; | ||
this.globalTags = typeof options.globalTags === "object" ? formatTags(options.globalTags, options.telegraf) : []; | ||
this.globalTags = typeof options.globalTags === "object" ? | ||
helpers.formatTags(options.globalTags, options.telegraf) : []; | ||
this.telegraf = options.telegraf || false; | ||
@@ -94,3 +96,3 @@ this.maxBufferSize = options.maxBufferSize || 0; | ||
if(options.useDefaultRoute) { | ||
var defaultRoute = getDefaultRoute(); | ||
var defaultRoute = helpers.getDefaultRoute(); | ||
if (defaultRoute) { | ||
@@ -110,264 +112,5 @@ console.log('Got ' + defaultRoute + " for the system's default route"); | ||
/** | ||
* Represents the timing stat | ||
* @param stat {String|Array} The stat(s) to send | ||
* @param time {Number} The time in milliseconds to send | ||
* @param sampleRate {Number=} The Number of times to sample (0 to 1). Optional. | ||
* @param tags {Array=} The Array of tags to add to metrics. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.timing = function (stat, time, sampleRate, tags, callback) { | ||
this.sendAll(stat, time, 'ms', sampleRate, tags, callback); | ||
}; | ||
applyStatsFns(Client); | ||
/** | ||
* Represents the timing stat by recording the duration a function takes to run (in milliseconds) | ||
* @param func {Function} The function to run | ||
* @param stat {String|Array} The stat(s) to send | ||
* @param sampleRate {Number=} The Number of times to sample (0 to 1). Optional. | ||
* @param tags {Array=} The Array of tags to add to metrics. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.timer = function (func, stat, sampleRate, tags, callback) { | ||
var _this = this; | ||
return function () { | ||
var start = process.hrtime(); | ||
try { | ||
return func.apply(null, arguments); | ||
} finally { | ||
// get duration in milliseconds | ||
var duration = process.hrtime(start)[1] / 1000000; | ||
_this.timing( | ||
stat, | ||
duration, | ||
sampleRate, | ||
tags, | ||
callback | ||
); | ||
} | ||
}; | ||
}; | ||
/** | ||
* Increments a stat by a specified amount | ||
* @param stat {String|Array} The stat(s) to send | ||
* @param value The value to send | ||
* @param sampleRate {Number=} The Number of times to sample (0 to 1). Optional. | ||
* @param tags {Array=} The Array of tags to add to metrics. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.increment = function (stat, value, sampleRate, tags, callback) { | ||
// allow use of tags without explicit value or sampleRate | ||
if (arguments.length < 3) { | ||
if (typeof value !== 'number') { | ||
tags = value; | ||
value = undefined; | ||
} | ||
} | ||
// we explicitly check for undefined and null (and don't do a "! value" check) | ||
// so that 0 values are allowed and sent through as-is | ||
if (value === undefined || value === null) { | ||
value = 1; | ||
} | ||
this.sendAll(stat, value, 'c', sampleRate, tags, callback); | ||
}; | ||
/** | ||
* Decrements a stat by a specified amount | ||
* @param stat {String|Array} The stat(s) to send | ||
* @param value The value to send | ||
* @param sampleRate {Number=} The Number of times to sample (0 to 1). Optional. | ||
* @param tags {Array=} The Array of tags to add to metrics. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.decrement = function (stat, value, sampleRate, tags, callback) { | ||
this.sendAll(stat, -value || -1, 'c', sampleRate, tags, callback); | ||
}; | ||
/** | ||
* Represents the histogram stat | ||
* @param stat {String|Array} The stat(s) to send | ||
* @param value The value to send | ||
* @param sampleRate {Number=} The Number of times to sample (0 to 1). Optional. | ||
* @param tags {Array=} The Array of tags to add to metrics. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.histogram = function (stat, value, sampleRate, tags, callback) { | ||
this.sendAll(stat, value, 'h', sampleRate, tags, callback); | ||
}; | ||
/** | ||
* Represents the distribution stat | ||
* @param stat {String|Array} The stat(s) to send | ||
* @param value The value to send | ||
* @param sampleRate {Number=} The Number of times to sample (0 to 1). Optional. | ||
* @param tags {Array=} The Array of tags to add to metrics. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.distribution = function (stat, value, sampleRate, tags, callback) { | ||
this.sendAll(stat, value, 'd', sampleRate, tags, callback); | ||
}; | ||
/** | ||
* Gauges a stat by a specified amount | ||
* @param stat {String|Array} The stat(s) to send | ||
* @param value The value to send | ||
* @param sampleRate {Number=} The Number of times to sample (0 to 1). Optional. | ||
* @param tags {Array=} The Array of tags to add to metrics. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.gauge = function (stat, value, sampleRate, tags, callback) { | ||
this.sendAll(stat, value, 'g', sampleRate, tags, callback); | ||
}; | ||
/** | ||
* Counts unique values by a specified amount | ||
* @param stat {String|Array} The stat(s) to send | ||
* @param value The value to send | ||
* @param sampleRate {Number=} The Number of times to sample (0 to 1). Optional. | ||
* @param tags {Array=} The Array of tags to add to metrics. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.unique = | ||
Client.prototype.set = function (stat, value, sampleRate, tags, callback) { | ||
this.sendAll(stat, value, 's', sampleRate, tags, callback); | ||
}; | ||
/** | ||
* Send a service check | ||
* @param name {String} The name of the service check | ||
* @param status {Number=} The status of the service check (0 to 3). | ||
* @param options | ||
* @option date_happened {Date} Assign a timestamp to the event. Default is now. | ||
* @option hostname {String} Assign a hostname to the check. | ||
* @option message {String} Assign a message to the check. | ||
* @param tags {Array=} The Array of tags to add to the check. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.check = function(name, status, options, tags, callback) { | ||
if (this.telegraf) { | ||
var err = new Error('Not supported by Telegraf / InfluxDB'); | ||
if (callback) { | ||
return callback(err); | ||
} | ||
else if (this.errorHandler) { | ||
return this.errorHandler(err); | ||
} | ||
throw err; | ||
} | ||
var check = ['_sc', this.prefix + name + this.suffix, status], | ||
metadata = options || {}; | ||
if (metadata.date_happened) { | ||
var timestamp = formatDate(metadata.date_happened); | ||
if (timestamp) { | ||
check.push('d:' + timestamp); | ||
} | ||
} | ||
if (metadata.hostname) { | ||
check.push('h:' + metadata.hostname); | ||
} | ||
var mergedTags = this.globalTags; | ||
if (tags && typeof(tags) === "object") { | ||
mergedTags = overrideTags(mergedTags, tags, this.telegraf); | ||
} | ||
if (mergedTags.length > 0) { | ||
check.push('#' + mergedTags.join(',')); | ||
} | ||
// message has to be the last part of a service check | ||
if (metadata.message) { | ||
check.push('m:' + metadata.message); | ||
} | ||
// allow for tags to be omitted and callback to be used in its place | ||
if(typeof tags === 'function' && callback === undefined) { | ||
callback = tags; | ||
} | ||
var message = check.join('|'); | ||
// Service checks are unique in that message has to be the last element in | ||
// the stat if provided, so we can't append tags like other checks. This | ||
// directly calls the `_send` method to avoid appending tags, since we've | ||
// already added them. | ||
this._send(message, callback); | ||
}; | ||
/** | ||
* Send on an event | ||
* @param title {String} The title of the event | ||
* @param text {String} The description of the event. Optional- title is used if not given. | ||
* @param options | ||
* @option date_happened {Date} Assign a timestamp to the event. Default is now. | ||
* @option hostname {String} Assign a hostname to the event. | ||
* @option aggregation_key {String} Assign an aggregation key to the event, to group it with some others. | ||
* @option priority {String} Can be ‘normal’ or ‘low’. Default is 'normal'. | ||
* @option source_type_name {String} Assign a source type to the event. | ||
* @option alert_type {String} Can be ‘error’, ‘warning’, ‘info’ or ‘success’. Default is 'info'. | ||
* @param tags {Array=} The Array of tags to add to metrics. Optional. | ||
* @param callback {Function=} Callback when message is done being delivered. Optional. | ||
*/ | ||
Client.prototype.event = function(title, text, options, tags, callback) { | ||
if (this.telegraf) { | ||
var err = new Error('Not supported by Telegraf / InfluxDB'); | ||
if (callback) { | ||
return callback(err); | ||
} | ||
else if (this.errorHandler) { | ||
return this.errorHandler(err); | ||
} | ||
throw err; | ||
} | ||
// Convert to strings | ||
var message, | ||
msgTitle = String(title ? title : ''), | ||
msgText = String(text ? text : msgTitle); | ||
// Escape new lines (unescaping is supported by DataDog) | ||
msgText = msgText.replace(/\n/g, '\\n'); | ||
// start out the message with the event-specific title and text info | ||
message = '_e{' + msgTitle.length + ',' + msgText.length + '}:' + msgTitle + '|' + msgText; | ||
// add in the event-specific options | ||
if (options) { | ||
if (options.date_happened) { | ||
var timestamp = formatDate(options.date_happened); | ||
if (timestamp) { | ||
message += '|d:' + timestamp; | ||
} | ||
} | ||
if (options.hostname) { | ||
message += '|h:' + options.hostname; | ||
} | ||
if (options.aggregation_key) { | ||
message += '|k:' + options.aggregation_key; | ||
} | ||
if (options.priority) { | ||
message += '|p:' + options.priority; | ||
} | ||
if (options.source_type_name) { | ||
message += '|s:' + options.source_type_name; | ||
} | ||
if (options.alert_type) { | ||
message += '|t:' + options.alert_type; | ||
} | ||
} | ||
// allow for tags to be omitted and callback to be used in its place | ||
if(typeof tags === 'function' && callback === undefined) { | ||
callback = tags; | ||
} | ||
this.send(message, tags, callback); | ||
}; | ||
/** | ||
* Checks if stats is an array and sends all stats calling back once all have sent | ||
@@ -469,3 +212,3 @@ * @param stat {String|Array} The stat(s) to send | ||
if(tags && typeof tags === "object"){ | ||
mergedTags = overrideTags(mergedTags, tags, this.telegraf); | ||
mergedTags = helpers.overrideTags(mergedTags, tags, this.telegraf); | ||
} | ||
@@ -636,3 +379,3 @@ if(mergedTags.length > 0){ | ||
globalTags : typeof options.globalTags === "object" ? | ||
overrideTags(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags, | ||
helpers.overrideTags(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags, | ||
maxBufferSize : parent.maxBufferSize, | ||
@@ -656,98 +399,3 @@ bufferFlushInterval: parent.bufferFlushInterval, | ||
function sanitizeTags(value, telegraf) { | ||
var blacklist = telegraf ? /:|\|/g : /:|\||@|,/g; | ||
// Replace reserved chars with underscores. | ||
return (value + "").replace(blacklist, "_"); | ||
} | ||
function formatTags(tags, telegraf) { | ||
if (Array.isArray(tags)) { | ||
return tags; | ||
} else { | ||
return Object.keys(tags).map(function (key) { | ||
return sanitizeTags(key, telegraf) + ":" + sanitizeTags(tags[key], telegraf); | ||
}); | ||
} | ||
} | ||
/** | ||
* Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as new | ||
* array. parent and child are not mutated. | ||
*/ | ||
function overrideTags (parent, child, telegraf) { | ||
var childCopy = {}; | ||
var toAppend = []; | ||
formatTags(child, telegraf).forEach(function (tag) { | ||
var idx = typeof tag === 'string' ? tag.indexOf(':') : -1; | ||
if (idx < 1) { // Not found or first character | ||
toAppend.push(tag); | ||
} else { | ||
childCopy[tag.substring(0, idx)] = tag.substring(idx + 1); | ||
} | ||
}); | ||
var result = parent.map(function (tag) { | ||
var idx = typeof tag === 'string' ? tag.indexOf(':') : -1; | ||
if (idx < 1) { // Not found or first character | ||
return tag; | ||
} | ||
var key = tag.substring(0, idx); | ||
if (childCopy.hasOwnProperty(key)) { | ||
var value = childCopy[key]; | ||
delete childCopy[key]; | ||
return key + ':' + value; | ||
} | ||
return tag; | ||
}); | ||
Object.keys(childCopy).forEach(function (key) { | ||
result.push(key + ':' + childCopy[key]); | ||
}); | ||
return result.concat(toAppend); | ||
} | ||
// Formats a date for use with DataDog | ||
function formatDate(date) { | ||
var timestamp; | ||
if (date instanceof Date) { | ||
// Datadog expects seconds. | ||
timestamp = Math.round(date.getTime() / 1000); | ||
} else if (date instanceof Number) { | ||
// Make sure it is an integer, not a float. | ||
timestamp = Math.round(date); | ||
} | ||
return timestamp; | ||
} | ||
// Converts int to a string IP | ||
function intToIP(int) { | ||
var part1 = int & 255; | ||
var part2 = ((int >> 8) & 255); | ||
var part3 = ((int >> 16) & 255); | ||
var part4 = ((int >> 24) & 255); | ||
return part4 + "." + part3 + "." + part2 + "." + part1; | ||
} | ||
// Returns the system default interface on Linux | ||
function getDefaultRoute() { | ||
try { | ||
var fileContents = fs.readFileSync('/proc/net/route', 'utf8'); | ||
var routes = fileContents.split('\n'); | ||
for (var routeIdx in routes) { | ||
var fields = routes[routeIdx].trim().split('\t'); | ||
if (fields[1] === '00000000') { | ||
var address = fields[2]; | ||
// Convert to little endian by splitting every 2 digits and reversing that list | ||
var littleEndianAddress = address.match(/.{2}/g).reverse().join(""); | ||
return intToIP(parseInt(littleEndianAddress, 16)); | ||
} | ||
} | ||
} catch (e) { | ||
console.error('Could not get default route from /proc/net/route'); | ||
} | ||
return null; | ||
} | ||
exports = module.exports = Client; | ||
exports.StatsD = Client; |
{ | ||
"name": "hot-shots", | ||
"description": "Node.js client for StatsD, DogStatsD, and Telegraf", | ||
"version": "5.4.1", | ||
"version": "5.5.0", | ||
"author": "Steve Ivy", | ||
@@ -33,2 +33,3 @@ "types": "./types.d.ts", | ||
"scripts": { | ||
"coverage": "nyc --reporter=lcov npm test", | ||
"test": "mocha -R spec", | ||
@@ -41,5 +42,6 @@ "lint": "jshint lib/**.js test/**.js", | ||
"jshint": "2.x", | ||
"mocha": "2.x" | ||
"mocha": "2.x", | ||
"nyc": "11.x" | ||
}, | ||
"license": "MIT" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
47945
11
767
3