pax_global_header00006660000000000000000000000064135256576150014531gustar00rootroot0000000000000052 comment=e9d860eaf553b489bd897e15bd0153f38b8e73a8 node-dtrace-provider-0.8.8/000077500000000000000000000000001352565761500155635ustar00rootroot00000000000000node-dtrace-provider-0.8.8/.gitignore000066400000000000000000000000761352565761500175560ustar00rootroot00000000000000.lock-wscript *.node *~ .#* *# build *.log node_modules *.tgz node-dtrace-provider-0.8.8/.gitmodules000066400000000000000000000001171352565761500177370ustar00rootroot00000000000000[submodule "libusdt"] path = libusdt url = https://github.com/chrisa/libusdt node-dtrace-provider-0.8.8/.npmignore000066400000000000000000000000761352565761500175650ustar00rootroot00000000000000.lock-wscript *.node *~ .#* *# build *.log test TODO.md *.tgz node-dtrace-provider-0.8.8/CHANGES.md000066400000000000000000000066021352565761500171610ustar00rootroot00000000000000dtrace-provider - Changes ========================= ## HISTORY * 0.8.8: Known support for v0.10.48, v0.12.16, v4.8.1, v6.17.0, v7.5.0, v8.16.0, v9.3.0, v10.16.0, v12.7.0 (#125) * 0.8.7: Known support for v0.10.48, v0.12.16, v4.6.0, v7.5.0, v8.9.4, v10.3.0 (#119) Don't crash when attempting to fire unknown probes (#120) * 0.8.6: Improved compilation failure behaviour (#96) * 0.8.5: Reverted "Install fails on Debian due to differently named node binary" for now * 0.8.4: Only log error once when DTraceProviderBindings can't be found Install fails on Debian due to differently named node binary * 0.8.3: Install fails with yarn * 0.8.2: Error installing in 64-bit SmartOS zones with 32-bit node * 0.8.1: Support FreeBSD 10 & 11 * 0.8.0: Support passing additional arguments to probe function via `.fire()` * 0.7.1: Update libusdt for chrisa/libusdt#12 fix * 0.7.0: known support for v0.10.47, v0.12.16, v4.6.0. Updated NaN dependency to remove warnings on newer Node versions. * 0.2.8: Add NODE_MODULE() declaration for compatibility with Node 0.9.1+ (reported by Trent Mick) Remove execSync dependency from tests. * 0.2.7: Don't build on FreeBSD by default - DTrace is not yet built in releases. * 0.2.6: Fall back to make(1) if gmake(1) is unavailable, still expected to be GNU Make (Trent Mick) * 0.2.5: Add "json" probe argument type, automatically serialising objects as JSON Trust npm to set PATH appropriately when invoking node (reported by Dave Pacheco) libusdt update - allow provider memory to be freed (reported by Bryan Cantrill) Build libusdt with gmake by default (reported by Keith Wesolowski) Turn the various scripts in test/ into a TAP-based testsuite. * 0.2.4: Improve Node architecture detection to support 0.6.x, and respect npm's prefix when choosing a node binary to use (reported by Trent Mick) * 0.2.3: libusdt update - don't invoke ranlib on SunOS-derived systems Disambiguate module name in probe tuple, and optionally allow it to be specified when creating a provider. (Bryan Cantrill bcantrill@acm.org) * 0.2.2: libusdt update for build fixes Respect MAKE variable in build script * 0.2.1: Update binding.gyp for clang on Snow Leopard - no space after -L. * 0.2.0: Update libusdt, and attempt to build it correctly for various platforms. Add support for disabling providers and removing probes. * 0.1.1: Replace Node-specific implementation with wrappers for libusdt. Extend argument support to 32 primitives. Adds Solaris x86_64 support. * 0.0.9: Force the build architecture to x86_64 for OS X. * 0.0.8: Removed overridden "scripts" section from package.json, breaking Windows installs * 0.0.7: Fix for multiple enable() calls breaking providers. * 0.0.6: Fix for segfault trying to use non-enabled probes (Mark Cavage mcavage@gmail.com) * 0.0.5: Revert changes to make probe objects available. * 0.0.4: Remove unused "sys" import (Alex Whitman) No longer builds an empty extension on non-DTrace platforms Probe objects are made available to Javascript. * 0.0.3: Builds to a stubbed-out version on non-DTrace platforms (Mark Cavage ) * 0.0.2: Solaris i386 support. Fixes memory leaks Improved performance, enabled- and disabled-probe. * 0.0.1: First working version: OSX x86_64 only. node-dtrace-provider-0.8.8/LICENCE000066400000000000000000000024021352565761500165460ustar00rootroot00000000000000Copyright 2011 Chris Andrews. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY CHRIS ANDREWS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CHRIS ANDREWS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. node-dtrace-provider-0.8.8/README.md000066400000000000000000000202571352565761500170500ustar00rootroot00000000000000# dtrace-provider - Native DTrace providers for Node.js apps. This extension allows you to create native DTrace providers for your Node.js applications. That is, to create providers and probes which expose information specific to your application, rather than information about the node runtime. You could use this to expose high-level information about the inner workings of your application, or to create a specific context in which to look at information from other runtime or system-level providers. The provider is not created in the usual way, by declaring it and then changing the build process to include it, but instead dynamically at runtime. This is done entirely in-process, and there is no background compiler or [dtrace(1M)](https://illumos.org/man/1M/dtrace) invocation. The process creating the provider need not run as root. ## INSTALL $ npm install dtrace-provider ## EXAMPLE Here's a simple example of creating a provider: ```javascript var d = require('dtrace-provider'); var dtp = d.createDTraceProvider("nodeapp"); var p1 = dtp.addProbe("probe1", "int", "int"); var p2 = dtp.addProbe("probe2", "char *"); dtp.enable(); ``` Probes may be fired via the provider object: ```javascript dtp.fire("probe1", function() { return [1, 2]; }); dtp.fire("probe2", function() { return ["hello, dtrace via provider", "foo"]; }); ``` or via the probe objects themselves: ```javascript p1.fire(function() { return [1, 2, 3, 4, 5, 6]; }); p2.fire(function() { return ["hello, dtrace via probe", "foo"]; }); ``` Note that `.fire()` takes a callback that returns the arguments to be provided when the DTrace probe actually fires. This allows you to call `.fire()` unconditionally when you want to fire the probe, but the callback will be invoked only when the DTrace probe is actually enabled. This allows you to create probes whose arguments might be expensive to construct, and only do any work when the probe is actually enabled. (Examples might include converting a large object to a string representation or gathering large amounts of information.) In some cases, creating a new closure to pass to `.fire()` each time it's called may introduce unwanted overhead. For extremely CPU-intensive or memory-conscious workloads, you can avoid this by lifting the closures for your hot probes into an outer scope. You can then supply arguments to that function as additional arguments to `.fire()`. As an example, you can convert the following program: ```javascript function manipulateObj(largeObj) { var count = 0; var name = null; ... p1.fire(function () { return [count, keyToValue(name), JSON.stringify(largeObj)]; }); } ``` Into this one: ```javascript function f(a, b, c) { return [a, keyToValue(b), JSON.stringify(c)]; } function manipulateObj(largeObj) { var count = 0; var name = null; ... p1.fire(f, count, name, largeObj); } ``` Be careful to avoid passing `.fire()` additional arguments that are themselves expensive to construct, as that undermines the design goal here: minimizing the effect of disabled probes. This example creates a provider called "nodeapp", and adds two probes. It then enables the provider, at which point the provider becomes visible to DTrace. The probes are then fired, which produces this output: $ sudo dtrace -Z -n 'nodeapp*:::probe1{ trace(arg0); trace(arg1) }' \ -n 'nodeapp*:::probe2{ trace(copyinstr(arg0)); }' dtrace: description 'nodeapp*:::probe1' matched 0 probes dtrace: description 'nodeapp*:::probe2' matched 0 probes CPU ID FUNCTION:NAME 1 123562 func:probe1 1 2 1 123563 func:probe2 hello, dtrace Arguments are captured by a callback only executed when the probe is enabled. This means you can do more expensive work to gather arguments. The maximum number of arguments supported is 32. Available argument types are "int", for integer numeric values, "char *" for strings, and "json" for objects rendered into JSON strings. Arguments typed as "json" will be created as "char *" probes in DTrace, but objects passed to these probe arguments will be automatically serialized to JSON before being passed to DTrace. This feature is best used in conjunction with the json() D subroutine, but is available whether or not the platform supports it. # create a json probe: var dtp = d.createDTraceProvider("nodeapp"); var p1 = dtp.addProbe("j1", "json"); dtp.enable(); p1.fire(function() { return { "foo": "bar" }; }); # on a platform supporting json(): $ sudo dtrace -Z -n 'nodeapp*:::j1{ this->j = copyinstr(arg0); \ trace(json(this->j, "foo")) }' dtrace: description 'nodeapp$target:::j1' matched 0 probes CPU ID FUNCTION:NAME 0 68712 j1:j1 bar ## PLATFORM SUPPORT This libusdt-based Node.JS module supports 64 and 32 bit processes on Mac OS X and Solaris-like systems such as illumos or SmartOS. As more platform support is added to libusdt, those platforms will be supported by this module. See libusdt's status at: https://github.com/chrisa/libusdt#readme When using Mac OS X, be aware that as of 10.11 (El Capitan), DTrace use is restricted, and you'll probably want to [disable SIP](http://internals.exposed/blog/dtrace-vs-sip.html) to effectively use DTrace. FreeBSD 10 and 11 are also supported, but you'll need to make sure that you have the DTrace headers installed in `/usr/src` otherwise libusdt won't be able to compile. You can [clone them using SVN](https://www.freebsd.org/doc/handbook/svn.html), or find the correct `src.txz` [here](http://ftp.freebsd.org/pub/FreeBSD/releases/) and extract that. Also note that FreeBSD 10 is restricted to only 4 working arguments per probe. Platforms not supporting DTrace (notably, Linux and Windows) may install this module without building libusdt, with a stub no-op implementation provided for compatibility. This allows cross-platform npm modules to embed probes and include a dependency on this module. GNU Make is required to build libusdt; the build scripts will look for gmake in `PATH` first, and then for make. ### TROUBLESHOOTING BUILD ISSUES If compilation fails during installation on platforms with DTrace, then the library will fall back to the stub implementation that does nothing. To force an installation failure when compiling fails, set the environment variable `NODE_DTRACE_PROVIDER_REQUIRE` to `hard`: ```shell $ NODE_DTRACE_PROVIDER_REQUIRE=hard npm install ``` This will then show you the output of the build process so you can see at which point it's having an issue. Common issues are: - Missing a C/C++ compiler toolchain for your platform. - `python` is Python 3 instead of Python 2; run `npm config set python python2.7` (or similar) to set the Python binary npm uses. - On OS X you may need to agree to the XCode license if that's the compiler toolchain you're using. This will usually manifest with an error like `Agreeing to the Xcode/iOS license requires admin privileges, please re-run as root via sudo.` To accept the license, you can run `sudo xcodebuild -license`. Once you've found and fixed the issue, you can run `npm rebuild` to rerun the lifecycle scripts. ## CAVEATS There is some overhead to probes, even when disabled. Probes are already using the "is-enabled" feature of DTrace to control execution of the arguments-gathering callback, but some work still needs to be done before that's checked. This overhead should not be a problem unless probes are placed in particularly hot code paths. ## CONTRIBUTING To clone the project's source code: $ git clone --recursive https://github.com/chrisa/node-dtrace-provider.git For issues, please use the [GitHub issue tracker](https://github.com/chrisa/node-dtrace-provider/issues) linked to the repository. GitHub pull requests are very welcome. ## RUNNING THE TESTS ```shell $ npm install $ sudo ./node_modules/.bin/tap --tap test/*.test.js ``` ## OTHER IMPLEMENTATIONS This node extension is derived from the ruby-dtrace gem, via the Perl module Devel::DTrace::Provider, both of which provide the same functionality to those languages. node-dtrace-provider-0.8.8/TODO.md000066400000000000000000000007161352565761500166560ustar00rootroot00000000000000# dtrace-provider - TODO ## FEATURES ### Structured Arguments The current support for argument types is limited to "char *" and "int", i.e. strings and integer types. Native string types in Javascript are converted to raw C strings for use with DTrace. With support for dynamic types and translators from the host DTrace implementation, it'd be possible to provide a mapping from Javascript objects to C structs, which could then be inspected in D scripts. node-dtrace-provider-0.8.8/binding.gyp000066400000000000000000000022051352565761500177150ustar00rootroot00000000000000{ 'conditions': [ # If we are on Mac OS X, FreeBSD, or a Solarish system, attempt # to build the DTrace provider extension. ['OS=="mac" or OS=="solaris" or OS=="freebsd"', { 'targets': [ { 'target_name': 'ndtp', 'type': 'none', 'actions': [{ 'inputs': [''], 'outputs': [''], 'action_name': 'build_ndtp', 'action': [ 'bash', 'build.sh' ] }] } ] }, # If we are on another system (like Windows or Linux), then DTrace is # unavailable. This target is necessary because GYP requires at least # one target to exist. We end up building nothing, and fall back to the # stub implementation when the package is loaded. { 'targets': [ { 'target_name': 'DTraceProviderStub', 'type': 'none' } ] }] ] } node-dtrace-provider-0.8.8/build.sh000066400000000000000000000044371352565761500172260ustar00rootroot00000000000000#!/usr/bin/env bash set -o pipefail if [[ -n "$V" ]]; then set -o xtrace fi fail() { if [[ -z "$NODE_DTRACE_PROVIDER_REQUIRE" && -z "$V" ]]; then echo "-----------------------------------------------------------------" echo "Building dtrace-provider failed with exit code $1, falling back" echo "on stub implementation." echo "" echo "Re-run install with V set in your environment to see the build" echo "output, or NODE_DTRACE_PROVIDER_REQUIRE=hard to force an" echo "installation failure." echo "-----------------------------------------------------------------" fi if [[ "$NODE_DTRACE_PROVIDER_REQUIRE" == "hard" ]]; then exit 1 else exit 0 fi } buildUSDT() { if [[ -z "$NODE_DTRACE_PROVIDER_REQUIRE" && -z "$V" ]]; then exec 1> /dev/null exec 2> /dev/null fi # GYP's MAKEFLAGS confuses libusdt's Makefile unset MAKEFLAGS # Ask node what architecture it's been built for ("target_arch" in # config.gypi), and build libusdt to match. # # We use node from the path; npm will have adjusted PATH for us if # necessary, otherwise we assume the user did so when building by # hand. # # (This will need to change at the point that GYP is able to build # node extensions universal on the Mac - for now we'll go with x86_64 # on a 64 bit Mac, because that's the default architecture in that # situation.) export ARCH=`node -e "console.log(process.arch === 'x64' ? 'x86_64' : 'i386')"` echo "Building libusdt for ${ARCH}" # Respect a MAKE variable if set if [[ -z $MAKE ]]; then # Default to `gmake` first if available, because we require GNU make # and `make` isn't GNU make on some plats. MAKE=`which gmake` if [[ -z $MAKE ]]; then MAKE=make fi fi # Build libusdt. $MAKE -C libusdt clean all } buildNDTP() { if [[ -z "$NODE_DTRACE_PROVIDER_REQUIRE" && -z "$V" ]]; then exec 1> /dev/null exec 2> /dev/null fi node-gyp rebuild -C src } (buildUSDT) LIBUSDT_STATUS=$? if [[ "$LIBUSDT_STATUS" -ne 0 ]]; then fail $LIBUSDT_STATUS fi (buildNDTP) NODE_GYP_STATUS=$? if [[ "$NODE_GYP_STATUS" -ne 0 ]]; then fail $NODE_GYP_STATUS fi exit 0 node-dtrace-provider-0.8.8/dtrace-provider.js000066400000000000000000000021261352565761500212140ustar00rootroot00000000000000var DTraceProvider; function DTraceProviderStub() {} DTraceProviderStub.prototype.addProbe = function(name) { var p = { 'fire': function () {} }; this[name] = p; return (p); }; DTraceProviderStub.prototype.enable = function() {}; DTraceProviderStub.prototype.fire = function() {}; DTraceProviderStub.prototype.disable = function() {}; var builds = ['Release', 'default', 'Debug']; var err = null; for (var i = 0; i < builds.length; i++) { try { var binding = require('./src/build/' + builds[i] + '/DTraceProviderBindings'); DTraceProvider = binding.DTraceProvider; break; } catch (e) { if (err === null) { err = e; } } } if (!DTraceProvider) { if (process.env.NODE_DTRACE_PROVIDER_REQUIRE === 'hard') { throw err; } else { DTraceProvider = DTraceProviderStub; } } exports.DTraceProvider = DTraceProvider; exports.createDTraceProvider = function(name, module) { if (arguments.length == 2) return (new exports.DTraceProvider(name, module)); return (new exports.DTraceProvider(name)); }; node-dtrace-provider-0.8.8/libusdt/000077500000000000000000000000001352565761500172315ustar00rootroot00000000000000node-dtrace-provider-0.8.8/package.json000066400000000000000000000013411352565761500200500ustar00rootroot00000000000000{ "name": "dtrace-provider", "version": "0.8.8", "description": "Native DTrace providers for node.js applications", "keywords": [ "dtrace", "usdt" ], "homepage": "https://github.com/chrisa/node-dtrace-provider#readme", "license": "BSD-2-Clause", "author": { "name": "Chris Andrews", "email": "chris@nodnol.org" }, "repository": { "type": "git", "url": "https://github.com/chrisa/node-dtrace-provider.git" }, "engines": { "node": ">=0.10" }, "dependencies": { "nan": "^2.14.0" }, "devDependencies": { "tap": "0.7.1" }, "scripts": { "install": "node-gyp rebuild || node suppress-error.js", "test": "tap test/*.test.js" }, "main": "./dtrace-provider.js" } node-dtrace-provider-0.8.8/src/000077500000000000000000000000001352565761500163525ustar00rootroot00000000000000node-dtrace-provider-0.8.8/src/binding.gyp000066400000000000000000000026231352565761500205100ustar00rootroot00000000000000{ 'conditions' : [ ['OS=="mac" or OS=="solaris"', { 'variables': { 'escaped_root': ' namespace node { using namespace v8; // Integer Argument #ifdef __x86_64__ # define INTMETHOD int64_t #else # define INTMETHOD int32_t #endif void * DTraceIntegerArgument::ArgumentValue(v8::Local value) { if (value->IsUndefined()) return 0; else return (void *)(long) Nan::To(value).FromJust(); } void DTraceIntegerArgument::FreeArgument(void *arg) { } const char * DTraceIntegerArgument::Type() { return "int"; } // String Argument void * DTraceStringArgument::ArgumentValue(v8::Local value) { if (value->IsUndefined()) return (void *) strdup("undefined"); Nan::Utf8String str(value); return (void *) strdup(*str); } void DTraceStringArgument::FreeArgument(void *arg) { free(arg); } const char * DTraceStringArgument::Type() { return "char *"; } // JSON Argument DTraceJsonArgument::DTraceJsonArgument() { Nan::HandleScope scope; v8::Local context = Nan::GetCurrentContext(); v8::Local global = context->Global(); v8::Local json = Nan::New("JSON").ToLocalChecked(); v8::Local l_JSON = Nan::To(global->Get(json)).ToLocalChecked(); v8::Local l_JSON_stringify = v8::Local::Cast(l_JSON->Get(Nan::New("stringify").ToLocalChecked())); JSON.Reset(l_JSON); JSON_stringify.Reset(l_JSON_stringify); } DTraceJsonArgument::~DTraceJsonArgument() { JSON.Reset(); JSON_stringify.Reset(); } void * DTraceJsonArgument::ArgumentValue(v8::Local value) { Nan::HandleScope scope; if (value->IsUndefined()) return (void *) strdup("undefined"); v8::Local info[1]; info[0] = value; v8::Local cb = Nan::New(JSON_stringify); v8::Local obj = Nan::New(JSON); Local j = Nan::Call(cb, obj, 1, info).ToLocalChecked(); if (*j == NULL) return (void *) strdup("{ \"error\": \"stringify failed\" }"); Nan::Utf8String json(j); return (void *) strdup(*json); } void DTraceJsonArgument::FreeArgument(void *arg) { free(arg); } const char * DTraceJsonArgument::Type() { return "char *"; } } // namespace node node-dtrace-provider-0.8.8/src/dtrace_probe.cc000066400000000000000000000055751352565761500213260ustar00rootroot00000000000000#include "dtrace_provider.h" #include namespace node { using namespace v8; DTraceProbe::DTraceProbe() : Nan::ObjectWrap() { argc = 0; probedef = NULL; } DTraceProbe::~DTraceProbe() { for (size_t i = 0; i < argc; i++) delete(this->arguments[i]); usdt_probe_release(probedef); } Nan::Persistent DTraceProbe::constructor_template; void DTraceProbe::Initialize(v8::Local target) { Nan::HandleScope scope; Local t = Nan::New(DTraceProbe::New); t->InstanceTemplate()->SetInternalFieldCount(2); t->SetClassName(Nan::New("DTraceProbe").ToLocalChecked()); constructor_template.Reset(t); Nan::SetPrototypeMethod(t, "fire", DTraceProbe::Fire); target->Set(Nan::New("DTraceProbe").ToLocalChecked(), Nan::GetFunction(t).ToLocalChecked()); } NAN_METHOD(DTraceProbe::New) { Nan::HandleScope scope; DTraceProbe *probe = new DTraceProbe(); probe->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } NAN_METHOD(DTraceProbe::Fire) { Nan::HandleScope scope; if (!info[0]->IsFunction()) { Nan::ThrowTypeError("Must give probe value callback as first argument"); return; } DTraceProbe *pd = Nan::ObjectWrap::Unwrap(info.Holder()); info.GetReturnValue().Set(pd->_fire(info, 0)); } v8::Local DTraceProbe::_fire(Nan::NAN_METHOD_ARGS_TYPE argsinfo, size_t fnidx) { Nan::HandleScope scope; if (usdt_is_enabled(this->probedef->probe) == 0) { return Nan::Undefined(); } // invoke fire callback Nan::TryCatch try_catch; size_t cblen = argsinfo.Length() - fnidx - 1; Local *cbargs = new Local[cblen]; for (size_t i = 0; i < cblen; i++) { cbargs[i] = argsinfo[i + fnidx + 1]; } Local cb = Local::Cast(argsinfo[fnidx]); Nan::MaybeLocal maybe = Nan::Call(cb, this->handle(), cblen, cbargs); if (maybe.IsEmpty()) { Nan::ThrowTypeError("Failed to invoke fire callback"); return Nan::Undefined(); } Local probe_args = maybe.ToLocalChecked(); delete [] cbargs; // exception in args callback? if (try_catch.HasCaught()) { Nan::FatalException(try_catch); return Nan::Undefined(); } // check return if (!probe_args->IsArray()) { return Nan::Undefined(); } Local a = Local::Cast(probe_args); void *argv[USDT_ARG_MAX]; // convert each argument value for (size_t i = 0; i < argc; i++) { argv[i] = this->arguments[i]->ArgumentValue(a->Get(i)); } // finally fire the probe usdt_fire_probe(this->probedef->probe, argc, argv); // free argument values for (size_t i = 0; i < argc; i++) { this->arguments[i]->FreeArgument(argv[i]); } return Nan::True(); } } // namespace node node-dtrace-provider-0.8.8/src/dtrace_provider.cc000066400000000000000000000152001352565761500220330ustar00rootroot00000000000000#include "dtrace_provider.h" #include #include namespace node { using namespace v8; DTraceProvider::DTraceProvider() : Nan::ObjectWrap() { provider = NULL; } DTraceProvider::~DTraceProvider() { usdt_provider_disable(provider); usdt_provider_free(provider); } Nan::Persistent DTraceProvider::constructor_template; void DTraceProvider::Initialize(v8::Local target) { Nan::HandleScope scope; Local t = Nan::New(DTraceProvider::New); t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(Nan::New("DTraceProvider").ToLocalChecked()); constructor_template.Reset(t); Nan::SetPrototypeMethod(t, "addProbe", DTraceProvider::AddProbe); Nan::SetPrototypeMethod(t, "removeProbe", DTraceProvider::RemoveProbe); Nan::SetPrototypeMethod(t, "enable", DTraceProvider::Enable); Nan::SetPrototypeMethod(t, "disable", DTraceProvider::Disable); Nan::SetPrototypeMethod(t, "fire", DTraceProvider::Fire); target->Set(Nan::New("DTraceProvider").ToLocalChecked(), Nan::GetFunction(t).ToLocalChecked()); DTraceProbe::Initialize(target); } NAN_METHOD(DTraceProvider::New) { Nan::HandleScope scope; DTraceProvider *p = new DTraceProvider(); char module[128]; p->Wrap(info.This()); if (info.Length() < 1 || !info[0]->IsString()) { Nan::ThrowTypeError("Must give provider name as argument"); return; } Nan::Utf8String name(info[0]); if (info.Length() == 2) { if (!info[1]->IsString()) { Nan::ThrowTypeError("Must give module name as argument"); return; } Nan::Utf8String mod(info[1]); (void) snprintf(module, sizeof (module), "%s", *mod); } else if (info.Length() == 1) { // If no module name is provided, develop a synthetic module name based // on our address (void) snprintf(module, sizeof (module), "mod-%p", p); } else { Nan::ThrowError("Expected only provider name and module as arguments"); return; } if ((p->provider = usdt_create_provider(*name, module)) == NULL) { Nan::ThrowError("usdt_create_provider failed"); return; } info.GetReturnValue().Set(info.This()); } NAN_METHOD(DTraceProvider::AddProbe) { Nan::HandleScope scope; const char *types[USDT_ARG_MAX]; v8::Local obj = info.Holder(); DTraceProvider *provider = Nan::ObjectWrap::Unwrap(obj); // create a DTraceProbe object v8::Local tmpl = Nan::New(DTraceProbe::constructor_template); v8::Local klass = Nan::GetFunction(tmpl).ToLocalChecked(); v8::Local pd = Nan::NewInstance(klass).ToLocalChecked(); // store in provider object DTraceProbe *probe = Nan::ObjectWrap::Unwrap(Nan::To(pd).ToLocalChecked()); obj->Set(Nan::To(info[0]).ToLocalChecked(), pd); // reference the provider to avoid GC'ing it when only probes remain in scope. Nan::DefineOwnProperty(pd, Nan::New("__prov__").ToLocalChecked(), obj, static_cast(DontEnum | ReadOnly | DontDelete)); // add probe to provider for (int i = 0; i < USDT_ARG_MAX; i++) { if (i < info.Length() - 1) { Nan::Utf8String type(info[i + 1]); if (strncmp("json", *type, 4) == 0) probe->arguments[i] = new DTraceJsonArgument(); else if (strncmp("char *", *type, 6) == 0) probe->arguments[i] = new DTraceStringArgument(); else if (strncmp("int", *type, 3) == 0) probe->arguments[i] = new DTraceIntegerArgument(); else probe->arguments[i] = new DTraceStringArgument(); types[i] = strdup(probe->arguments[i]->Type()); probe->argc++; } } Nan::Utf8String name(info[0]); probe->probedef = usdt_create_probe(*name, *name, probe->argc, types); Nan::SetInternalFieldPointer(pd, 1, provider); usdt_provider_add_probe(provider->provider, probe->probedef); for (size_t i = 0; i < probe->argc; i++) { free((char *)types[i]); } info.GetReturnValue().Set(pd); } NAN_METHOD(DTraceProvider::RemoveProbe) { Nan::HandleScope scope; v8::Local provider_obj = info.Holder(); DTraceProvider *provider = Nan::ObjectWrap::Unwrap(provider_obj); v8::Local probe_obj = Local::Cast(info[0]); DTraceProbe *probe = Nan::ObjectWrap::Unwrap(probe_obj); v8::Local name = Nan::New(probe->probedef->name).ToLocalChecked(); Nan::Delete(provider_obj, name); if (usdt_provider_remove_probe(provider->provider, probe->probedef) != 0) { Nan::ThrowError(usdt_errstr(provider->provider)); return; } info.GetReturnValue().Set(Nan::True()); } NAN_METHOD(DTraceProvider::Enable) { Nan::HandleScope scope; DTraceProvider *provider = Nan::ObjectWrap::Unwrap(info.Holder()); if (usdt_provider_enable(provider->provider) != 0) { Nan::ThrowError(usdt_errstr(provider->provider)); return; } return; } NAN_METHOD(DTraceProvider::Disable) { Nan::HandleScope scope; DTraceProvider *provider = Nan::ObjectWrap::Unwrap(info.Holder()); if (usdt_provider_disable(provider->provider) != 0) { Nan::ThrowError(usdt_errstr(provider->provider)); return; } return; } NAN_METHOD(DTraceProvider::Fire) { Nan::HandleScope scope; if (!info[0]->IsString()) { Nan::ThrowTypeError("Must give probe name as first argument"); return; } if (!info[1]->IsFunction()) { Nan::ThrowTypeError("Must give probe value callback as second argument"); return; } v8::Local holder = info.Holder(); DTraceProvider *provider = Nan::ObjectWrap::Unwrap(holder); Nan::MaybeLocal maybe = Nan::Get(holder, info[0]); if (maybe.IsEmpty()) { return; } v8::Local value = maybe.ToLocalChecked(); if (!value->IsObject()) { return; } v8::Local probe = Local::Cast(value); if (probe->InternalFieldCount() != 2) { return; } if (Nan::GetInternalFieldPointer(probe, 1) != provider) { return; } DTraceProbe *p = Nan::ObjectWrap::Unwrap(probe); if (p == NULL) { return; } p->_fire(info, 1); info.GetReturnValue().Set(Nan::True()); } extern "C" void init(v8::Local target) { DTraceProvider::Initialize(target); } NODE_MODULE(DTraceProviderBindings, init) } // namespace node node-dtrace-provider-0.8.8/src/dtrace_provider.h000066400000000000000000000042421352565761500217010ustar00rootroot00000000000000#include #include extern "C" { #include } #include #include #include #include #include #include #include #ifndef __APPLE__ #include #ifndef __FreeBSD__ #include #endif #endif namespace node { using namespace v8; class DTraceArgument { public: virtual const char *Type() = 0; virtual void *ArgumentValue(v8::Local) = 0; virtual void FreeArgument(void *) = 0; virtual ~DTraceArgument() { }; }; class DTraceIntegerArgument : public DTraceArgument { public: const char *Type(); void *ArgumentValue(v8::Local); void FreeArgument(void *); }; class DTraceStringArgument : public DTraceArgument { public: const char *Type(); void *ArgumentValue(v8::Local); void FreeArgument(void *); }; class DTraceJsonArgument : public DTraceArgument { public: const char *Type(); void *ArgumentValue(v8::Local); void FreeArgument(void *); DTraceJsonArgument(); ~DTraceJsonArgument(); private: Nan::Persistent JSON; Nan::Persistent JSON_stringify; }; class DTraceProbe : public Nan::ObjectWrap { public: static void Initialize(v8::Local target); usdt_probedef_t *probedef; size_t argc; DTraceArgument *arguments[USDT_ARG_MAX]; static NAN_METHOD(New); static NAN_METHOD(Fire); v8::Local _fire(Nan::NAN_METHOD_ARGS_TYPE, size_t); static Nan::Persistent constructor_template; DTraceProbe(); ~DTraceProbe(); private: }; class DTraceProvider : public Nan::ObjectWrap { public: static void Initialize(v8::Local target); usdt_provider_t *provider; static NAN_METHOD(New); static NAN_METHOD(AddProbe); static NAN_METHOD(RemoveProbe); static NAN_METHOD(Enable); static NAN_METHOD(Disable); static NAN_METHOD(Fire); DTraceProvider(); ~DTraceProvider(); private: static Nan::Persistent constructor_template; }; void InitDTraceProvider(v8::Local target); } node-dtrace-provider-0.8.8/suppress-error.js000066400000000000000000000022671352565761500211430ustar00rootroot00000000000000/** * During `npm install`, we run: * * node-gyp rebuild || node suppress-error.js * * (Note that this expression is written to work on *nix and Windows.) * * When we run node-gyp, we detect whether or not we're on a supported platform, * and either compile the node addon or exit having done nothing. It's possible * for the platform to lack the requirements to run node-gyp though (such as * Python 2, make, Visual C++ Build Tools, and so on), in which case we fall * back onto this script. * * If NODE_DTRACE_PROVIDER_REQUIRE is set to "hard", then we want to propagate * the failure and stop the install. Otherwise, we want to suppress it and * allow the program to fall back onto the stub code. * * There is one case where we might stop an install and not want to: on Debian * and Ubuntu, where the binary is named "nodejs" instead of "node", the * fallback will fail to run. There doesn't really seem to be a great way to * handle this scenario, so users on those systems will need to either install * node-gyp's requirements or set up a "node" symbolic link. */ if (process.env.NODE_DTRACE_PROVIDER_REQUIRE === 'hard') { process.exit(1); } else { process.exit(0); } node-dtrace-provider-0.8.8/test/000077500000000000000000000000001352565761500165425ustar00rootroot00000000000000node-dtrace-provider-0.8.8/test/32probe-char.test.js000066400000000000000000000104141352565761500222450ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; if (process.platform == 'darwin') { var dscript = 'testlibusdt*:::32probe{ printf("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\\n", copyinstr((user_addr_t)args[0]), copyinstr((user_addr_t)args[1]), copyinstr((user_addr_t)args[2]), copyinstr((user_addr_t)args[3]), copyinstr((user_addr_t)args[4]), copyinstr((user_addr_t)args[5]), copyinstr((user_addr_t)args[6]), copyinstr((user_addr_t)args[7]), copyinstr((user_addr_t)args[8]), copyinstr((user_addr_t)args[9]), copyinstr((user_addr_t)args[10]), copyinstr((user_addr_t)args[11]), copyinstr((user_addr_t)args[12]), copyinstr((user_addr_t)args[13]), copyinstr((user_addr_t)args[14]), copyinstr((user_addr_t)args[15]), copyinstr((user_addr_t)args[16]), copyinstr((user_addr_t)args[17]), copyinstr((user_addr_t)args[18]), copyinstr((user_addr_t)args[19]), copyinstr((user_addr_t)args[20]), copyinstr((user_addr_t)args[21]), copyinstr((user_addr_t)args[22]), copyinstr((user_addr_t)args[23]), copyinstr((user_addr_t)args[24]), copyinstr((user_addr_t)args[25]), copyinstr((user_addr_t)args[26]), copyinstr((user_addr_t)args[27]), copyinstr((user_addr_t)args[28]), copyinstr((user_addr_t)args[29]), copyinstr((user_addr_t)args[30]), copyinstr((user_addr_t)args[31])); }'; } else { var dscript = 'testlibusdt*:::32probe{ printf("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\\n", copyinstr((uintptr_t)args[0]), copyinstr((uintptr_t)args[1]), copyinstr((uintptr_t)args[2]), copyinstr((uintptr_t)args[3]), copyinstr((uintptr_t)args[4]), copyinstr((uintptr_t)args[5]), copyinstr((uintptr_t)args[6]), copyinstr((uintptr_t)args[7]), copyinstr((uintptr_t)args[8]), copyinstr((uintptr_t)args[9]), copyinstr((uintptr_t)args[10]), copyinstr((uintptr_t)args[11]), copyinstr((uintptr_t)args[12]), copyinstr((uintptr_t)args[13]), copyinstr((uintptr_t)args[14]), copyinstr((uintptr_t)args[15]), copyinstr((uintptr_t)args[16]), copyinstr((uintptr_t)args[17]), copyinstr((uintptr_t)args[18]), copyinstr((uintptr_t)args[19]), copyinstr((uintptr_t)args[20]), copyinstr((uintptr_t)args[21]), copyinstr((uintptr_t)args[22]), copyinstr((uintptr_t)args[23]), copyinstr((uintptr_t)args[24]), copyinstr((uintptr_t)args[25]), copyinstr((uintptr_t)args[26]), copyinstr((uintptr_t)args[27]), copyinstr((uintptr_t)args[28]), copyinstr((uintptr_t)args[29]), copyinstr((uintptr_t)args[30]), copyinstr((uintptr_t)args[31])); }'; } var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("testlibusdt"); test( '32-arg probe', dtest( function() { /* * We define the probe here, even though we won't fire it. We do * this because we index into the args[] array in our D script, and * DTrace wants to verify the types of the probe arguments, which * means -Z won't work here. */ var p = provider.addProbe( "32probe", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *"); provider.enable(); }, ['dtrace', '-qn', dscript, '-c', format('node %s/32probe-char_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces.length, 1); var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F']; var traced = traces[0].split(' '); for (var i = 0; i < 32; i++) { t.equal(traced[i], letters[i], format('arg%d of a 32-arg probe firing should be %s', i, letters[i])); } provider.disable(); } ) ); node-dtrace-provider-0.8.8/test/32probe-char_fire.js000066400000000000000000000014361352565761500223000ustar00rootroot00000000000000// see 32probe-char.test.js var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("testlibusdt"); var probe = provider.addProbe( "32probe", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *", "char *"); provider.enable(); var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F']; probe.fire(function(p) { return letters; }); node-dtrace-provider-0.8.8/test/32probe.test.js000066400000000000000000000042651352565761500213410ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("testlibusdt"); test( '32-arg probe', dtest( function() { /* * We define the probe here, even though we won't fire it. We do * this because we index into the args[] array in our D script, and * DTrace wants to verify the types of the probe arguments, which * means -Z won't work here. */ var probe = provider.addProbe("32probe", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int"); provider.enable(); }, ['dtrace', '-qn', 'testlibusdt*:::32probe{ printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\\n", args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15], args[16], args[17], args[18], args[19], args[20], args[21], args[22], args[23], args[24], args[25], args[26], args[27], args[28], args[29], args[30], args[31]) }', '-c', format('node %s/32probe_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces.length, 32, 'got 32 traces'); var args = []; for (var i = 1; i <= 32; i++) { args.push(i); var traced = traces[i - 1].split(' '); args.forEach(function(n) { t.equal(traced[n - 1], [n].toString(), format('arg%d of a %d-arg probe firing should be %d', n - 1, i, n)); }); } provider.disable(); } ) ); node-dtrace-provider-0.8.8/test/32probe_fire.js000066400000000000000000000010471352565761500213630ustar00rootroot00000000000000// see 32probe.test.js var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("testlibusdt"); var probe = provider.addProbe( "32probe", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int", "int"); provider.enable(); var args = []; for (var n = 1; n <= 32; n++) { args.push(n); probe.fire(function(p) { return args; }); } node-dtrace-provider-0.8.8/test/add-probes.test.js000066400000000000000000000014751352565761500221050ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'adding probes to an existing provider', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp*:::{ printf("%d\\n", arg0); }', '-c', format('node %s/add-probes_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces.length, 46); traces.sort(function(a, b) { return a - b }); t.equal(traces[0], '0'); var x = 1; for (var i = 1; i < 10; i++) { for (var j = 0; j < i; j++) { t.equal(traces[x++], [i].toString()); } } } ) ); node-dtrace-provider-0.8.8/test/add-probes_fire.js000066400000000000000000000006031352565761500221240ustar00rootroot00000000000000var d = require('../dtrace-provider'); var dtp = d.createDTraceProvider("nodeapp"); dtp.addProbe("probe0", "int"); dtp.enable(); dtp.fire("probe0", function(p) { return [0]; }); for (var i = 1; i < 10; i++) { dtp.addProbe("probe" + i, "int"); dtp.disable(); dtp.enable(); for (var j = 0; j < i; j++) { dtp.fire("probe" + j, function(p) { return [i]; }); } } node-dtrace-provider-0.8.8/test/args-after-cb-1.test.js000066400000000000000000000012671352565761500226370ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'probes where .fire() is called with arguments to pass to the callback', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::after1{ printf("%d\\n%s\\n%d\\n", arg0, copyinstr(arg1), arg2); }', '-c', format('node %s/args-after-cb-1_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], '42'); t.equal(traces[1], 'forty-two'); t.equal(traces[2], '15'); } ) ); node-dtrace-provider-0.8.8/test/args-after-cb-1_fire.js000066400000000000000000000004311352565761500226560ustar00rootroot00000000000000var d = require('../dtrace-provider'); var provider = d.createDTraceProvider('nodeapp'); var probe = provider.addProbe('after1', 'int', 'char *', 'int'); provider.enable(); function fireCb(n1, str2, n2) { return [n1, str2, n2 + 5]; } probe.fire(fireCb, 42, 'forty-two', 10); node-dtrace-provider-0.8.8/test/args-after-cb-2.test.js000066400000000000000000000012721352565761500226340ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'providers where .fire() is called with arguments to pass to the callback', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::after1{ printf("%d\\n%s\\n%d\\n", arg0, copyinstr(arg1), arg2); }', '-c', format('node %s/args-after-cb-2_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], '42'); t.equal(traces[1], 'forty-two'); t.equal(traces[2], '15'); } ) ); node-dtrace-provider-0.8.8/test/args-after-cb-2_fire.js000066400000000000000000000004301352565761500226560ustar00rootroot00000000000000var d = require('../dtrace-provider'); var provider = d.createDTraceProvider('nodeapp'); provider.addProbe('after1', 'int', 'char *', 'int'); provider.enable(); function fireCb(n1, str, n2) { return [n1, str, n2 + 5]; } provider.fire('after1', fireCb, 42, 'forty-two', 10); node-dtrace-provider-0.8.8/test/bad-probe.test.js000066400000000000000000000014241352565761500217120ustar00rootroot00000000000000var test = require('tap').test; var fmt = require('util').format; var d = require('../dtrace-provider'); test('firing non-existent probes', function (t) { var provider = d.createDTraceProvider("nodeapp"); provider['typenull'] = null; provider['typeobj1'] = {}; provider['typeobj2'] = { fire: 5 }; provider['typenan'] = provider; provider['typenum'] = 10; function cb(p) { return [1, 2, 3, 4]; } function tryName(name) { provider.fire(name, cb); t.pass(fmt('fire("%s", cb) should not raise SIGABRT', name)); } tryName('kaboom'); tryName('fire'); tryName('toString'); tryName('typenull'); tryName('typeobj1'); tryName('typeobj2'); tryName('typenan'); tryName('typenum'); t.end(); }); node-dtrace-provider-0.8.8/test/basic.test.js000066400000000000000000000011221352565761500211330ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'basic probes', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::p1{ printf("%d\\n", arg0); printf("%s\\n", copyinstr(arg1)) }', '-c', format('node %s/basic_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], '42'); t.equal(traces[1], 'forty-two'); } ) ); node-dtrace-provider-0.8.8/test/basic_fire.js000066400000000000000000000003361352565761500211700ustar00rootroot00000000000000var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("nodeapp"); var probe = provider.addProbe("p1", "int", "char *"); provider.enable(); probe.fire(function(p) { return [42, 'forty-two']; }); node-dtrace-provider-0.8.8/test/create-destroy.test.js000066400000000000000000000012741352565761500230140ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'creating and destroying a provider', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp*:::{ printf("%d\\n", arg0); }', '-c', format('node %s/create-destroy_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces.length, 10); traces.sort(function(a, b) { return a - b }); for (var i = 0; i < 10; i++) { t.equal(traces[i], [i].toString()); } } ) ); node-dtrace-provider-0.8.8/test/create-destroy_fire.js000066400000000000000000000004071352565761500230400ustar00rootroot00000000000000var d = require('../dtrace-provider'); for (var i = 0; i < 10; i++) { //gc(); var dtp = d.createDTraceProvider("nodeapp"); dtp.addProbe("probe1", "int"); dtp.enable(); dtp.fire("probe1", function(p) { return [i]; }); //dtp.disable(); } node-dtrace-provider-0.8.8/test/disambiguation.test.js000066400000000000000000000013151352565761500230550ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'module name disambiguation', dtest( function() { }, [ 'dtrace', '-Zqn', 'test*:::{printf("%s\\n%s\\n", probename, probemod)}', '-c', format('node %s/disambiguation_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces.length, 8); t.equal(traces[0], traces[2]); t.notEqual(traces[1], traces[3]); t.equal(traces[4], traces[6]); t.notEqual(traces[5], traces[7]); } ) ); node-dtrace-provider-0.8.8/test/disambiguation_fire.js000066400000000000000000000015201352565761500231020ustar00rootroot00000000000000var d = require('../dtrace-provider'); var dtp = d.createDTraceProvider('test'); dtp.addProbe('probe1', 'int', 'int'); dtp.addProbe('probe2', 'int', 'int'); dtp.enable(); var dtp2 = d.createDTraceProvider('test'); dtp2.addProbe('probe3', 'int', 'int'); dtp2.addProbe('probe1', 'int', 'int'); dtp2.enable(); var dtp3 = d.createDTraceProvider('test', 'mymod1'); dtp3.addProbe('probe1', 'int', 'int'); dtp3.addProbe('probe2', 'int', 'int'); dtp3.enable(); var dtp4 = d.createDTraceProvider('test', 'mymod2'); dtp4.addProbe('probe1', 'int', 'int'); dtp4.addProbe('probe3', 'int', 'int'); dtp4.enable(); dtp.fire('probe1', function () { return ([12, 3]); }); dtp2.fire('probe1', function () { return ([12, 73]); }); dtp3.fire('probe1', function () { return ([12, 3]); }); dtp4.fire('probe1', function () { return ([12, 73]); }); node-dtrace-provider-0.8.8/test/dtrace-test.js000066400000000000000000000016111352565761500213160ustar00rootroot00000000000000var spawn = require('child_process').spawn; exports.dtraceTest = function(setup, dtargv, test) { return function(t) { setup(); var dtrace = spawn('/usr/sbin/dtrace', dtargv.slice(1)); var traces = []; var exit_code; dtrace.stdout.on('data', function (data) { //console.error("DTRACE STDOUT:", data.toString()); traces.push(data.toString()); }); dtrace.stderr.on('data', function (data) { //console.error("DTRACE STDERR:", data.toString()); }); dtrace.on('exit', function (code) { exit_code = code; }); dtrace.on('close', function () { traces = traces.join('').split('\n') .filter(function (t) { return t.trim().length }); test(t, exit_code, traces); t.end(); }); }; } node-dtrace-provider-0.8.8/test/enabled-disabled.test.js000066400000000000000000000012761352565761500232230ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'enabling and disabling a provider', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp*:::{ printf("%d\\n", arg0); }', '-c', format('node %s/enabled-disabled_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces.length, 11); traces.sort(function(a, b) { return a - b }); for (var i = 0; i < 10; i++) { t.equal(traces[i], [i].toString()); } } ) ); node-dtrace-provider-0.8.8/test/enabled-disabled_fire.js000066400000000000000000000005561352565761500232520ustar00rootroot00000000000000var d = require('../dtrace-provider'); var dtp = d.createDTraceProvider("nodeapp"); dtp.addProbe("probe1", "int"); dtp.enable(); dtp.fire("probe1", function(p) { return [0]; }); for (var i = 1; i <= 10; i++) { dtp.enable(); dtp.fire("probe1", function(p) { return [i]; }); dtp.disable(); //gc(); } dtp.fire("probe1", function(p) { return [42]; }); node-dtrace-provider-0.8.8/test/enabledagain.test.js000066400000000000000000000017471352565761500224610ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'provider enabled again', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::{ printf("%d %d\\n", epid, arg0); }', '-c', format('node %s/enabledagain_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces.length, 2, 'got 2 traces'); var i = 1; var epid; traces.forEach(function(trace) { cols = trace.split(' '); t.equal([i].toString(), cols[1], 'traced value correct'); if (epid) { t.equal(epid, cols[0], 'same epid'); } else { epid = cols[0]; } i++; }); } ) ); node-dtrace-provider-0.8.8/test/enabledagain_fire.js000066400000000000000000000003611352565761500224770ustar00rootroot00000000000000var d = require('../dtrace-provider'); var dtp = d.createDTraceProvider("nodeapp"); dtp.addProbe("probe1", "int"); dtp.enable(); dtp.fire("probe1", function(p) { return [1]; }); dtp.enable(); dtp.fire("probe1", function(p) { return [2]; }); node-dtrace-provider-0.8.8/test/fewer-args-json.test.js000066400000000000000000000011771352565761500230750ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'firing JSON probe with too few arguments', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::p1{ printf("%s\\n%s\\n", copyinstr(arg0), copyinstr(arg1)); }', '-c', format('node %s/fewer-args-json_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], '{"foo":1}'); t.equal(traces[1], 'undefined'); } ) ); node-dtrace-provider-0.8.8/test/fewer-args-json_fire.js000066400000000000000000000003321352565761500231140ustar00rootroot00000000000000var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("nodeapp"); var probe = provider.addProbe("p1", "json", "json"); provider.enable(); probe.fire(function(p) { return [{ "foo": 1 }]; }); node-dtrace-provider-0.8.8/test/fewer-args.test.js000066400000000000000000000012231352565761500221160ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'firing probe with too few arguments', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::p1{ printf("%d\\n%d\\n%s\\n", arg0, arg1, copyinstr(arg2)); }', '-c', format('node %s/fewer-args_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], '42'); t.equal(traces[1], '0'); t.equal(traces[2], 'undefined'); } ) ); node-dtrace-provider-0.8.8/test/fewer-args_fire.js000066400000000000000000000003301352565761500221430ustar00rootroot00000000000000var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("nodeapp"); var probe = provider.addProbe("p1", "int", "int", "char *"); provider.enable(); probe.fire(function(p) { return [42]; }); node-dtrace-provider-0.8.8/test/gc-provider.test.js000066400000000000000000000011041352565761500222730ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'check provider object is not GC\'d while probe exists', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::gcprobe{ printf("%d\\n", arg0); }', '-c', format('node --expose_gc %s/gc-provider_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], '5'); } ) ); node-dtrace-provider-0.8.8/test/gc-provider_fire.js000066400000000000000000000005201352565761500223230ustar00rootroot00000000000000var d = require('../dtrace-provider'); function mkProbe() { var dtp = d.createDTraceProvider("nodeapp"); var probe = dtp.addProbe("gcprobe", "int"); dtp.enable(); return probe; } var p1 = mkProbe(); // run GC gc(); // if the provider were GC'd, the USDT probes will be gone. p1.fire(function() { return [ 5 ]; }); node-dtrace-provider-0.8.8/test/gc.js000066400000000000000000000011441352565761500174710ustar00rootroot00000000000000// expected output: // // $ sudo dtrace -Zn 'nodeapp*:::gcprobe{ trace(arg0); }' -c 'node --expose_gc test/gc.js' // Dtrace: description 'nodeapp*:::gcprobe' matched 0 probes // dtrace: pid 66257 has exited // CPU ID FUNCTION:NAME // 1 1778 gcprobe:gcprobe 4320227343 var d = require('../dtrace-provider'); var dtp = d.createDTraceProvider("nodeapp"); // don't assign the returned probe object anywhere dtp.addProbe("gcprobe", "int"); dtp.enable(); // run GC gc(); // probe object should still be around dtp.fire("gcprobe", function() { return []; }); node-dtrace-provider-0.8.8/test/gc.test.js000066400000000000000000000010701352565761500204450ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'check probe object is not GCd while provider exists', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::gcprobe{ printf("%d\\n", arg0); }', '-c', format('node --expose_gc %s/gc_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], '0'); } ) ); node-dtrace-provider-0.8.8/test/gc2.js000066400000000000000000000006461352565761500175610ustar00rootroot00000000000000// node --expose_gc ... var d = require('../dtrace-provider'); var dtp = d.createDTraceProvider("testlibusdt"); // don't assign the returned probe object anywhere var p = dtp.addProbe("gcprobe"); dtp.enable(); // run GC gc(); // probe object should still be around dtp.fire("gcprobe", function() { return []; }); dtp = "something else"; gc(); p.fire(function() { return []; }); p = "something else"; gc(); node-dtrace-provider-0.8.8/test/gc3.js000066400000000000000000000004141352565761500175530ustar00rootroot00000000000000// node --expose_gc ... var d = require('../dtrace-provider'); for (var i = 0; i < 1000000; i++) { console.log("i: " + i); var dtp = d.createDTraceProvider("testlibusdt" + i); var p = dtp.addProbe("gcprobe"); dtp.enable(); dtp.disable(); } gc(); node-dtrace-provider-0.8.8/test/gc_fire.js000066400000000000000000000004431352565761500204770ustar00rootroot00000000000000var d = require('../dtrace-provider'); var dtp = d.createDTraceProvider("nodeapp"); // don't assign the returned probe object anywhere dtp.addProbe("gcprobe", "int"); dtp.enable(); // run GC gc(); // probe object should still be around dtp.fire("gcprobe", function() { return []; }); node-dtrace-provider-0.8.8/test/json-args.test.js000066400000000000000000000017151352565761500217650ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'probes with json type', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::json1{ this->j = copyinstr(arg0); printf("%s\\n%d\\n%s\\n", this->j, strtoll(json(this->j, "foo")), json(this->j, "bar")) }', '-c', format('node %s/json-args_fire.js', __dirname) ], function(t, exit_code, traces) { // skip if dtrace failed; assume no json() sub skip = exit_code == 0 ? 0 : 1; t.test("json tests, need json() subroutine", {"skip": skip}, function (t) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], '{"foo":42,"bar":"forty-two"}'); t.equal(traces[1], '42'); t.equal(traces[2], 'forty-two'); t.end(); }); } ) ); node-dtrace-provider-0.8.8/test/json-args_fire.js000066400000000000000000000004101352565761500220030ustar00rootroot00000000000000var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("nodeapp"); var probe = provider.addProbe("json1", "json"); provider.enable(); var obj = new Object; obj.foo = 42; obj.bar = 'forty-two'; probe.fire(function(p) { return [obj]; }); node-dtrace-provider-0.8.8/test/more-args.test.js000066400000000000000000000011171352565761500217520ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'firing probe with too many arguments', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::p1{ printf("%d\\n%d\\n", arg0, arg1); }', '-c', format('node %s/more-args_fire.js', __dirname) ], function(t, exit_code, traces) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], '1'); t.equal(traces[1], '2'); } ) ); node-dtrace-provider-0.8.8/test/more-args_fire.js000066400000000000000000000003261352565761500220020ustar00rootroot00000000000000var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("nodeapp"); var probe = provider.addProbe("p1", "int", "int"); provider.enable(); probe.fire(function(p) { return [1, 2, 3, 4]; }); node-dtrace-provider-0.8.8/test/multiple-json-args.test.js000066400000000000000000000015151352565761500236140ustar00rootroot00000000000000var test = require('tap').test; var format = require('util').format; var dtest = require('./dtrace-test').dtraceTest; test( 'probes with multiple json types', dtest( function() { }, [ 'dtrace', '-Zqn', 'nodeapp$target:::json1{ printf("%s %s", json(copyinstr(arg0), "value"), json(copyinstr(arg1), "value")) }', '-c', format('node %s/multiple-json-args_fire.js', __dirname) ], function(t, exit_code, traces) { // skip if dtrace failed; assume no json() sub skip = exit_code == 0 ? 0 : 1; t.test("json tests, need json() subroutine", {"skip": skip}, function (t) { t.notOk(exit_code, 'dtrace exited cleanly'); t.equal(traces[0], 'abc def'); t.end(); }); } ) ); node-dtrace-provider-0.8.8/test/multiple-json-args_fire.js000066400000000000000000000004321352565761500236400ustar00rootroot00000000000000var d = require('../dtrace-provider'); var provider = d.createDTraceProvider("nodeapp"); var probe = provider.addProbe("json1", "json", "json"); provider.enable(); var obj1 = { "value": "abc" }; var obj2 = { "value": "def" }; probe.fire(function(p) { return [obj1, obj2]; }); node-dtrace-provider-0.8.8/test/notenabled.test.js000066400000000000000000000006431352565761500221740ustar00rootroot00000000000000var test = require('tap').test; var d = require('../dtrace-provider'); test( 'firing probes when provider not enabled', function(t) { var dtp = d.createDTraceProvider("nodeapp"); dtp.addProbe("probe1", "int"); //dtp.enable(); dtp.fire("probe1", function(p) { t.notOk(); return [1]; }); t.ok(1, 'no problem'); t.end(); } );