diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-01-25 04:50:10 +0300 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-01-25 05:59:06 +0300 |
commit | 068b733583a4f0781a8418ddf42f7912e3dd53a6 (patch) | |
tree | 7f9dd4ca422b06447db9f901cc11d9f7bca90423 /src | |
parent | 91cc2d8c4bff5c5fbacd757f38b9a8c690dce131 (diff) |
Land Cantrill's DTrace patch
only works on solaris
Diffstat (limited to 'src')
-rw-r--r-- | src/node.cc | 3 | ||||
-rw-r--r-- | src/node.d | 64 | ||||
-rw-r--r-- | src/node_dtrace.cc | 113 | ||||
-rw-r--r-- | src/node_dtrace.h | 28 | ||||
-rw-r--r-- | src/node_provider.d | 44 |
5 files changed, 252 insertions, 0 deletions
diff --git a/src/node.cc b/src/node.cc index 512c1d97f12..582b0d23c41 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3,6 +3,7 @@ #include <node.h> #include <v8-debug.h> +#include <node_dtrace.h> #include <locale.h> #include <stdio.h> @@ -2028,6 +2029,8 @@ static void Load(int argc, char *argv[]) { Local<Object> global = v8::Context::GetCurrent()->Global(); Local<Value> args[1] = { Local<Value>::New(process) }; + InitDTrace(global); + f->Call(global, 1, args); if (try_catch.HasCaught()) { diff --git a/src/node.d b/src/node.d new file mode 100644 index 00000000000..80010e9b4f7 --- /dev/null +++ b/src/node.d @@ -0,0 +1,64 @@ +/* + * This is the DTrace library file for the node provider, which includes + * the necessary translators to get from the args[] to something useful. + * Be warned: the mechanics here are seriously ugly -- and one must always + * keep in mind that clean abstractions often require filthy systems. + */ +#pragma D depends_on library procfs.d + +typedef struct { + int32_t fd; + int32_t port; + uint32_t remote; +} node_dtrace_connection_t; + +typedef struct { + int32_t fd; + int32_t port; + uint64_t remote; +} node_dtrace_connection64_t; + +typedef struct { + int fd; + string remoteAddress; + int remotePort; +} node_connection_t; + +translator node_connection_t <node_dtrace_connection_t *nc> { + fd = *(int32_t *)copyin((uintptr_t)&nc->fd, sizeof (int32_t)); + remotePort = + *(int32_t *)copyin((uintptr_t)&nc->port, sizeof (int32_t)); + remoteAddress = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ? + copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nc->remote, + sizeof (int32_t))) : + copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t) + &((node_dtrace_connection64_t *)nc)->remote, sizeof (int64_t))); +}; + +typedef struct { + uint32_t url; + uint32_t method; +} node_dtrace_http_request_t; + +typedef struct { + uint64_t url; + uint64_t method; +} node_dtrace_http_request64_t; + +typedef struct { + string url; + string method; +} node_http_request_t; + +translator node_http_request_t <node_dtrace_http_request_t *nd> { + url = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ? + copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nd->url, + sizeof (int32_t))) : + copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t) + &((node_dtrace_http_request64_t *)nd)->url, sizeof (int64_t))); + method = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ? + copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nd->method, + sizeof (int32_t))) : + copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t) + &((node_dtrace_http_request64_t *)nd)->method, sizeof (int64_t))); +}; diff --git a/src/node_dtrace.cc b/src/node_dtrace.cc new file mode 100644 index 00000000000..0f7726a6209 --- /dev/null +++ b/src/node_dtrace.cc @@ -0,0 +1,113 @@ +#include <node_dtrace.h> + +#ifdef HAVE_DTRACE +#include "node_provider.h" +#else +#define NODE_HTTP_SERVER_REQUEST(arg0, arg1) +#define NODE_HTTP_SERVER_REQUEST_ENABLED() (0) +#define NODE_HTTP_SERVER_RESPONSE(arg0) +#define NODE_HTTP_SERVER_RESPONSE_ENABLED() (0) +#define NODE_NET_SERVER_CONNECTION(arg0) +#define NODE_NET_SERVER_CONNECTION_ENABLED() (0) +#define NODE_NET_STREAM_END(arg0) +#define NODE_NET_STREAM_END_ENABLED() (0) +#endif + +namespace node { + +using namespace v8; + +#define SLURP_STRING(obj, member, valp) \ + String::Utf8Value _##member(obj->Get(String::New(#member))->ToString()); \ + if ((*(const char **)valp = *_##member) == NULL) \ + *(const char **)valp = "<unknown>"; + +#define SLURP_INT(obj, member, valp) \ + *valp = obj->Get(String::New(#member))->ToInteger()->Value(); + +#define SLURP_CONNECTION(arg, conn) \ + node_dtrace_connection_t conn; \ + Local<Object> _##conn = Local<Object>::Cast(arg); \ + SLURP_INT(_##conn, fd, &conn.fd); \ + SLURP_STRING(_##conn, remoteAddress, &conn.remote); \ + SLURP_INT(_##conn, remotePort, &conn.port); + +Handle<Value> DTRACE_NET_SERVER_CONNECTION(const Arguments& args) { + if (!NODE_NET_SERVER_CONNECTION_ENABLED()) + return Undefined(); + + HandleScope scope; + + SLURP_CONNECTION(args[0], conn); + NODE_NET_SERVER_CONNECTION(&conn); + + return Undefined(); +} + +Handle<Value> DTRACE_NET_STREAM_END(const Arguments& args) { + if (!NODE_NET_STREAM_END_ENABLED()) + return Undefined(); + + HandleScope scope; + + SLURP_CONNECTION(args[0], conn); + NODE_NET_STREAM_END(&conn); + + return Undefined(); +} + +Handle<Value> DTRACE_HTTP_SERVER_REQUEST(const Arguments& args) { + node_dtrace_http_request_t req; + + if (!NODE_HTTP_SERVER_REQUEST_ENABLED()) + return Undefined(); + + HandleScope scope; + + Local<Object> arg0 = Local<Object>::Cast(args[0]); + Local<Object> arg1 = Local<Object>::Cast(args[1]); + + SLURP_STRING(arg0, url, &req.url); + SLURP_STRING(arg0, method, &req.method); + + SLURP_CONNECTION(args[1], conn); + + NODE_HTTP_SERVER_REQUEST(&req, &conn); + return Undefined(); +} + +Handle<Value> DTRACE_HTTP_SERVER_RESPONSE(const Arguments& args) { + if (!NODE_HTTP_SERVER_RESPONSE_ENABLED()) + return Undefined(); + + HandleScope scope; + + SLURP_CONNECTION(args[0], conn); + NODE_HTTP_SERVER_RESPONSE(&conn); + + return Undefined(); +} + +#define NODE_PROBE(name) #name, name + +void InitDTrace(Handle<Object> target) { + static struct { + const char *name; + Handle<Value> (*func)(const Arguments&); + Persistent<FunctionTemplate> templ; + } tab[] = { + { NODE_PROBE(DTRACE_NET_SERVER_CONNECTION) }, + { NODE_PROBE(DTRACE_NET_STREAM_END) }, + { NODE_PROBE(DTRACE_HTTP_SERVER_REQUEST) }, + { NODE_PROBE(DTRACE_HTTP_SERVER_RESPONSE) }, + { NULL } + }; + + for (int i = 0; tab[i].name != NULL; i++) { + tab[i].templ = Persistent<FunctionTemplate>::New( + FunctionTemplate::New(tab[i].func)); + target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction()); + } +} + +} diff --git a/src/node_dtrace.h b/src/node_dtrace.h new file mode 100644 index 00000000000..267c7292169 --- /dev/null +++ b/src/node_dtrace.h @@ -0,0 +1,28 @@ +#ifndef NODE_DTRACE_H_ +#define NODE_DTRACE_H_ + +#include <node.h> +#include <v8.h> + +extern "C" { + +typedef struct { + int32_t fd; + int32_t port; + char *remote; +} node_dtrace_connection_t; + +typedef struct { + char *url; + char *method; +} node_dtrace_http_request_t; + +} + +namespace node { + +void InitDTrace(v8::Handle<v8::Object> target); + +} + +#endif diff --git a/src/node_provider.d b/src/node_provider.d new file mode 100644 index 00000000000..3d11f39416b --- /dev/null +++ b/src/node_provider.d @@ -0,0 +1,44 @@ +/* + * DTrace provider for node.js. + */ + +/* + * In order to have the information we need here to create the provider, + * we must declare bogus definitions for our depended-upon structures. And + * yes, the fact that we need to do this represents a shortcoming in DTrace, + * one that would be resolved by that elusive El Dorado: dynamic translators. + */ + +typedef struct { + int dummy; +} node_dtrace_connection_t; + +typedef struct { + int dummy; +} node_connection_t; + +typedef struct { + int dummy; +} node_dtrace_http_request_t; + +typedef struct { + int dummy; +} node_http_request_t; + +provider node { + probe net__server__connection(node_dtrace_connection_t *c) : + (node_connection_t *c); + probe net__stream__end(node_dtrace_connection_t *c) : + (node_connection_t *c); + probe http__server__request(node_dtrace_http_request_t *h, + node_dtrace_connection_t *c) : + (node_http_request_t *h, node_connection_t *c); + probe http__server__response(node_dtrace_connection_t *c) : + (node_connection_t *c); +}; + +#pragma D attributes Evolving/Evolving/ISA provider node provider +#pragma D attributes Private/Private/Unknown provider node module +#pragma D attributes Private/Private/Unknown provider node function +#pragma D attributes Private/Private/ISA provider node name +#pragma D attributes Evolving/Evolving/ISA provider node args |