Skip to content
This repository has been archived by the owner on May 5, 2022. It is now read-only.

just for Ravi to review don't need to merge #48

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 92 additions & 13 deletions appmetrics-zipkin.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,19 @@ var aspect = require('./lib/aspect.js');
var fs = require('fs');
var PropertyReader = require('properties-reader');
var properties = PropertyReader(__dirname + '/appmetrics-zipkin.properties');
var tcpp = require('tcp-ping');
var {Endpoint} = require('zipkin/lib/model');
Endpoint.prototype.setServiceName = function setServiceName(serviceName) {
// In zipkin, names are lowercase. This eagerly converts to alert users early.
this.serviceName = serviceName || undefined;
};

const {
BatchRecorder
} = require('zipkin');
const {
HttpLogger
} = require('zipkin-transport-http');
const HttpsLogger = require('./lib/zipkin-transport-https');

// Load module probes into probes array by searching the probes directory.
var probes = [];
Expand All @@ -54,10 +59,22 @@ module.exports = function(options) {
function start(options) {
// Set up the zipkin
var host, port, serviceName, sampleRate;
var zipkin_endpoint, pfx, passphase;

global.KNJ_TT_MAX_LENGTH = global.KNJ_TT_MAX_LENGTH || 128;

if (options) {
host = options['host'];
port = options['port'];
if (options.zipkinEndpoint){
zipkin_endpoint = options.zipkinEndpoint;
}
if (options.pfx){
pfx = options.pfx;
}
if (options.passphase){
passphase = options.passphase;
}
serviceName = options['serviceName'];
sampleRate = options['sampleRate'];
}
Expand Down Expand Up @@ -92,20 +109,28 @@ function start(options) {
}

// Test if the host & port are valid
tcpp.probe(host, port, function(err, available) {
if (err) {
console.log('Unable to contact Zipkin at ' + host + ':' + port);
return;
}
if (!available) {
console.log('Unable to contact Zipkin at ' + host + ':' + port);
}
});
// if (host && port) {
// tcpp.probe(host, port, function(err, available) {
// if (err) {
// console.log('Unable to contact Zipkin at ' + host + ':' + port);
// return;
// }
// if (!available) {
// console.log('Unable to contact Zipkin at ' + host + ':' + port);
// }
// });
// }

const zipkinUrl = `http://${host}:${port}`;
const zipkinUrl = zipkin_endpoint || `http://${host}:${port}/api/v1/spans`;
const recorder = new BatchRecorder({
logger: new HttpLogger({
endpoint: `${zipkinUrl}/api/v1/spans`
logger: zipkinUrl.startsWith('https:') ?
new HttpsLogger({
endpoint: zipkinUrl,
pfx: pfx,
passphase: passphase
}) :
new HttpLogger({
endpoint: zipkinUrl
})
});

Expand All @@ -119,6 +144,60 @@ function start(options) {
});
}

module.exports.update = function(options) {
start(options);
// for (var i = 0; i < probes.length; i++) {
// probes[i].updateServiceName(probes[i].serviceName);
// }
probes.forEach(function(probe) {
probe.updateProbes();
// probe.enableRequests();
});
};

module.exports.updateServiceName = function(serviceName){
probes.forEach(function(probe) {
probe.setServiceName(serviceName);
probe.updateProbes();
});
};

module.exports.updatePathFilter = function(paths){
probes.forEach(function(probe) {
probe.setPathFilter(paths);
probe.updateProbes();
});
};


module.exports.updateHeaderFilter = function(headers){
probes.forEach(function(probe) {
probe.setHeaderFilter(headers);
probe.updateProbes();
});
};


module.exports.updateIbmapmContext = function(context) {
probes.forEach(function(probe) {
probe.setIbmapmContext(context);
probe.updateProbes();
});
};

module.exports.stop = function(){
probes.forEach(function(probe) {
probe.stop();
// probe.enableRequests();
});
};

module.exports.disable = function(){
probes.forEach(function(probe) {
probe.disable();
// probe.enableRequests();
});
};
/*
* Patch the module require function to run the probe attach function
* for any matching module. This loads the monitoring probes into the modules
Expand Down
2 changes: 1 addition & 1 deletion lib/aspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

exports.aroundCallback = function(args, context, hookBefore, hookAfter) {
var position = this.findCallbackArg(args);
if (position == undefined) return;
if (position === undefined) return;

var orig = args[position];

Expand Down
13 changes: 13 additions & 0 deletions lib/probe.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ function Probe(name) {
this.config = {};
this.recorder = {};
this.serviceName = '';
this.ibmapmContext = {};
this.pathFilters = [];
this.headerFilters = {};
}

/*
Expand Down Expand Up @@ -54,6 +57,16 @@ Probe.prototype.setRecorder = function(recorder) {
Probe.prototype.setServiceName = function(name) {
this.serviceName = name;
};
Probe.prototype.setPathFilter = function(paths) {
this.pathFilters = paths || [];
};
Probe.prototype.setHeaderFilter = function(headers) {
this.headerFilters = headers || {};
};

Probe.prototype.setIbmapmContext = function(ibmapmContext) {
this.ibmapmContext = ibmapmContext;
};

/*
* Lightweight metrics probes
Expand Down
2 changes: 1 addition & 1 deletion lib/timer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function Timer() {

Timer.prototype.stop = function() {
// Prevent the timer being stopped twice.
if (this.timeDelta == -1) {
if (this.timeDelta === -1) {
var dur = process.hrtime(this.startTime);
this.timeDelta = (dur[0] * 1000) + (dur[1] / 1000000);
}
Expand Down
43 changes: 43 additions & 0 deletions lib/tools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

'use strict';

module.exports.recordIbmapmContext = function(tracer, ibmapmContext){
if (ibmapmContext && ibmapmContext.podName) {
tracer.recordBinary('pod.name', ibmapmContext.podName);
tracer.recordBinary('container.id', ibmapmContext.containerId);
tracer.recordBinary('namespace', ibmapmContext.nameSpace);
tracer.recordBinary('cluster.id', ibmapmContext.clusterID || 'unamedcluster');
tracer.recordBinary('node.name', ibmapmContext.nodeName);
tracer.recordBinary('service.name', ibmapmContext.serviceName);

}
if (ibmapmContext && ibmapmContext.applicationName) {
tracer.recordBinary('application.name', ibmapmContext.applicationName);
}
if (ibmapmContext && ibmapmContext['resource.id']) {
tracer.recordBinary('resource.id', ibmapmContext['resource.id']);
}
if (ibmapmContext && ibmapmContext.tenantId) {
tracer.recordBinary('tenant.id', ibmapmContext.tenantId);
}
if (ibmapmContext && ibmapmContext.ip) {
tracer.recordBinary('ip', ibmapmContext.ip);
}
};

module.exports.isIcamInternalRequest = function(options, headerFilters, pathFilters) {
if (options.headers) {
for (var key in headerFilters){
if (Object.keys(options.headers).indexOf(key) >= 0
|| options.headers[key] === headerFilters[key]){
return true;
}
}
}
for (var i = 0; i < pathFilters.length; i++) {
if (options.path.indexOf(pathFilters[i]) >= 0){
return true;
}
}
return false;
};
103 changes: 103 additions & 0 deletions lib/zipkin-transport-https.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
'use strict';
var uuid = require('uuid');
var https = require('https');
var url = require('url');
var commonTools = require('../../lib/tool/common.js');

var log4js = require('log4js');
var logger = log4js.getLogger('knj_log');
var _createClass = function() { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function(Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

var _require = require('zipkin');
var JSON_V1 = _require.jsonEncoder.JSON_V1;

var HttpsLogger = function() {
function HttpsLogger(_ref) {
var _this = this;

var endpoint = _ref.endpoint;
var _ref$httpInterval = _ref.httpInterval;
var httpInterval = _ref$httpInterval === undefined ? 1000 : _ref$httpInterval;
var _ref$jsonEncoder = _ref.jsonEncoder;
var jsonEncoder = _ref$jsonEncoder === undefined ? JSON_V1 : _ref$jsonEncoder;

_classCallCheck(this, HttpsLogger);

this.endpoint = endpoint;
this.pfx = _ref.pfx;
this.passphase = _ref.passphase;
this.queue = [];
this.jsonEncoder = jsonEncoder;

var timer = setInterval(function() {
_this.processQueue();
}, httpInterval);
if (timer.unref) {
// unref might not be available in browsers
timer.unref(); // Allows Node to terminate instead of blocking on timer
}
}

_createClass(HttpsLogger, [{
key: 'logSpan',
value: function logSpan(span) {
this.queue.push(this.jsonEncoder.encode(span));
}
}, {
key: 'processQueue',
value: function processQueue() {
if (this.queue.length > 0) {
var postBody = '[' + this.queue.join(',') + ']';
var options = url.parse(this.endpoint);
var header = {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-TransactionID': uuid.v1(),
'User-Agent': 'NodeDC'
};
if (process.env.APM_TENANT_ID) {
header['X-TenantId'] = process.env.APM_TENANT_ID;
}
var finalOptions = {
hostname: options.hostname,
host: options.host,
port: options.port,
path: options.path,
protocol: options.protocol,
pfx: this.pfx,
passphrase: this.passphase,
ca: this.pfx,
requestCert: true,
rejectUnauthorized: false,
method: 'POST',
headers: header
};
commonTools.tlsFix8(finalOptions);
try {
var req = https.request(finalOptions, function(res){
if (res.statusCode === 202)
logger.debug('Send to Jaeger server successfully: ', postBody);
else
logger.warn('Failed to sent to Jaeger server. statusCode=', res.statusCode, 'options=', finalOptions);
});
req.on('error', function(err){
logger.error('Failed to sent to Jaeger server');
logger.error(err);
});
req.write(postBody);
req.end();
} catch (e) {
logger.error('Failed to sent to Jaeger server');
logger.error(e);
}
this.queue.length = 0;
}
}
}]);

return HttpsLogger;
}();

module.exports = HttpsLogger;
Loading