From 5e825d1073b57a87fc9a77751ed3e21c86970082 Mon Sep 17 00:00:00 2001 From: Glen Keane Date: Thu, 22 Jan 2015 12:35:16 +0000 Subject: [PATCH] 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 Reviewed-By: Ryan Graham Reviewed-By: Stephen Belanger --- Makefile | 3 +- configure | 14 ++ lib/_http_client.js | 2 + lib/_http_server.js | 2 + lib/net.js | 2 + node.gyp | 12 ++ src/node.cc | 8 + src/node_lttng.cc | 266 +++++++++++++++++++++++++++++ src/node_lttng.h | 40 +++++ src/node_lttng_provider.h | 100 +++++++++++ src/node_lttng_tp.h | 130 ++++++++++++++ src/nolttng_macros.py | 9 + test/common.js | 9 + test/sequential/test-util-debug.js | 7 +- 14 files changed, 602 insertions(+), 2 deletions(-) create mode 100644 src/node_lttng.cc create mode 100644 src/node_lttng.h create mode 100644 src/node_lttng_provider.h create mode 100644 src/node_lttng_tp.h create mode 100644 src/nolttng_macros.py diff --git a/Makefile b/Makefile index fdbf4d7179144d..39741096f1d3ad 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 e85621e9cb4af0..d63232626c7d1e 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 6804157ee0a4dc..b02ab66b294d13 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 d8b979943841e1..99903024c26d14 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 af8c3dd8feb68e..030083d3f40983 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 2874f130945b16..8506b286853145 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 4386d372b7460c..fd65fbff0bddf3 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 00000000000000..0c63882c793ec4 --- /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 00000000000000..31f706f7582402 --- /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 00000000000000..22dd935a95f464 --- /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 00000000000000..53d04f47a80e5a --- /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 00000000000000..cefd80507e1026 --- /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 1599de07be8177..352f7b676471af 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 e6e4cbb5a5f806..1af9a7705a104a 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);