summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/node.cc12
-rw-r--r--src/node_dtrace.cc9
-rw-r--r--src/node_win32_etw_provider-inl.h141
-rw-r--r--src/node_win32_etw_provider.cc91
-rw-r--r--src/node_win32_etw_provider.h82
-rw-r--r--src/res/node_etw_provider.man102
6 files changed, 434 insertions, 3 deletions
diff --git a/src/node.cc b/src/node.cc
index 5db4d86c28..d478f06e76 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -26,10 +26,14 @@
#include "uv.h"
#include "v8-debug.h"
-#ifdef HAVE_DTRACE
+#if defined HAVE_DTRACE || defined HAVE_ETW
# include "node_dtrace.h"
#endif
+#ifdef HAVE_ETW
+# include "node_win32_etw_provider.h"
+#endif
+
#include <locale.h>
#include <signal.h>
#include <stdio.h>
@@ -2325,7 +2329,7 @@ void Load(Handle<Object> process_l) {
Local<Object> global = v8::Context::GetCurrent()->Global();
Local<Value> args[1] = { Local<Value>::New(process_l) };
-#ifdef HAVE_DTRACE
+#if defined HAVE_DTRACE || defined HAVE_ETW
InitDTrace(global);
#endif
@@ -2894,6 +2898,10 @@ int Start(int argc, char *argv[]) {
// watchers, it blocks.
uv_run(uv_default_loop());
+#ifdef HAVE_ETW
+ shutdown_etw();
+#endif
+
EmitExit(process_l);
RunAtExit();
diff --git a/src/node_dtrace.cc b/src/node_dtrace.cc
index 01ea7b87fd..e560999c52 100644
--- a/src/node_dtrace.cc
+++ b/src/node_dtrace.cc
@@ -24,6 +24,9 @@
#ifdef HAVE_DTRACE
#include "node_provider.h"
+#elif HAVE_ETW
+#include "node_win32_etw_provider.h"
+#include "node_win32_etw_provider-inl.h"
#else
#define NODE_HTTP_SERVER_REQUEST(arg0, arg1)
#define NODE_HTTP_SERVER_REQUEST_ENABLED() (0)
@@ -315,7 +318,11 @@ void InitDTrace(Handle<Object> target) {
target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction());
}
-#ifdef HAVE_DTRACE
+#ifdef HAVE_ETW
+ init_etw();
+#endif
+
+#if defined HAVE_DTRACE || defined HAVE_ETW
v8::V8::AddGCPrologueCallback((GCPrologueCallback)dtrace_gc_start);
v8::V8::AddGCEpilogueCallback((GCEpilogueCallback)dtrace_gc_done);
#endif
diff --git a/src/node_win32_etw_provider-inl.h b/src/node_win32_etw_provider-inl.h
new file mode 100644
index 0000000000..70b04acba1
--- /dev/null
+++ b/src/node_win32_etw_provider-inl.h
@@ -0,0 +1,141 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef SRC_ETW_INL_H_
+#define SRC_ETW_INL_H_
+
+#include "node_win32_etw_provider.h"
+#include "node_etw_provider.h"
+
+namespace node {
+
+using namespace v8;
+
+// From node_win32_etw_provider.cc
+extern REGHANDLE node_provider;
+extern EventWriteFunc event_write;
+extern int events_enabled;
+
+#define ETW_WRITE_STRING_DATA(data_descriptor, data) \
+ EventDataDescCreate(data_descriptor, \
+ data, \
+ (strlen(data) + 1) * sizeof(char));
+
+#define ETW_WRITE_INT32_DATA(data_descriptor, data) \
+ EventDataDescCreate(data_descriptor, data, sizeof(int32_t));
+
+#define ETW_WRITE_NET_CONNECTION(descriptors, conn) \
+ ETW_WRITE_INT32_DATA(descriptors, &conn->fd); \
+ ETW_WRITE_INT32_DATA(descriptors + 1, &conn->port); \
+ ETW_WRITE_STRING_DATA(descriptors + 2, conn->remote); \
+ ETW_WRITE_INT32_DATA(descriptors + 3, &conn->buffered);
+
+#define ETW_WRITE_HTTP_SERVER_REQUEST(descriptors, req) \
+ ETW_WRITE_STRING_DATA(descriptors, req->url); \
+ ETW_WRITE_STRING_DATA(descriptors + 1, req->method); \
+ ETW_WRITE_STRING_DATA(descriptors + 2, req->forwardedFor);
+
+#define ETW_WRITE_HTTP_CLIENT_REQUEST(descriptors, req) \
+ ETW_WRITE_STRING_DATA(descriptors, req->url); \
+ ETW_WRITE_STRING_DATA(descriptors + 1, req->method);
+
+#define ETW_WRITE_GC(descriptors, type, flags) \
+ ETW_WRITE_INT32_DATA(descriptors, &type); \
+ ETW_WRITE_INT32_DATA(descriptors + 1, &flags);
+
+#define ETW_WRITE_EVENT(eventDescriptor, dataDescriptors) \
+ DWORD status = event_write(node_provider, \
+ &eventDescriptor, \
+ sizeof(dataDescriptors)/sizeof(*dataDescriptors),\
+ dataDescriptors); \
+ assert(status == ERROR_SUCCESS);
+
+
+void NODE_HTTP_SERVER_REQUEST(node_dtrace_http_server_request_t* req,
+ node_dtrace_connection_t* conn) {
+ EVENT_DATA_DESCRIPTOR descriptors[7];
+ ETW_WRITE_HTTP_SERVER_REQUEST(descriptors, req);
+ ETW_WRITE_NET_CONNECTION(descriptors + 3, conn);
+ ETW_WRITE_EVENT(NODE_HTTP_SERVER_REQUEST_EVENT, descriptors);
+}
+
+
+void NODE_HTTP_SERVER_RESPONSE(node_dtrace_connection_t* conn) {
+ EVENT_DATA_DESCRIPTOR descriptors[4];
+ ETW_WRITE_NET_CONNECTION(descriptors, conn);
+ ETW_WRITE_EVENT(NODE_HTTP_SERVER_RESPONSE_EVENT, descriptors);
+}
+
+
+void NODE_HTTP_CLIENT_REQUEST(node_dtrace_http_client_request_t* req,
+ node_dtrace_connection_t* conn) {
+ EVENT_DATA_DESCRIPTOR descriptors[6];
+ ETW_WRITE_HTTP_CLIENT_REQUEST(descriptors, req);
+ ETW_WRITE_NET_CONNECTION(descriptors + 2, conn);
+ ETW_WRITE_EVENT(NODE_HTTP_CLIENT_REQUEST_EVENT, descriptors);
+}
+
+
+void NODE_HTTP_CLIENT_RESPONSE(node_dtrace_connection_t* conn) {
+ EVENT_DATA_DESCRIPTOR descriptors[4];
+ ETW_WRITE_NET_CONNECTION(descriptors, conn);
+ ETW_WRITE_EVENT(NODE_HTTP_CLIENT_RESPONSE_EVENT, descriptors);
+}
+
+
+void NODE_NET_SERVER_CONNECTION(node_dtrace_connection_t* conn) {
+ EVENT_DATA_DESCRIPTOR descriptors[4];
+ ETW_WRITE_NET_CONNECTION(descriptors, conn);
+ ETW_WRITE_EVENT(NODE_NET_SERVER_CONNECTION_EVENT, descriptors);
+}
+
+
+void NODE_NET_STREAM_END(node_dtrace_connection_t* conn) {
+ EVENT_DATA_DESCRIPTOR descriptors[4];
+ ETW_WRITE_NET_CONNECTION(descriptors, conn);
+ ETW_WRITE_EVENT(NODE_NET_STREAM_END_EVENT, descriptors);
+}
+
+
+void NODE_GC_START(GCType type, GCCallbackFlags flags) {
+ EVENT_DATA_DESCRIPTOR descriptors[2];
+ ETW_WRITE_GC(descriptors, type, flags);
+ ETW_WRITE_EVENT(NODE_GC_START_EVENT, descriptors);
+}
+
+
+void NODE_GC_DONE(GCType type, GCCallbackFlags flags) {
+ EVENT_DATA_DESCRIPTOR descriptors[2];
+ ETW_WRITE_GC(descriptors, type, flags);
+ ETW_WRITE_EVENT(NODE_GC_DONE_EVENT, descriptors);
+}
+
+
+bool NODE_HTTP_SERVER_REQUEST_ENABLED() { return events_enabled > 0; }
+bool NODE_HTTP_SERVER_RESPONSE_ENABLED() { return events_enabled > 0; }
+bool NODE_HTTP_CLIENT_REQUEST_ENABLED() { return events_enabled > 0; }
+bool NODE_HTTP_CLIENT_RESPONSE_ENABLED() { return events_enabled > 0; }
+bool NODE_NET_SERVER_CONNECTION_ENABLED() { return events_enabled > 0; }
+bool NODE_NET_STREAM_END_ENABLED() { return events_enabled > 0; }
+bool NODE_NET_SOCKET_READ_ENABLED() { return events_enabled > 0; }
+bool NODE_NET_SOCKET_WRITE_ENABLED() { return events_enabled > 0; }
+}
+#endif // SRC_ETW_INL_H_ \ No newline at end of file
diff --git a/src/node_win32_etw_provider.cc b/src/node_win32_etw_provider.cc
new file mode 100644
index 0000000000..78f465c466
--- /dev/null
+++ b/src/node_win32_etw_provider.cc
@@ -0,0 +1,91 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#include "node_dtrace.h"
+#include "node_win32_etw_provider.h"
+#include "node_etw_provider.h"
+
+namespace node {
+
+using namespace v8;
+
+HMODULE advapi;
+REGHANDLE node_provider;
+EventRegisterFunc event_register;
+EventUnregisterFunc event_unregister;
+EventWriteFunc event_write;
+int events_enabled;
+
+// This callback is called by ETW when consumers of our provider
+// are enabled or disabled.
+// The callback is dispatched on ETW thread.
+void NTAPI etw_events_enable_callback(
+ LPCGUID SourceId,
+ ULONG IsEnabled,
+ UCHAR Level,
+ ULONGLONG MatchAnyKeyword,
+ ULONGLONG MatchAllKeywords,
+ PEVENT_FILTER_DESCRIPTOR FilterData,
+ PVOID CallbackContext) {
+ if (IsEnabled) {
+ events_enabled++;
+ } else {
+ events_enabled--;
+ }
+}
+
+
+void init_etw() {
+ events_enabled = 0;
+
+ advapi = LoadLibrary("advapi32.dll");
+ if (advapi) {
+ event_register = (EventRegisterFunc)
+ GetProcAddress(advapi, "EventRegister");
+ event_unregister = (EventUnregisterFunc)
+ GetProcAddress(advapi, "EventUnregister");
+ event_write = (EventWriteFunc)GetProcAddress(advapi, "EventWrite");
+
+ if (event_register) {
+ DWORD status = event_register(&NODE_ETW_PROVIDER,
+ etw_events_enable_callback,
+ NULL,
+ &node_provider);
+ assert(status == ERROR_SUCCESS);
+ }
+ }
+}
+
+
+void shutdown_etw() {
+ if (advapi && event_unregister && node_provider) {
+ event_unregister(node_provider);
+ node_provider = 0;
+ }
+
+ events_enabled = 0;
+
+ if (advapi) {
+ FreeLibrary(advapi);
+ advapi = NULL;
+ }
+}
+} \ No newline at end of file
diff --git a/src/node_win32_etw_provider.h b/src/node_win32_etw_provider.h
new file mode 100644
index 0000000000..adfff37e56
--- /dev/null
+++ b/src/node_win32_etw_provider.h
@@ -0,0 +1,82 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef SRC_ETW_H_
+#define SRC_ETW_H_
+
+#include <evntprov.h>
+#include "node_dtrace.h"
+
+namespace node {
+
+using namespace v8;
+
+#if defined(_MSC_VER)
+# define INLINE __forceinline
+#else
+# define INLINE inline
+#endif
+
+typedef ULONG (NTAPI *EventRegisterFunc)(
+ LPCGUID ProviderId,
+ PENABLECALLBACK EnableCallback,
+ PVOID CallbackContext,
+ PREGHANDLE RegHandle
+);
+
+typedef ULONG (NTAPI *EventUnregisterFunc)(
+ REGHANDLE RegHandle
+);
+
+typedef ULONG (NTAPI *EventWriteFunc)(
+ REGHANDLE RegHandle,
+ PCEVENT_DESCRIPTOR EventDescriptor,
+ ULONG UserDataCount,
+ PEVENT_DATA_DESCRIPTOR UserData
+);
+
+void init_etw();
+void shutdown_etw();
+
+INLINE void NODE_HTTP_SERVER_REQUEST(node_dtrace_http_server_request_t* req,
+ node_dtrace_connection_t* conn);
+INLINE void NODE_HTTP_SERVER_RESPONSE(node_dtrace_connection_t* conn);
+INLINE void NODE_HTTP_CLIENT_REQUEST(node_dtrace_http_client_request_t* req,
+ node_dtrace_connection_t* conn);
+INLINE void NODE_HTTP_CLIENT_RESPONSE(node_dtrace_connection_t* conn);
+INLINE void NODE_NET_SERVER_CONNECTION(node_dtrace_connection_t* conn);
+INLINE void NODE_NET_STREAM_END(node_dtrace_connection_t* conn);
+INLINE void NODE_GC_START(GCType type, GCCallbackFlags flags);
+INLINE void NODE_GC_DONE(GCType type, GCCallbackFlags flags);
+
+INLINE bool NODE_HTTP_SERVER_REQUEST_ENABLED();
+INLINE bool NODE_HTTP_SERVER_RESPONSE_ENABLED();
+INLINE bool NODE_HTTP_CLIENT_REQUEST_ENABLED();
+INLINE bool NODE_HTTP_CLIENT_RESPONSE_ENABLED();
+INLINE bool NODE_NET_SERVER_CONNECTION_ENABLED();
+INLINE bool NODE_NET_STREAM_END_ENABLED();
+INLINE bool NODE_NET_SOCKET_READ_ENABLED();
+INLINE bool NODE_NET_SOCKET_WRITE_ENABLED();
+
+#define NODE_NET_SOCKET_READ(arg0, arg1)
+#define NODE_NET_SOCKET_WRITE(arg0, arg1)
+}
+#endif // SRC_ETW_H_ \ No newline at end of file
diff --git a/src/res/node_etw_provider.man b/src/res/node_etw_provider.man
new file mode 100644
index 0000000000..2d96a20c31
--- /dev/null
+++ b/src/res/node_etw_provider.man
@@ -0,0 +1,102 @@
+<instrumentationManifest
+ xmlns="http://schemas.microsoft.com/win/2004/08/events"
+ xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <instrumentation>
+ <events>
+ <provider name="NodeJS-ETW-provider"
+ guid="{77754E9B-264B-4D8D-B981-E4135C1ECB0C}"
+ symbol="NODE_ETW_PROVIDER"
+ resourceFileName="node.exe"
+ messageFileName="node.exe">
+
+ <opcodes>
+ <opcode name="NODE_HTTP_SERVER_REQUEST" value="10"/>
+ <opcode name="NODE_HTTP_SERVER_RESPONSE" value="11"/>
+ <opcode name="NODE_HTTP_CLIENT_REQUEST" value="12"/>
+ <opcode name="NODE_HTTP_CLIENT_RESPONSE" value="13"/>
+ <opcode name="NODE_NET_SERVER_CONNECTION" value="14"/>
+ <opcode name="NODE_NET_STREAM_END" value="15"/>
+ <opcode name="NODE_GC_START" value="16"/>
+ <opcode name="NODE_GC_DONE" value="17"/>
+ </opcodes>
+
+ <templates>
+ <template tid="node_connection">
+ <data name="fd" inType="win:UInt32" />
+ <data name="port" inType="win:UInt32" />
+ <data name="remote" inType="win:AnsiString" />
+ <data name="buffered" inType="win:UInt32" />
+ </template>
+
+ <template tid="node_http_client_request">
+ <data name="url" inType="win:AnsiString" />
+ <data name="method" inType="win:AnsiString" />
+ <data name="fd" inType="win:UInt32" />
+ <data name="port" inType="win:UInt32" />
+ <data name="remote" inType="win:AnsiString" />
+ <data name="buffered" inType="win:UInt32" />
+ </template>
+
+ <template tid="node_http_server_request">
+ <data name="url" inType="win:AnsiString" />
+ <data name="method" inType="win:AnsiString" />
+ <data name="forwardedFor" inType="win:AnsiString" />
+ <data name="fd" inType="win:UInt32" />
+ <data name="port" inType="win:UInt32" />
+ <data name="remote" inType="win:AnsiString" />
+ <data name="buffered" inType="win:UInt32" />
+ </template>
+
+ <template tid="node_gc">
+ <data name="gctype" inType="win:UInt32" />
+ <data name="gccallbackflags" inType="win:UInt32" />
+ </template>
+ </templates>
+
+ <events>
+ <event value="1"
+ opcode="NODE_HTTP_SERVER_REQUEST"
+ template="node_http_server_request"
+ symbol="NODE_HTTP_SERVER_REQUEST_EVENT"
+ level="win:Informational"/>
+ <event value="2"
+ opcode="NODE_HTTP_SERVER_RESPONSE"
+ template="node_connection"
+ symbol="NODE_HTTP_SERVER_RESPONSE_EVENT"
+ level="win:Informational"/>
+ <event value="3"
+ opcode="NODE_HTTP_CLIENT_REQUEST"
+ template="node_http_client_request"
+ symbol="NODE_HTTP_CLIENT_REQUEST_EVENT"
+ level="win:Informational"/>
+ <event value="4"
+ opcode="NODE_HTTP_CLIENT_RESPONSE"
+ template="node_connection"
+ symbol="NODE_HTTP_CLIENT_RESPONSE_EVENT"
+ level="win:Informational"/>
+ <event value="5"
+ opcode="NODE_NET_SERVER_CONNECTION"
+ template="node_connection"
+ symbol="NODE_NET_SERVER_CONNECTION_EVENT"
+ level="win:Informational"/>
+ <event value="6"
+ opcode="NODE_NET_STREAM_END"
+ template="node_connection"
+ symbol="NODE_NET_STREAM_END_EVENT"
+ level="win:Informational"/>
+ <event value="7"
+ opcode="NODE_GC_START"
+ template="node_gc"
+ symbol="NODE_GC_START_EVENT"
+ level="win:Informational"/>
+ <event value="8"
+ opcode="NODE_GC_DONE"
+ template="node_gc"
+ symbol="NODE_GC_DONE_EVENT"
+ level="win:Informational"/>
+ </events>
+ </provider>
+ </events>
+ </instrumentation>
+</instrumentationManifest>