Browse Source

tracing: add lttng support for tracing on linux

This commit adds the ability to enable userspace tracing with lttng
in io.js. It adds tracepoints for all the equivalent dtrace and ETW
tracepoints. To use these tracepoints enable --with-lttng on linux.

PR-URL: https://github.com/iojs/io.js/pull/702
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Ryan Graham <ryan@strongloop.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
v1.8.0-commit
Glen Keane 10 years ago
committed by Ben Noordhuis
parent
commit
5e825d1073
  1. 3
      Makefile
  2. 14
      configure
  3. 2
      lib/_http_client.js
  4. 2
      lib/_http_server.js
  5. 2
      lib/net.js
  6. 12
      node.gyp
  7. 8
      src/node.cc
  8. 266
      src/node_lttng.cc
  9. 40
      src/node_lttng.h
  10. 100
      src/node_lttng_provider.h
  11. 130
      src/node_lttng_tp.h
  12. 9
      src/nolttng_macros.py
  13. 9
      test/common.js
  14. 7
      test/sequential/test-util-debug.js

3
Makefile

@ -385,8 +385,9 @@ jslint:
CPPLINT_EXCLUDE ?= CPPLINT_EXCLUDE ?=
CPPLINT_EXCLUDE += src/node_dtrace.cc CPPLINT_EXCLUDE += src/node_dtrace.cc
CPPLINT_EXCLUDE += src/node_dtrace.cc CPPLINT_EXCLUDE += src/node_lttng.cc
CPPLINT_EXCLUDE += src/node_root_certs.h CPPLINT_EXCLUDE += src/node_root_certs.h
CPPLINT_EXCLUDE += src/node_lttng_tp.h
CPPLINT_EXCLUDE += src/node_win32_perfctr_provider.cc CPPLINT_EXCLUDE += src/node_win32_perfctr_provider.cc
CPPLINT_EXCLUDE += src/queue.h CPPLINT_EXCLUDE += src/queue.h
CPPLINT_EXCLUDE += src/tree.h CPPLINT_EXCLUDE += src/tree.h

14
configure

@ -213,6 +213,11 @@ parser.add_option('--with-dtrace',
dest='with_dtrace', dest='with_dtrace',
help='build with DTrace (default is true on sunos)') help='build with DTrace (default is true on sunos)')
parser.add_option('--with-lttng',
action='store_true',
dest='with_lttng',
help='build with Lttng (Only available to Linux)')
parser.add_option('--with-etw', parser.add_option('--with-etw',
action='store_true', action='store_true',
dest='with_etw', dest='with_etw',
@ -524,6 +529,15 @@ def configure_node(o):
else: else:
o['variables']['node_use_dtrace'] = 'false' o['variables']['node_use_dtrace'] = 'false'
# Enable Lttng if --with-lttng was defined. Use logic similar to
# ETW for windows. Lttng is only available on the Linux platform.
if flavor == 'linux':
o['variables']['node_use_lttng'] = b(options.with_lttng)
elif options.with_lttng:
raise Exception('lttng is only supported on Linux.')
else:
o['variables']['node_use_lttng'] = 'false'
# if we're on illumos based systems wrap the helper library into the # if we're on illumos based systems wrap the helper library into the
# executable # executable
if flavor == 'solaris': if flavor == 'solaris':

2
lib/_http_client.js

@ -155,6 +155,7 @@ ClientRequest.prototype.aborted = undefined;
ClientRequest.prototype._finish = function() { ClientRequest.prototype._finish = function() {
DTRACE_HTTP_CLIENT_REQUEST(this, this.connection); DTRACE_HTTP_CLIENT_REQUEST(this, this.connection);
LTTNG_HTTP_CLIENT_REQUEST(this, this.connection);
COUNTER_HTTP_CLIENT_REQUEST(); COUNTER_HTTP_CLIENT_REQUEST();
OutgoingMessage.prototype._finish.call(this); OutgoingMessage.prototype._finish.call(this);
}; };
@ -386,6 +387,7 @@ function parserOnIncomingClient(res, shouldKeepAlive) {
DTRACE_HTTP_CLIENT_RESPONSE(socket, req); DTRACE_HTTP_CLIENT_RESPONSE(socket, req);
LTTNG_HTTP_CLIENT_RESPONSE(socket, req);
COUNTER_HTTP_CLIENT_RESPONSE(); COUNTER_HTTP_CLIENT_RESPONSE();
req.res = res; req.res = res;
res.req = req; res.req = req;

2
lib/_http_server.js

@ -92,6 +92,7 @@ util.inherits(ServerResponse, OutgoingMessage);
ServerResponse.prototype._finish = function() { ServerResponse.prototype._finish = function() {
DTRACE_HTTP_SERVER_RESPONSE(this.connection); DTRACE_HTTP_SERVER_RESPONSE(this.connection);
LTTNG_HTTP_SERVER_RESPONSE(this.connection);
COUNTER_HTTP_SERVER_RESPONSE(); COUNTER_HTTP_SERVER_RESPONSE();
OutgoingMessage.prototype._finish.call(this); OutgoingMessage.prototype._finish.call(this);
}; };
@ -416,6 +417,7 @@ function connectionListener(socket) {
res.shouldKeepAlive = shouldKeepAlive; res.shouldKeepAlive = shouldKeepAlive;
DTRACE_HTTP_SERVER_REQUEST(req, socket); DTRACE_HTTP_SERVER_REQUEST(req, socket);
LTTNG_HTTP_SERVER_REQUEST(req, socket);
COUNTER_HTTP_SERVER_REQUEST(); COUNTER_HTTP_SERVER_REQUEST();
if (socket._httpMessage) { if (socket._httpMessage) {

2
lib/net.js

@ -387,6 +387,7 @@ Socket.prototype.end = function(data, encoding) {
stream.Duplex.prototype.end.call(this, data, encoding); stream.Duplex.prototype.end.call(this, data, encoding);
this.writable = false; this.writable = false;
DTRACE_NET_STREAM_END(this); DTRACE_NET_STREAM_END(this);
LTTNG_NET_STREAM_END(this);
// just in case we're waiting for an EOF. // just in case we're waiting for an EOF.
if (this.readable && !this._readableState.endEmitted) if (this.readable && !this._readableState.endEmitted)
@ -1324,6 +1325,7 @@ function onconnection(err, clientHandle) {
socket.server = self; socket.server = self;
DTRACE_NET_SERVER_CONNECTION(socket); DTRACE_NET_SERVER_CONNECTION(socket);
LTTNG_NET_SERVER_CONNECTION(socket);
COUNTER_NET_SERVER_CONNECTION(socket); COUNTER_NET_SERVER_CONNECTION(socket);
self.emit('connection', socket); self.emit('connection', socket);
} }

12
node.gyp

@ -2,6 +2,7 @@
'variables': { 'variables': {
'v8_use_snapshot%': 'false', 'v8_use_snapshot%': 'false',
'node_use_dtrace%': 'false', 'node_use_dtrace%': 'false',
'node_use_lttng%': 'false',
'node_use_etw%': 'false', 'node_use_etw%': 'false',
'node_use_perfctr%': 'false', 'node_use_perfctr%': 'false',
'node_has_winsdk%': 'false', 'node_has_winsdk%': 'false',
@ -260,6 +261,14 @@
} }
] ] ] ]
} ], } ],
[ 'node_use_lttng=="true"', {
'defines': [ 'HAVE_LTTNG=1' ],
'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ],
'libraries': [ '-llttng-ust' ],
'sources': [
'src/node_lttng.cc'
],
} ],
[ 'node_use_mdb=="true"', { [ 'node_use_mdb=="true"', {
'dependencies': [ 'node_mdb' ], 'dependencies': [ 'node_mdb' ],
'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ], 'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ],
@ -450,6 +459,9 @@
[ 'node_use_dtrace=="false" and node_use_etw=="false"', { [ 'node_use_dtrace=="false" and node_use_etw=="false"', {
'inputs': [ 'src/notrace_macros.py' ] 'inputs': [ 'src/notrace_macros.py' ]
}], }],
['node_use_lttng=="false"', {
'inputs': [ 'src/nolttng_macros.py' ]
}],
[ 'node_use_perfctr=="false"', { [ 'node_use_perfctr=="false"', {
'inputs': [ 'src/perfctr_macros.py' ] 'inputs': [ 'src/perfctr_macros.py' ]
}] }]

8
src/node.cc

@ -23,6 +23,10 @@
#include "node_dtrace.h" #include "node_dtrace.h"
#endif #endif
#if defined HAVE_LTTNG
#include "node_lttng.h"
#endif
#include "ares.h" #include "ares.h"
#include "async-wrap.h" #include "async-wrap.h"
#include "async-wrap-inl.h" #include "async-wrap-inl.h"
@ -2871,6 +2875,10 @@ void LoadEnvironment(Environment* env) {
InitDTrace(env, global); InitDTrace(env, global);
#endif #endif
#if defined HAVE_LTTNG
InitLTTNG(env, global);
#endif
#if defined HAVE_PERFCTR #if defined HAVE_PERFCTR
InitPerfCounters(env, global); InitPerfCounters(env, global);
#endif #endif

266
src/node_lttng.cc

@ -0,0 +1,266 @@
#include "util.h"
#ifdef HAVE_LTTNG
#include "node_lttng.h"
#include "node_lttng_provider.h"
#include <string.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_HTTP_CLIENT_REQUEST(arg0, arg1)
#define NODE_HTTP_CLIENT_REQUEST_ENABLED() (0)
#define NODE_HTTP_CLIENT_RESPONSE(arg0)
#define NODE_HTTP_CLIENT_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)
#define NODE_GC_START(arg0, arg1, arg2)
#define NODE_GC_DONE(arg0, arg1, arg2)
#endif
#include "env.h"
#include "env-inl.h"
namespace node {
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::GCCallbackFlags;
using v8::GCEpilogueCallback;
using v8::GCPrologueCallback;
using v8::GCType;
using v8::Handle;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
#define SLURP_STRING(obj, member, valp) \
if (!(obj)->IsObject()) { \
return env->ThrowError( \
"expected object for " #obj " to contain string member " #member); \
} \
node::Utf8Value _##member(env->isolate(), \
obj->Get(OneByteString(env->isolate(), #member))); \
if ((*(const char **)valp = *_##member) == nullptr) \
*(const char **)valp = "<unknown>";
#define SLURP_INT(obj, member, valp) \
if (!(obj)->IsObject()) { \
return env->ThrowError( \
"expected object for " #obj " to contain integer member " #member); \
} \
*valp = obj->Get(OneByteString(env->isolate(), #member)) \
->ToInteger(env->isolate())->Value();
#define SLURP_OBJECT(obj, member, valp) \
if (!(obj)->IsObject()) { \
return env->ThrowError( \
"expected object for " #obj " to contain object member " #member); \
} \
*valp = Local<Object>::Cast(obj->Get(OneByteString(env->isolate(), #member)));
#define SLURP_CONNECTION(arg, conn) \
if (!(arg)->IsObject()) { \
return env->ThrowError( \
"expected argument " #arg " to be a connection object"); \
} \
node_lttng_connection_t conn; \
Local<Object> _##conn = Local<Object>::Cast(arg); \
Local<Value> _handle = \
(_##conn)->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "_handle")); \
if (_handle->IsObject()) { \
SLURP_INT(_handle.As<Object>(), fd, &conn.fd); \
} else { \
conn.fd = -1; \
} \
SLURP_STRING(_##conn, remoteAddress, &conn.remote); \
SLURP_INT(_##conn, remotePort, &conn.port); \
SLURP_INT(_##conn, bufferSize, &conn.buffered);
#define SLURP_CONNECTION_HTTP_CLIENT(arg, conn) \
if (!(arg)->IsObject()) { \
return env->ThrowError( \
"expected argument " #arg " to be a connection object"); \
} \
node_lttng_connection_t conn; \
Local<Object> _##conn = Local<Object>::Cast(arg); \
SLURP_INT(_##conn, fd, &conn.fd); \
SLURP_STRING(_##conn, host, &conn.remote); \
SLURP_INT(_##conn, port, &conn.port); \
SLURP_INT(_##conn, bufferSize, &conn.buffered);
#define SLURP_CONNECTION_HTTP_CLIENT_RESPONSE(arg0, arg1, conn) \
if (!(arg0)->IsObject()) { \
return env->ThrowError( \
"expected argument " #arg0 " to be a connection object"); \
} \
if (!(arg1)->IsObject()) { \
return env->ThrowError( \
"expected argument " #arg1 " to be a connection object"); \
} \
node_lttng_connection_t conn; \
Local<Object> _##conn = Local<Object>::Cast(arg0); \
SLURP_INT(_##conn, fd, &conn.fd); \
SLURP_INT(_##conn, bufferSize, &conn.buffered); \
_##conn = Local<Object>::Cast(arg1); \
SLURP_STRING(_##conn, host, &conn.remote); \
SLURP_INT(_##conn, port, &conn.port);
void LTTNG_NET_SERVER_CONNECTION(const FunctionCallbackInfo<Value>& args) {
if (!NODE_NET_SERVER_CONNECTION_ENABLED())
return;
Environment* env = Environment::GetCurrent(args);
SLURP_CONNECTION(args[0], conn);
NODE_NET_SERVER_CONNECTION(&conn, conn.remote, conn.port, conn.fd);
}
void LTTNG_NET_STREAM_END(const FunctionCallbackInfo<Value>& args) {
if (!NODE_NET_STREAM_END_ENABLED())
return;
Environment* env = Environment::GetCurrent(args);
SLURP_CONNECTION(args[0], conn);
NODE_NET_STREAM_END(&conn, conn.remote, conn.port, conn.fd);
}
void LTTNG_HTTP_SERVER_REQUEST(const FunctionCallbackInfo<Value>& args) {
node_lttng_http_server_request_t req;
if (!NODE_HTTP_SERVER_REQUEST_ENABLED())
return;
if (!args[0]->IsObject())
return;
Environment* env = Environment::GetCurrent(args);
Local<Object> arg0 = args[0].As<Object>();
Local<Object> headers;
memset(&req, 0, sizeof(req));
req._un.version = 1;
SLURP_STRING(arg0, url, &req.url);
SLURP_STRING(arg0, method, &req.method);
SLURP_OBJECT(arg0, headers, &headers);
if (!(headers)->IsObject()) {
return env->ThrowError(
"expected object for request to contain string member headers");
}
Local<Value> strfwdfor = headers->Get(env->x_forwarded_string());
node::Utf8Value fwdfor(env->isolate(), strfwdfor);
req.forwarded_for = *fwdfor;
if (!strfwdfor->IsString() || req.forwarded_for == nullptr)
req.forwarded_for = "";
SLURP_CONNECTION(args[1], conn);
NODE_HTTP_SERVER_REQUEST(&req, &conn, conn.remote, conn.port, req.method, \
req.url, conn.fd);
}
void LTTNG_HTTP_SERVER_RESPONSE(const FunctionCallbackInfo<Value>& args) {
if (!NODE_HTTP_SERVER_RESPONSE_ENABLED())
return;
Environment* env = Environment::GetCurrent(args);
SLURP_CONNECTION(args[0], conn);
NODE_HTTP_SERVER_RESPONSE(&conn, conn.remote, conn.port, conn.fd);
}
void LTTNG_HTTP_CLIENT_REQUEST(const FunctionCallbackInfo<Value>& args) {
node_lttng_http_client_request_t req;
char* header;
if (!NODE_HTTP_CLIENT_REQUEST_ENABLED())
return;
Environment* env = Environment::GetCurrent(args);
/*
* For the method and URL, we're going to dig them out of the header. This
* is not as efficient as it could be, but we would rather not force the
* caller here to retain their method and URL until the time at which
* LTTNG_HTTP_CLIENT_REQUEST can be called.
*/
Local<Object> arg0 = args[0].As<Object>();
SLURP_STRING(arg0, _header, &header);
req.method = header;
while (*header != '\0' && *header != ' ')
header++;
if (*header != '\0')
*header++ = '\0';
req.url = header;
while (*header != '\0' && *header != ' ')
header++;
*header = '\0';
SLURP_CONNECTION_HTTP_CLIENT(args[1], conn);
NODE_HTTP_CLIENT_REQUEST(&req, &conn, conn.remote, conn.port, req.method, \
req.url, conn.fd);
}
void LTTNG_HTTP_CLIENT_RESPONSE(const FunctionCallbackInfo<Value>& args) {
if (!NODE_HTTP_CLIENT_RESPONSE_ENABLED())
return;
Environment* env = Environment::GetCurrent(args);
SLURP_CONNECTION_HTTP_CLIENT_RESPONSE(args[0], args[1], conn);
NODE_HTTP_CLIENT_RESPONSE(&conn, conn.remote, conn.port, conn.fd);
}
void lttng_gc_start(Isolate* isolate, GCType type, GCCallbackFlags flags) {
NODE_GC_START(type, flags, isolate);
}
void lttng_gc_done(Isolate* isolate, GCType type, GCCallbackFlags flags) {
NODE_GC_DONE(type, flags, isolate);
}
void InitLTTNG(Environment* env, Handle<Object> target) {
HandleScope scope(env->isolate());
static struct {
const char *name;
void (*func)(const FunctionCallbackInfo<Value>&);
} tab[] = {
#define NODE_PROBE(name) #name, name
{ NODE_PROBE(LTTNG_NET_SERVER_CONNECTION) },
{ NODE_PROBE(LTTNG_NET_STREAM_END) },
{ NODE_PROBE(LTTNG_HTTP_SERVER_REQUEST) },
{ NODE_PROBE(LTTNG_HTTP_SERVER_RESPONSE) },
{ NODE_PROBE(LTTNG_HTTP_CLIENT_REQUEST) },
{ NODE_PROBE(LTTNG_HTTP_CLIENT_RESPONSE) }
#undef NODE_PROBE
};
for (unsigned int i = 0; i < ARRAY_SIZE(tab); i++) {
Local<String> key = OneByteString(env->isolate(), tab[i].name);
Local<Value> val = env->NewFunctionTemplate(tab[i].func)->GetFunction();
target->Set(key, val);
}
#if defined HAVE_LTTNG
env->isolate()->AddGCPrologueCallback(lttng_gc_start);
env->isolate()->AddGCEpilogueCallback(lttng_gc_done);
#endif
}
} // namespace node

40
src/node_lttng.h

@ -0,0 +1,40 @@
#ifndef SRC_NODE_LTTNG_H_
#define SRC_NODE_LTTNG_H_
#include "node.h"
#include "v8.h"
#include "env.h"
extern "C" {
typedef struct {
int32_t fd;
int32_t port;
const char* remote;
int32_t buffered;
} node_lttng_connection_t;
typedef struct {
const char* url;
const char* method;
} node_lttng_http_client_request_t;
typedef struct {
union {
uint32_t version;
uintptr_t unused; /* for compat. with old 64-bit struct */
} _un;
const char* url;
const char* method;
const char* forwarded_for;
const char* _pad[8];
} node_lttng_http_server_request_t;
} // extern "C"
namespace node {
void InitLTTNG(Environment* env, v8::Handle<v8::Object> target);
} // namespace node
#endif // SRC_NODE_LTTNG_H_

100
src/node_lttng_provider.h

@ -0,0 +1,100 @@
#ifndef SRC_NODE_LTTNG_PROVIDER_H_
#define SRC_NODE_LTTNG_PROVIDER_H_
#define TRACEPOINT_CREATE_PROBES
#define TRACEPOINT_DEFINE
#include "node_lttng_tp.h"
namespace node {
void NODE_HTTP_SERVER_REQUEST(node_lttng_http_server_request_t* req,
node_lttng_connection_t* conn,
const char *remote, int port,
const char *method, const char *url,
int fd) {
tracepoint(node, http_server_request, req->url, req->method, \
req->forwarded_for);
}
void NODE_HTTP_SERVER_RESPONSE(node_lttng_connection_t* conn,
const char *remote, int port, int fd) {
tracepoint(node, http_server_response, port, conn->remote, fd);
}
void NODE_HTTP_CLIENT_REQUEST(node_lttng_http_client_request_t* req,
node_lttng_connection_t* conn,
const char *remote, int port,
const char *method, const char *url,
int fd) {
tracepoint(node, http_client_request, req->url, req->method);
}
void NODE_HTTP_CLIENT_RESPONSE(node_lttng_connection_t* conn,
const char *remote, int port, int fd) {
tracepoint(node, http_client_response, port, conn->remote, fd);
}
void NODE_NET_SERVER_CONNECTION(node_lttng_connection_t* conn,
const char *remote, int port, int fd) {
tracepoint(node, net_server_connection, conn->remote, port, fd, \
conn->buffered);
}
void NODE_NET_STREAM_END(node_lttng_connection_t* conn,
const char *remote, int port, int fd) {
tracepoint(node, net_stream_end, conn->remote, port, fd);
}
void NODE_GC_START(v8::GCType type,
v8::GCCallbackFlags flags,
v8::Isolate* isolate) {
const char* typeStr = "";
const char* flagsStr = "";
if (type == v8::GCType::kGCTypeScavenge) {
typeStr = "kGCTypeScavenge";
} else if (type == v8::GCType::kGCTypeMarkSweepCompact) {
typeStr = "kGCTypeMarkSweepCompact";
} else if (type == v8::GCType::kGCTypeAll) {
typeStr = "kGCTypeAll";
}
if (flags == v8::GCCallbackFlags::kNoGCCallbackFlags) {
flagsStr = "kNoGCCallbackFlags";
} else if (flags == v8::GCCallbackFlags::kGCCallbackFlagCompacted) {
flagsStr = "kGCCallbackFlagCompacted";
}
tracepoint(node, gc_start, typeStr, flagsStr);
}
void NODE_GC_DONE(v8::GCType type,
v8::GCCallbackFlags flags,
v8::Isolate* isolate) {
const char* typeStr = "";
const char* flagsStr = "";
if (type == v8::GCType::kGCTypeScavenge) {
typeStr = "kGCTypeScavenge";
} else if (type == v8::GCType::kGCTypeMarkSweepCompact) {
typeStr = "kGCTypeMarkSweepCompact";
} else if (type == v8::GCType::kGCTypeAll) {
typeStr = "kGCTypeAll";
}
if (flags == v8::GCCallbackFlags::kNoGCCallbackFlags) {
flagsStr = "kNoGCCallbackFlags";
} else if (flags == v8::GCCallbackFlags::kGCCallbackFlagCompacted) {
flagsStr = "kGCCallbackFlagCompacted";
}
tracepoint(node, gc_done, typeStr, flagsStr);
}
bool NODE_HTTP_SERVER_REQUEST_ENABLED() { return true; }
bool NODE_HTTP_SERVER_RESPONSE_ENABLED() { return true; }
bool NODE_HTTP_CLIENT_REQUEST_ENABLED() { return true; }
bool NODE_HTTP_CLIENT_RESPONSE_ENABLED() { return true; }
bool NODE_NET_SERVER_CONNECTION_ENABLED() { return true; }
bool NODE_NET_STREAM_END_ENABLED() { return true; }
} // namespace node
#endif // SRC_NODE_LTTNG_PROVIDER_H_

130
src/node_lttng_tp.h

@ -0,0 +1,130 @@
#undef TRACEPOINT_PROVIDER
#define TRACEPOINT_PROVIDER node
#undef TRACEPOINT_INCLUDE
#define TRACEPOINT_INCLUDE "./node_lttng_tp.h"
#if !defined(__NODE_LTTNG_TP_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
#define __NODE_LTTNG_TP_H
#include <lttng/tracepoint.h>
TRACEPOINT_EVENT(
node,
http_server_request,
TP_ARGS(
const char*, url,
const char*, method,
const char*, forwardedFor
),
TP_FIELDS(
ctf_string(url, url)
ctf_string(method, method)
ctf_string(forwardedFor, forwardedFor)
)
)
TRACEPOINT_EVENT(
node,
http_server_response,
TP_ARGS(
int, port,
const char*, remote,
int, fd
),
TP_FIELDS(
ctf_integer(int, port, port)
ctf_string(remote, remote)
ctf_integer(int, fd, fd)
)
)
TRACEPOINT_EVENT(
node,
http_client_request,
TP_ARGS(
const char*, url,
const char*, method
),
TP_FIELDS(
ctf_string(url, url)
ctf_string(method, method)
)
)
TRACEPOINT_EVENT(
node,
http_client_response,
TP_ARGS(
int, port,
const char*, remote,
int, fd
),
TP_FIELDS(
ctf_integer(int, port, port)
ctf_string(remote, remote)
ctf_integer(int, fd, fd)
)
)
TRACEPOINT_EVENT(
node,
net_server_connection,
TP_ARGS(
const char*, remote,
int, port,
int, fd,
int, buffered
),
TP_FIELDS(
ctf_string(remote, remote)
ctf_integer(int, port, port)
ctf_integer(int, fd, fd)
ctf_integer(int, buffered, buffered)
)
)
TRACEPOINT_EVENT(
node,
net_stream_end,
TP_ARGS(
const char*, remote,
int, port,
int, fd
),
TP_FIELDS(
ctf_string(remote, remote)
ctf_integer(int, port, port)
ctf_integer(int, fd, fd)
)
)
TRACEPOINT_EVENT(
node,
gc_start,
TP_ARGS(
const char*, gctype,
const char*, gcflags
),
TP_FIELDS(
ctf_string(gctype, gctype)
ctf_string(gcflags, gcflags)
)
)
TRACEPOINT_EVENT(
node,
gc_done,
TP_ARGS(
const char*, gctype,
const char*, gcflags
),
TP_FIELDS(
ctf_string(gctype, gctype)
ctf_string(gcflags, gcflags)
)
)
#endif /* __NODE_LTTNG_TP_H */
#include <lttng/tracepoint-event.h>

9
src/nolttng_macros.py

@ -0,0 +1,9 @@
# This file is used by tools/js2c.py to preprocess out the LTTNG symbols in
# builds that don't support LTTNG. This is not used in builds that support
# LTTNG.
macro LTTNG_HTTP_CLIENT_REQUEST(x) = ;
macro LTTNG_HTTP_CLIENT_RESPONSE(x) = ;
macro LTTNG_HTTP_SERVER_REQUEST(x) = ;
macro LTTNG_HTTP_SERVER_RESPONSE(x) = ;
macro LTTNG_NET_SERVER_CONNECTION(x) = ;
macro LTTNG_NET_STREAM_END(x) = ;

9
test/common.js

@ -170,6 +170,15 @@ if (global.COUNTER_NET_SERVER_CONNECTION) {
knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE); knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE);
} }
if (global.LTTNG_HTTP_SERVER_RESPONSE) {
knownGlobals.push(LTTNG_HTTP_SERVER_RESPONSE);
knownGlobals.push(LTTNG_HTTP_SERVER_REQUEST);
knownGlobals.push(LTTNG_HTTP_CLIENT_RESPONSE);
knownGlobals.push(LTTNG_HTTP_CLIENT_REQUEST);
knownGlobals.push(LTTNG_NET_STREAM_END);
knownGlobals.push(LTTNG_NET_SERVER_CONNECTION);
}
if (global.ArrayBuffer) { if (global.ArrayBuffer) {
knownGlobals.push(ArrayBuffer); knownGlobals.push(ArrayBuffer);
knownGlobals.push(Int8Array); knownGlobals.push(Int8Array);

7
test/sequential/test-util-debug.js

@ -26,7 +26,12 @@ function test(environ, shouldWrite) {
var spawn = require('child_process').spawn; var spawn = require('child_process').spawn;
var child = spawn(process.execPath, [__filename, 'child'], { var child = spawn(process.execPath, [__filename, 'child'], {
env: { NODE_DEBUG: environ } // Lttng requires the HOME env variable or it prints to stderr,
// This is not really ideal, as it breaks this test, so the HOME
// env variable is passed to the child to make the test pass.
// this is fixed in the next version of lttng (2.7+), so we can
// remove it at sometime in the future.
env: { NODE_DEBUG: environ, HOME: process.env.HOME }
}); });
expectErr = expectErr.split('%PID%').join(child.pid); expectErr = expectErr.split('%PID%').join(child.pid);

Loading…
Cancel
Save