Skip to content

Commit

Permalink
Added support for using default route
Browse files Browse the repository at this point in the history
This is useful for dynamically setting the host in containers.
For example, most Kubernetes nodes will have a statsd server on them,
and using this will allow containers to send metrics directly to that
without extra configuration.

(Inspired by the same option in the datadogpy library)

Tested by:
    Checking the output of the getDefaultRoute() function
  • Loading branch information
tanelso2 committed Apr 3, 2018
1 parent 4df911e commit c870245
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Parameters (specified as an options hash):
* `telegraf`: Use Telegraf's StatsD line protocol, which is slightly different than the rest `default: false`
* `sampleRate`: Sends only a sample of data to StatsD for all StatsD methods. Can be overriden at the method level. `default: 1`
* `errorHandler`: A function with one argument. It is called to handle various errors. `default: none`, errors are thrown/logger to console
* `useDefaultRoute`: Use the default interface on a Linux system. Useful when running in containers

All StatsD methods other than event and close have the same API:
* `name`: Stat name `required`
Expand Down
42 changes: 41 additions & 1 deletion lib/statsd.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

var dgram = require('dgram'),
util = require('util'),
dns = require('dns');
dns = require('dns'),
fs = require('fs');

/**
* The UDP Client for StatsD
Expand All @@ -19,6 +20,7 @@ var dgram = require('dgram'),
* @maxBufferSize {Number} An optional value for aggregating metrics to send, mainly for performance improvement
* @bufferFlushInterval {Number} the time out value to flush out buffer if not
* @option sampleRate {Float} Global Sampling rate, default: 1 (No sampling)
* @option useDefaultRoute {boolean} An optional boolean to use the default route on Linux. Useful for containers
* @constructor
*/
var Client = function (host, port, prefix, suffix, globalize, cacheDns, mock,
Expand Down Expand Up @@ -87,6 +89,14 @@ var Client = function (host, port, prefix, suffix, globalize, cacheDns, mock,
global.statsd = this;
}

if(options.useDefaultRoute) {
var defaultRoute = getDefaultRoute();
if (defaultRoute) {
console.log('Got ' + defaultRoute + " for the system's default route");
this.host = defaultRoute;
}
}

this.CHECKS = {
OK: 0,
WARNING: 1,
Expand Down Expand Up @@ -690,5 +700,35 @@ function formatDate(date) {
return timestamp;
}

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
function getDefaultRoute() {
try {
var fileContents = fs.readFileSync('/proc/net/route');
var routes = fileContents.split('\n');
for (var route in routes) {
var fields = route.trim().split('');
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;
1 change: 1 addition & 0 deletions types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ declare module "hot-shots" {
socket?: dgram.Socket;
suffix?: string;
telegraf?: boolean;
useDefaultRoute?: boolean;
}

export interface ChildClientOptions {
Expand Down

0 comments on commit c870245

Please sign in to comment.