diff --git a/Makefile b/Makefile index fdbf4d7179..39741096f1 100644 --- a/Makefile +++ b/Makefile @@ -385,8 +385,9 @@ jslint: CPPLINT_EXCLUDE ?= 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_lttng_tp.h CPPLINT_EXCLUDE += src/node_win32_perfctr_provider.cc CPPLINT_EXCLUDE += src/queue.h CPPLINT_EXCLUDE += src/tree.h diff --git a/configure b/configure index e85621e9cb..d63232626c 100755 --- a/configure +++ b/configure @@ -213,6 +213,11 @@ parser.add_option('--with-dtrace', dest='with_dtrace', 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', action='store_true', dest='with_etw', @@ -524,6 +529,15 @@ def configure_node(o): else: 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 # executable if flavor == 'solaris': diff --git a/lib/_http_client.js b/lib/_http_client.js index 6804157ee0..b02ab66b29 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -155,6 +155,7 @@ ClientRequest.prototype.aborted = undefined; ClientRequest.prototype._finish = function() { DTRACE_HTTP_CLIENT_REQUEST(this, this.connection); + LTTNG_HTTP_CLIENT_REQUEST(this, this.connection); COUNTER_HTTP_CLIENT_REQUEST(); OutgoingMessage.prototype._finish.call(this); }; @@ -386,6 +387,7 @@ function parserOnIncomingClient(res, shouldKeepAlive) { DTRACE_HTTP_CLIENT_RESPONSE(socket, req); + LTTNG_HTTP_CLIENT_RESPONSE(socket, req); COUNTER_HTTP_CLIENT_RESPONSE(); req.res = res; res.req = req; diff --git a/lib/_http_server.js b/lib/_http_server.js index d8b9799438..99903024c2 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -92,6 +92,7 @@ util.inherits(ServerResponse, OutgoingMessage); ServerResponse.prototype._finish = function() { DTRACE_HTTP_SERVER_RESPONSE(this.connection); + LTTNG_HTTP_SERVER_RESPONSE(this.connection); COUNTER_HTTP_SERVER_RESPONSE(); OutgoingMessage.prototype._finish.call(this); }; @@ -416,6 +417,7 @@ function connectionListener(socket) { res.shouldKeepAlive = shouldKeepAlive; DTRACE_HTTP_SERVER_REQUEST(req, socket); + LTTNG_HTTP_SERVER_REQUEST(req, socket); COUNTER_HTTP_SERVER_REQUEST(); if (socket._httpMessage) { diff --git a/lib/net.js b/lib/net.js index af8c3dd8fe..030083d3f4 100644 --- a/lib/net.js +++ b/lib/net.js @@ -387,6 +387,7 @@ Socket.prototype.end = function(data, encoding) { stream.Duplex.prototype.end.call(this, data, encoding); this.writable = false; DTRACE_NET_STREAM_END(this); + LTTNG_NET_STREAM_END(this); // just in case we're waiting for an EOF. if (this.readable && !this._readableState.endEmitted) @@ -1324,6 +1325,7 @@ function onconnection(err, clientHandle) { socket.server = self; DTRACE_NET_SERVER_CONNECTION(socket); + LTTNG_NET_SERVER_CONNECTION(socket); COUNTER_NET_SERVER_CONNECTION(socket); self.emit('connection', socket); } diff --git a/node.gyp b/node.gyp index 2874f13094..8506b28685 100644 --- a/node.gyp +++ b/node.gyp @@ -2,6 +2,7 @@ 'variables': { 'v8_use_snapshot%': 'false', 'node_use_dtrace%': 'false', + 'node_use_lttng%': 'false', 'node_use_etw%': 'false', 'node_use_perfctr%': '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"', { 'dependencies': [ 'node_mdb' ], 'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ], @@ -450,6 +459,9 @@ [ 'node_use_dtrace=="false" and node_use_etw=="false"', { 'inputs': [ 'src/notrace_macros.py' ] }], + ['node_use_lttng=="false"', { + 'inputs': [ 'src/nolttng_macros.py' ] + }], [ 'node_use_perfctr=="false"', { 'inputs': [ 'src/perfctr_macros.py' ] }] diff --git a/src/node.cc b/src/node.cc index 4386d372b7..fd65fbff0b 100644 --- a/src/node.cc +++ b/src/node.cc @@ -23,6 +23,10 @@ #include "node_dtrace.h" #endif +#if defined HAVE_LTTNG +#include "node_lttng.h" +#endif + #include "ares.h" #include "async-wrap.h" #include "async-wrap-inl.h" @@ -2871,6 +2875,10 @@ void LoadEnvironment(Environment* env) { InitDTrace(env, global); #endif +#if defined HAVE_LTTNG + InitLTTNG(env, global); +#endif + #if defined HAVE_PERFCTR InitPerfCounters(env, global); #endif diff --git a/src/node_lttng.cc b/src/node_lttng.cc new file mode 100644 index 0000000000..0c63882c79 --- /dev/null +++ b/src/node_lttng.cc @@ -0,0 +1,266 @@ +#include "util.h" + +#ifdef HAVE_LTTNG +#include "node_lttng.h" +#include "node_lttng_provider.h" +#include +#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 = ""; + +#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::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 _##conn = Local::Cast(arg); \ + Local _handle = \ + (_##conn)->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "_handle")); \ + if (_handle->IsObject()) { \ + SLURP_INT(_handle.As(), 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 _##conn = Local::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 _##conn = Local::Cast(arg0); \ + SLURP_INT(_##conn, fd, &conn.fd); \ + SLURP_INT(_##conn, bufferSize, &conn.buffered); \ + _##conn = Local::Cast(arg1); \ + SLURP_STRING(_##conn, host, &conn.remote); \ + SLURP_INT(_##conn, port, &conn.port); + + +void LTTNG_NET_SERVER_CONNECTION(const FunctionCallbackInfo& 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& 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& 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 arg0 = args[0].As(); + Local 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 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& 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& 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 arg0 = args[0].As(); + 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& 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 target) { + HandleScope scope(env->isolate()); + + static struct { + const char *name; + void (*func)(const FunctionCallbackInfo&); + } 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 key = OneByteString(env->isolate(), tab[i].name); + Local 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 diff --git a/src/node_lttng.h b/src/node_lttng.h new file mode 100644 index 0000000000..31f706f758 --- /dev/null +++ b/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 target); + +} // namespace node + +#endif // SRC_NODE_LTTNG_H_ diff --git a/src/node_lttng_provider.h b/src/node_lttng_provider.h new file mode 100644 index 0000000000..22dd935a95 --- /dev/null +++ b/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_ diff --git a/src/node_lttng_tp.h b/src/node_lttng_tp.h new file mode 100644 index 0000000000..53d04f47a8 --- /dev/null +++ b/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 + +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 diff --git a/src/nolttng_macros.py b/src/nolttng_macros.py new file mode 100644 index 0000000000..cefd80507e --- /dev/null +++ b/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) = ; diff --git a/test/common.js b/test/common.js index 1599de07be..352f7b6764 100644 --- a/test/common.js +++ b/test/common.js @@ -170,6 +170,15 @@ if (global.COUNTER_NET_SERVER_CONNECTION) { 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) { knownGlobals.push(ArrayBuffer); knownGlobals.push(Int8Array); diff --git a/test/sequential/test-util-debug.js b/test/sequential/test-util-debug.js index e6e4cbb5a5..1af9a7705a 100644 --- a/test/sequential/test-util-debug.js +++ b/test/sequential/test-util-debug.js @@ -26,7 +26,12 @@ function test(environ, shouldWrite) { var spawn = require('child_process').spawn; 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);