root / HServer / 00.Server / 00.Program / node_modules / dtrace-provider / README.md
이력 | 보기 | 이력해설 | 다운로드 (8.17 KB)
| 1 |
# dtrace-provider - Native DTrace providers for Node.js apps. |
|---|---|
| 2 |
|
| 3 |
This extension allows you to create native DTrace providers for your |
| 4 |
Node.js applications. That is, to create providers and probes which |
| 5 |
expose information specific to your application, rather than |
| 6 |
information about the node runtime. |
| 7 |
|
| 8 |
You could use this to expose high-level information about the inner |
| 9 |
workings of your application, or to create a specific context in which |
| 10 |
to look at information from other runtime or system-level providers. |
| 11 |
|
| 12 |
The provider is not created in the usual way, by declaring it and then |
| 13 |
changing the build process to include it, but instead dynamically at |
| 14 |
runtime. This is done entirely in-process, and there is no background |
| 15 |
compiler or [dtrace(1M)](https://illumos.org/man/1M/dtrace) invocation. |
| 16 |
The process creating the provider need not run as root. |
| 17 |
|
| 18 |
## INSTALL |
| 19 |
|
| 20 |
$ npm install dtrace-provider |
| 21 |
|
| 22 |
## EXAMPLE |
| 23 |
|
| 24 |
Here's a simple example of creating a provider: |
| 25 |
|
| 26 |
```javascript |
| 27 |
var d = require('dtrace-provider');
|
| 28 |
|
| 29 |
var dtp = d.createDTraceProvider("nodeapp");
|
| 30 |
var p1 = dtp.addProbe("probe1", "int", "int");
|
| 31 |
var p2 = dtp.addProbe("probe2", "char *");
|
| 32 |
dtp.enable(); |
| 33 |
``` |
| 34 |
|
| 35 |
Probes may be fired via the provider object: |
| 36 |
|
| 37 |
```javascript |
| 38 |
dtp.fire("probe1", function() {
|
| 39 |
return [1, 2]; |
| 40 |
}); |
| 41 |
dtp.fire("probe2", function() {
|
| 42 |
return ["hello, dtrace via provider", "foo"]; |
| 43 |
}); |
| 44 |
``` |
| 45 |
|
| 46 |
or via the probe objects themselves: |
| 47 |
|
| 48 |
```javascript |
| 49 |
p1.fire(function() {
|
| 50 |
return [1, 2, 3, 4, 5, 6]; |
| 51 |
}); |
| 52 |
p2.fire(function() {
|
| 53 |
return ["hello, dtrace via probe", "foo"]; |
| 54 |
}); |
| 55 |
``` |
| 56 |
|
| 57 |
Note that `.fire()` takes a callback that returns the arguments to be |
| 58 |
provided when the DTrace probe actually fires. This allows you to call |
| 59 |
`.fire()` unconditionally when you want to fire the probe, but the |
| 60 |
callback will be invoked only when the DTrace probe is actually |
| 61 |
enabled. This allows you to create probes whose arguments might be |
| 62 |
expensive to construct, and only do any work when the probe is |
| 63 |
actually enabled. (Examples might include converting a large object to |
| 64 |
a string representation or gathering large amounts of information.) |
| 65 |
|
| 66 |
In some cases, creating a new closure to pass to `.fire()` each time |
| 67 |
it's called may introduce unwanted overhead. For extremely |
| 68 |
CPU-intensive or memory-conscious workloads, you can avoid this by |
| 69 |
lifting the closures for your hot probes into an outer scope. You can |
| 70 |
then supply arguments to that function as additional arguments to |
| 71 |
`.fire()`. As an example, you can convert the following program: |
| 72 |
|
| 73 |
```javascript |
| 74 |
function manipulateObj(largeObj) {
|
| 75 |
var count = 0; |
| 76 |
var name = null; |
| 77 |
... |
| 78 |
p1.fire(function () {
|
| 79 |
return [count, keyToValue(name), JSON.stringify(largeObj)]; |
| 80 |
}); |
| 81 |
} |
| 82 |
``` |
| 83 |
|
| 84 |
Into this one: |
| 85 |
|
| 86 |
```javascript |
| 87 |
function f(a, b, c) {
|
| 88 |
return [a, keyToValue(b), JSON.stringify(c)]; |
| 89 |
} |
| 90 |
|
| 91 |
function manipulateObj(largeObj) {
|
| 92 |
var count = 0; |
| 93 |
var name = null; |
| 94 |
... |
| 95 |
p1.fire(f, count, name, largeObj); |
| 96 |
} |
| 97 |
``` |
| 98 |
|
| 99 |
Be careful to avoid passing `.fire()` additional arguments that are |
| 100 |
themselves expensive to construct, as that undermines the design goal |
| 101 |
here: minimizing the effect of disabled probes. |
| 102 |
|
| 103 |
This example creates a provider called "nodeapp", and adds two |
| 104 |
probes. It then enables the provider, at which point the provider |
| 105 |
becomes visible to DTrace. |
| 106 |
|
| 107 |
The probes are then fired, which produces this output: |
| 108 |
|
| 109 |
$ sudo dtrace -Z -n 'nodeapp*:::probe1{ trace(arg0); trace(arg1) }' \
|
| 110 |
-n 'nodeapp*:::probe2{ trace(copyinstr(arg0)); }'
|
| 111 |
dtrace: description 'nodeapp*:::probe1' matched 0 probes |
| 112 |
dtrace: description 'nodeapp*:::probe2' matched 0 probes |
| 113 |
CPU ID FUNCTION:NAME |
| 114 |
1 123562 func:probe1 1 2 |
| 115 |
1 123563 func:probe2 hello, dtrace |
| 116 |
|
| 117 |
Arguments are captured by a callback only executed when the probe is |
| 118 |
enabled. This means you can do more expensive work to gather arguments. |
| 119 |
|
| 120 |
The maximum number of arguments supported is 32. |
| 121 |
|
| 122 |
Available argument types are "int", for integer numeric values, |
| 123 |
"char *" for strings, and "json" for objects rendered into JSON strings. |
| 124 |
|
| 125 |
Arguments typed as "json" will be created as "char *" probes in |
| 126 |
DTrace, but objects passed to these probe arguments will be |
| 127 |
automatically serialized to JSON before being passed to DTrace. This |
| 128 |
feature is best used in conjunction with the json() D subroutine, but |
| 129 |
is available whether or not the platform supports it. |
| 130 |
|
| 131 |
# create a json probe: |
| 132 |
|
| 133 |
var dtp = d.createDTraceProvider("nodeapp");
|
| 134 |
var p1 = dtp.addProbe("j1", "json");
|
| 135 |
dtp.enable(); |
| 136 |
p1.fire(function() { return { "foo": "bar" }; });
|
| 137 |
|
| 138 |
# on a platform supporting json(): |
| 139 |
|
| 140 |
$ sudo dtrace -Z -n 'nodeapp*:::j1{ this->j = copyinstr(arg0); \
|
| 141 |
trace(json(this->j, "foo")) }' |
| 142 |
dtrace: description 'nodeapp$target:::j1' matched 0 probes |
| 143 |
CPU ID FUNCTION:NAME |
| 144 |
0 68712 j1:j1 bar |
| 145 |
|
| 146 |
## PLATFORM SUPPORT |
| 147 |
|
| 148 |
This libusdt-based Node.JS module supports 64 and 32 bit processes on |
| 149 |
Mac OS X and Solaris-like systems such as illumos or SmartOS. As more |
| 150 |
platform support is added to libusdt, those platforms will be |
| 151 |
supported by this module. See libusdt's status at: |
| 152 |
|
| 153 |
https://github.com/chrisa/libusdt#readme |
| 154 |
|
| 155 |
When using Mac OS X, be aware that as of 10.11 (El Capitan), DTrace use |
| 156 |
is restricted, and you'll probably want to |
| 157 |
[disable SIP](http://internals.exposed/blog/dtrace-vs-sip.html) to |
| 158 |
effectively use DTrace. |
| 159 |
|
| 160 |
FreeBSD 10 and 11 are also supported, but you'll need to make sure that |
| 161 |
you have the DTrace headers installed in `/usr/src` otherwise libusdt |
| 162 |
won't be able to compile. You can |
| 163 |
[clone them using SVN](https://www.freebsd.org/doc/handbook/svn.html), |
| 164 |
or find the correct `src.txz` |
| 165 |
[here](http://ftp.freebsd.org/pub/FreeBSD/releases/) and extract that. |
| 166 |
Also note that FreeBSD 10 is restricted to only 4 working arguments per |
| 167 |
probe. |
| 168 |
|
| 169 |
Platforms not supporting DTrace (notably, Linux and Windows) may |
| 170 |
install this module without building libusdt, with a stub no-op |
| 171 |
implementation provided for compatibility. This allows cross-platform |
| 172 |
npm modules to embed probes and include a dependency on this module. |
| 173 |
|
| 174 |
GNU Make is required to build libusdt; the build scripts will look for |
| 175 |
gmake in `PATH` first, and then for make. |
| 176 |
|
| 177 |
### TROUBLESHOOTING BUILD ISSUES |
| 178 |
|
| 179 |
If compilation fails during installation on platforms with DTrace, then |
| 180 |
the library will fall back to the stub implementation that does nothing. |
| 181 |
To force an installation failure when compiling fails, set the environment |
| 182 |
variable `NODE_DTRACE_PROVIDER_REQUIRE` to `hard`: |
| 183 |
|
| 184 |
```shell |
| 185 |
$ NODE_DTRACE_PROVIDER_REQUIRE=hard npm install |
| 186 |
``` |
| 187 |
|
| 188 |
This will then show you the output of the build process so you can see at |
| 189 |
which point it's having an issue. Common issues are: |
| 190 |
|
| 191 |
- Missing a C/C++ compiler toolchain for your platform. |
| 192 |
- `python` is Python 3 instead of Python 2; run `npm config set python python2.7` |
| 193 |
(or similar) to set the Python binary npm uses. |
| 194 |
- On OS X you may need to agree to the XCode license if that's the compiler |
| 195 |
toolchain you're using. This will usually manifest with an error like |
| 196 |
`Agreeing to the Xcode/iOS license requires admin privileges, please re-run as root via sudo.` |
| 197 |
To accept the license, you can run `sudo xcodebuild -license`. |
| 198 |
|
| 199 |
Once you've found and fixed the issue, you can run `npm rebuild` to rerun |
| 200 |
the lifecycle scripts. |
| 201 |
|
| 202 |
## CAVEATS |
| 203 |
|
| 204 |
There is some overhead to probes, even when disabled. Probes are |
| 205 |
already using the "is-enabled" feature of DTrace to control execution |
| 206 |
of the arguments-gathering callback, but some work still needs to be |
| 207 |
done before that's checked. This overhead should not be a problem |
| 208 |
unless probes are placed in particularly hot code paths. |
| 209 |
|
| 210 |
## CONTRIBUTING |
| 211 |
|
| 212 |
To clone the project's source code: |
| 213 |
|
| 214 |
$ git clone --recursive https://github.com/chrisa/node-dtrace-provider.git |
| 215 |
|
| 216 |
For issues, please use the [GitHub issue tracker](https://github.com/chrisa/node-dtrace-provider/issues) |
| 217 |
linked to the repository. GitHub pull requests are very welcome. |
| 218 |
|
| 219 |
## RUNNING THE TESTS |
| 220 |
|
| 221 |
```shell |
| 222 |
$ npm install |
| 223 |
$ sudo ./node_modules/.bin/tap --tap test/*.test.js |
| 224 |
``` |
| 225 |
|
| 226 |
## OTHER IMPLEMENTATIONS |
| 227 |
|
| 228 |
This node extension is derived from the ruby-dtrace gem, via the Perl |
| 229 |
module Devel::DTrace::Provider, both of which provide the same |
| 230 |
functionality to those languages. |