mirror of https://github.com/lukechilds/node.git
Ryan Dahl
14 years ago
9 changed files with 358 additions and 2 deletions
@ -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))); |
|||
}; |
@ -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()); |
|||
} |
|||
} |
|||
|
|||
} |
@ -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 |
@ -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 |
Loading…
Reference in new issue