forked from hapijs/hapi
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request hapijs#959 from wpreul/dtrace
Adding foundation for dtrace probe support
- Loading branch information
Showing
6 changed files
with
308 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// Load modules | ||
|
||
var Utils = require('./utils'); | ||
// dtrace-provider loaded inline when installed | ||
|
||
|
||
// Declare internals | ||
|
||
var internals = {}; | ||
|
||
|
||
module.exports = internals.DTrace = function (name) { | ||
|
||
Utils.assert(this.constructor === internals.DTrace, 'DTrace must be instantiated using new'); | ||
|
||
if (!internals.DTrace.isInstalled()) { | ||
this.report = function () {}; | ||
return; | ||
} | ||
|
||
this._probes = {}; | ||
this._dtrace = new internals.DTrace.Provider(name); | ||
}; | ||
|
||
|
||
internals.DTrace.prototype.report = function (key/* arg1, arg2 */) { | ||
|
||
var args = Array.prototype.slice.call(arguments, 1); | ||
var probe = this._probes[key] || this._addProbe(key, args); // If probe not found create and add it | ||
|
||
probe.fire(function () { | ||
|
||
return args; | ||
}); | ||
}; | ||
|
||
|
||
internals.DTrace.prototype._addProbe = function (key, values) { | ||
|
||
var paramTypes = []; | ||
for (var i = 0, il = values.length; i < il; ++i) { | ||
var value = values[i]; | ||
if (typeof value === 'number') { | ||
paramTypes.push('int'); | ||
} | ||
else if (value !== null && typeof value === 'object') { | ||
paramTypes.push('json'); | ||
} | ||
else { | ||
paramTypes.push('char *'); | ||
} | ||
} | ||
|
||
var probe = this._dtrace.addProbe.apply(this._dtrace, [key].concat(paramTypes)); | ||
this._probes[key] = probe; | ||
|
||
this._dtrace.disable(); // Provider must be disabled/enabled for probe to be visible | ||
this._dtrace.enable(); | ||
|
||
return probe; | ||
}; | ||
|
||
|
||
internals.DTrace.isInstalled = function () { | ||
|
||
var result = false; | ||
try { | ||
result = !!require.resolve('dtrace-provider'); | ||
} | ||
catch (err) {} | ||
|
||
internals.DTrace.isInstalled = function () { | ||
|
||
return result; | ||
}; | ||
|
||
return result; | ||
}; | ||
|
||
|
||
internals.DTrace.Provider = internals.DTrace.isInstalled() && require('dtrace-provider').DTraceProvider; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
// Load modules | ||
|
||
var Lab = require('lab'); | ||
var Hapi = require('../..'); | ||
var DTrace = require('../../lib/dtrace'); | ||
|
||
|
||
// Declare internals | ||
|
||
var internals = {}; | ||
|
||
|
||
// Test shortcuts | ||
|
||
var expect = Lab.expect; | ||
var before = Lab.before; | ||
var after = Lab.after; | ||
var describe = Lab.experiment; | ||
var it = Lab.test; | ||
|
||
|
||
describe('DTrace', function () { | ||
|
||
it('doesn\'t fire probes when dtrace provider isn\'t installed', function (done) { | ||
|
||
var provider = DTrace.Provider; | ||
var isInstalled = DTrace.isInstalled; | ||
DTrace.Provider = function () { | ||
|
||
return { | ||
enable: function () {}, | ||
disable: function () {}, | ||
addProbe: function () { | ||
|
||
return { | ||
fire: function (fn) { | ||
|
||
expect(fn).to.not.exist; | ||
} | ||
}; | ||
} | ||
}; | ||
}; | ||
DTrace.isInstalled = function () { | ||
|
||
return false; | ||
}; | ||
|
||
var server = new Hapi.Server(); | ||
|
||
|
||
var pre1 = function (request, next) { | ||
|
||
next('Hello'); | ||
}; | ||
|
||
server.route({ method: '*', path: '/', config: { | ||
handler: function () { | ||
|
||
this.reply('OK'); | ||
}, | ||
pre: [ | ||
{ method: pre1, assign: 'm1' } | ||
] | ||
}}); | ||
|
||
server.inject({ url: '/' }, function () { | ||
|
||
DTrace.Provider = provider; | ||
DTrace.isInstalled = isInstalled; | ||
done(); | ||
}); | ||
}); | ||
|
||
it('fires correct probe on prerequisites when dtrace-provider is installed', function (done) { | ||
|
||
var provider = DTrace.Provider; | ||
var isInstalled = DTrace.isInstalled; | ||
DTrace.Provider = function () { | ||
|
||
return { | ||
enable: function () {}, | ||
disable: function () {}, | ||
addProbe: function () { | ||
|
||
return { | ||
fire: function (fn) { | ||
|
||
expect(fn()).to.contain('m1'); | ||
DTrace.Provider = provider; | ||
DTrace.isInstalled = isInstalled; | ||
done(); | ||
} | ||
}; | ||
} | ||
}; | ||
}; | ||
DTrace.isInstalled = function () { | ||
|
||
return true; | ||
}; | ||
|
||
var server = new Hapi.Server(); | ||
var pre1 = function (request, next) { | ||
|
||
next('Hello'); | ||
}; | ||
|
||
server.route({ method: '*', path: '/', config: { | ||
handler: function () { | ||
|
||
this.reply('OK'); | ||
}, | ||
pre: [ | ||
{ method: pre1, assign: 'm1' } | ||
] | ||
}}); | ||
|
||
server.inject({ url: '/' }, function () {}); | ||
}); | ||
|
||
it('allows probes to be added dynamically', function (done) { | ||
|
||
var runNum = 0; | ||
var provider = DTrace.Provider; | ||
DTrace.Provider = function () { | ||
|
||
return { | ||
enable: function () {}, | ||
disable: function () {}, | ||
addProbe: function () { | ||
|
||
return { | ||
fire: function (fn) { | ||
|
||
if (runNum++ === 0) { | ||
expect(fn()).to.contain(20); | ||
expect(fn()).to.contain('some value'); | ||
} | ||
else { | ||
expect(fn()).to.contain(1); | ||
expect(fn()).to.contain('3'); | ||
} | ||
} | ||
}; | ||
} | ||
}; | ||
}; | ||
var server = new Hapi.Server(); | ||
|
||
server.route({ method: '*', path: '/', config: { | ||
handler: function () { | ||
|
||
this.server._dtrace.report('my.handler.start', 20, 'some value'); | ||
this.reply('OK'); | ||
this.server._dtrace.report('my.handler.end', 1, '3'); | ||
} | ||
}}); | ||
|
||
server.inject({ url: '/' }, function () { | ||
DTrace.Provider = provider; | ||
done(); | ||
}); | ||
}); | ||
|
||
it('probes add the correct data types', function (done) { | ||
|
||
var provider = DTrace.Provider; | ||
DTrace.Provider = function () { | ||
|
||
return { | ||
enable: function () {}, | ||
disable: function () {}, | ||
addProbe: function (key, val1, val2, val3) { | ||
|
||
expect(key).to.equal('my.probe'); | ||
expect(val1).to.equal('int'); | ||
expect(val2).to.equal('char *'); | ||
expect(val3).to.equal('json'); | ||
DTrace.Provider = provider; | ||
done(); | ||
|
||
return { | ||
fire: function () {} | ||
}; | ||
} | ||
}; | ||
}; | ||
var server = new Hapi.Server(); | ||
server._dtrace.report('my.probe', 20, 'some value', { some: 'obj' }); | ||
}); | ||
|
||
it('allows probes to be added dynamically with the dtrace-provider installed', function (done) { | ||
|
||
var server = new Hapi.Server(); | ||
|
||
server.route({ method: '*', path: '/', config: { | ||
handler: function () { | ||
|
||
this.server._dtrace.report('my.handler.start', 20, ['some value', 1]); | ||
this.reply('OK'); | ||
this.server._dtrace.report('my.handler.end', 1, '3'); | ||
} | ||
}}); | ||
|
||
server.inject({ url: '/' }, function (res) { | ||
|
||
expect(res.statusCode).to.equal(200); | ||
done(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters