From 54d42e059c74f43f58ee1a63267813416527b867 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 7 Mar 2018 16:00:13 -0800 Subject: [PATCH 1/6] trace_events: enable trace events implicitly, add module Enable trace events to be turned on if `--trace-event-categories` is set even if `--trace-events-enabled` is not used. Using `--trace-events-enabled` will still work and will still set the default categories to `v8,node,node.async_hooks`, but the boolean flag is not required to enable the tracing agent. Also, add trace_events module and API Allows trace event collection to be turned on/off at runtime via a new top level `trace_events` module. --- doc/api/errors.md | 5 ++ doc/api/tracing.md | 52 ++++++++++++---- lib/internal/errors.js | 1 + lib/trace_events.js | 34 +++++++++++ node.gyp | 1 + src/node.cc | 74 ++++++++++++----------- src/node_config.cc | 4 ++ src/node_internals.h | 5 ++ src/node_trace_events.cc | 39 ++++++++++++ src/tracing/agent.cc | 50 ++++++++------- src/tracing/agent.h | 8 ++- test/parallel/test-trace-events-module.js | 65 ++++++++++++++++++++ 12 files changed, 269 insertions(+), 69 deletions(-) create mode 100644 lib/trace_events.js create mode 100644 test/parallel/test-trace-events-module.js diff --git a/doc/api/errors.md b/doc/api/errors.md index 7d6e238f93bdaa..6377e77d1247a9 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1510,6 +1510,11 @@ socket, which is only valid from a client. An attempt was made to renegotiate TLS on a socket instance with TLS disabled. + +### ERR_TRACE_EVENTS_UNAVAILABLE + +The trace events mechanism is not available for use in the Node.js binary. + ### ERR_TRANSFORM_ALREADY_TRANSFORMING diff --git a/doc/api/tracing.md b/doc/api/tracing.md index ef58eb72bac217..d8e5b42aafbd0a 100644 --- a/doc/api/tracing.md +++ b/doc/api/tracing.md @@ -5,12 +5,9 @@ Trace Event provides a mechanism to centralize tracing information generated by V8, Node.js core, and userspace code. -Tracing can be enabled by passing the `--trace-events-enabled` flag when -starting a Node.js application. - -The set of categories for which traces are recorded can be specified using the -`--trace-event-categories` flag followed by a list of comma separated category -names. +Tracing can be enabled either by using the `--trace-event-categories` flag +followed by a list of comma separated category names, or by using the +`trace_events.setTracingCategories()` method. The available categories are: @@ -23,15 +20,17 @@ The available categories are: measurements. * `v8` -By default the `node`, `node.async_hooks`, and `v8` categories are enabled. - ```txt -node --trace-events-enabled --trace-event-categories v8,node,node.async_hooks server.js +node --trace-event-categories v8,node,node.async_hooks server.js +``` + +```js +const trace_events = require('trace_events'); +trace_events.setTracingCategories('v8,node,node.async_hooks'); ``` Running Node.js with tracing enabled will produce log files that can be opened -in the [`chrome://tracing`](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool) -tab of Chrome. +in the [`chrome://tracing`][] tab of Chrome. The logging file is by default called `node_trace.${rotation}.log`, where `${rotation}` is an incrementing log-rotation id. The filepath pattern can @@ -47,4 +46,35 @@ as the one used by `process.hrtime()` however the trace-event timestamps are expressed in microseconds, unlike `process.hrtime()` which returns nanoseconds. +## The `trace_events` module + +The `trace_events` module may be used to turn trace event reporting on and off. + +It is accessible using `require('trace_events')`. + +### trace_events.setTracingCategories(categories) + +* `categories` [string] A comma-separated list of category names. If + `categories` is `undefined`, `null`, or an empty string, capture of trace + events will be stopped. + +Sets the currently enabled trace event category names and enables trace event +capture. + +An error will be thrown if trace event support is not enabled in the Node.js +binary. + +### trace_events.getTracingCategories() + +* Return: [string] + +Returns the current list of category names as a comma-separated list or +`undefined`. + +```js +const trace_events = require('trace_events'); +console.log(trace_events.getTracingCategories()); +``` + +[`chrome://tracing`]: https://www.chromium.org/developers/how-tos/trace-event-profiling-tool [Performance API]: perf_hooks.html diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 8ec72dd647b1b2..58a821059fff2f 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -866,6 +866,7 @@ E('ERR_TLS_REQUIRED_SERVER_NAME', E('ERR_TLS_SESSION_ATTACK', 'TLS session renegotiation attack detected', Error); E('ERR_TLS_SNI_FROM_SERVER', 'Cannot issue SNI from a TLS server-side socket', Error); +E('ERR_TRACE_EVENTS_UNAVAILABLE', 'Trace events are not available', Error); E('ERR_TRANSFORM_ALREADY_TRANSFORMING', 'Calling transform done when still transforming', Error); diff --git a/lib/trace_events.js b/lib/trace_events.js new file mode 100644 index 00000000000000..beae4ea80e25f5 --- /dev/null +++ b/lib/trace_events.js @@ -0,0 +1,34 @@ +'use strict'; + +const { + startTracing, + stopTracing, + getTracingCategories +} = process.binding('trace_events'); + +const { trace_events_enabled } = process.binding('config'); + +const { + codes: { + ERR_INVALID_ARG_TYPE, + ERR_TRACE_EVENTS_UNAVAILABLE + } +} = require('internal/errors'); + +function setTracingCategories(categories) { + if (!trace_events_enabled) + throw new ERR_TRACE_EVENTS_UNAVAILABLE(); + + if (categories == null || categories === '') + return stopTracing(); + + if (typeof categories !== 'string') + throw new ERR_INVALID_ARG_TYPE('categories', 'string'); + + startTracing(categories); +} + +module.exports = { + setTracingCategories, + getTracingCategories +}; diff --git a/node.gyp b/node.gyp index ce8125ecc39d39..373e373aa29b58 100644 --- a/node.gyp +++ b/node.gyp @@ -73,6 +73,7 @@ 'lib/tls.js', 'lib/_tls_common.js', 'lib/_tls_wrap.js', + 'lib/trace_events.js', 'lib/tty.js', 'lib/url.js', 'lib/util.js', diff --git a/src/node.cc b/src/node.cc index 2e44e249a0d5fd..e4dea81b9becae 100644 --- a/src/node.cc +++ b/src/node.cc @@ -190,8 +190,8 @@ static node_module* modlist_builtin; static node_module* modlist_internal; static node_module* modlist_linked; static node_module* modlist_addon; -static bool trace_enabled = false; -static std::string trace_enabled_categories; // NOLINT(runtime/string) + +std::string trace_enabled_categories; // NOLINT(runtime/string) static std::string trace_file_pattern = // NOLINT(runtime/string) "node_trace.${rotation}.log"; static bool abort_on_uncaught_exception = false; @@ -276,20 +276,11 @@ DebugOptions debug_options; static struct { #if NODE_USE_V8_PLATFORM void Initialize(int thread_pool_size) { - if (trace_enabled) { - tracing_agent_.reset(new tracing::Agent(trace_file_pattern)); - platform_ = new NodePlatform(thread_pool_size, - tracing_agent_->GetTracingController()); - V8::InitializePlatform(platform_); - tracing::TraceEventHelper::SetTracingController( - tracing_agent_->GetTracingController()); - } else { - tracing_agent_.reset(nullptr); - platform_ = new NodePlatform(thread_pool_size, nullptr); - V8::InitializePlatform(platform_); - tracing::TraceEventHelper::SetTracingController( - new v8::TracingController()); - } + tracing_agent_.reset(new tracing::Agent(trace_file_pattern)); + v8::TracingController* controller = tracing_agent_->GetTracingController(); + platform_ = new NodePlatform(thread_pool_size, controller); + tracing::TraceEventHelper::SetTracingController(controller); + V8::InitializePlatform(platform_); } void Dispose() { @@ -322,7 +313,12 @@ static struct { #endif // HAVE_INSPECTOR void StartTracingAgent() { - tracing_agent_->Start(trace_enabled_categories); + if (!trace_enabled_categories.empty()) + tracing_agent_->StartTracing(trace_enabled_categories); + } + + void StopTracing() { + tracing_agent_->StopTracing(); } void StopTracingAgent() { @@ -346,10 +342,8 @@ static struct { return true; } - void StartTracingAgent() { - fprintf(stderr, "Node compiled with NODE_USE_V8_PLATFORM=0, " - "so event tracing is not available.\n"); - } + void StartTracingAgent() {} + void StopTracing() {} void StopTracingAgent() {} NodePlatform* Platform() { @@ -364,6 +358,16 @@ static struct { #endif // !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR } v8_platform; +void StartTracing(const std::string& enabled_categories) { + trace_enabled_categories = enabled_categories; + v8_platform.StartTracingAgent(); +} + +void StopTracing() { + trace_enabled_categories.erase(); + v8_platform.StopTracing(); +} + #ifdef __POSIX__ static const unsigned kMaxSignal = 32; #endif @@ -1987,9 +1991,7 @@ static void WaitForInspectorDisconnect(Environment* env) { static void Exit(const FunctionCallbackInfo& args) { WaitForInspectorDisconnect(Environment::GetCurrent(args)); - if (trace_enabled) { - v8_platform.StopTracingAgent(); - } + v8_platform.StopTracingAgent(); exit(args[0]->Int32Value()); } @@ -3287,9 +3289,7 @@ void SetupProcessObject(Environment* env, void SignalExit(int signo) { uv_tty_reset_mode(); - if (trace_enabled) { - v8_platform.StopTracingAgent(); - } + v8_platform.StopTracingAgent(); #ifdef __FreeBSD__ // FreeBSD has a nasty bug, see RegisterSignalHandler for details struct sigaction sa; @@ -3491,6 +3491,7 @@ static void PrintHelp() { " is detected after the first tick\n" " --no-force-async-hooks-checks\n" " disable checks for async_hooks\n" +#if NODE_USE_V8_PLATFORM " --trace-events-enabled track trace events\n" " --trace-event-categories comma separated list of trace event\n" " categories to record\n" @@ -3498,6 +3499,7 @@ static void PrintHelp() { " filepath for the trace-events data, it\n" " supports ${rotation} and ${pid}\n" " log-rotation id. %%2$u is the pid.\n" +#endif " --track-heap-objects track heap object allocations for heap " "snapshots\n" " --prof-process process v8 profiler output generated\n" @@ -3624,9 +3626,11 @@ static void CheckIfAllowedInEnv(const char* exe, bool is_env, "--redirect-warnings", "--trace-sync-io", "--no-force-async-hooks-checks", +#if NODE_USE_V8_PLATFORM "--trace-events-enabled", "--trace-event-categories", "--trace-event-file-pattern", +#endif "--track-heap-objects", "--zero-fill-buffers", "--v8-pool-size", @@ -3768,8 +3772,11 @@ static void ParseArgs(int* argc, trace_sync_io = true; } else if (strcmp(arg, "--no-force-async-hooks-checks") == 0) { no_force_async_hooks_checks = true; +#if NODE_USE_V8_PLATFORM } else if (strcmp(arg, "--trace-events-enabled") == 0) { - trace_enabled = true; + if (trace_enabled_categories.empty()) { + trace_enabled_categories = "v8,node,node.async_hooks"; + } } else if (strcmp(arg, "--trace-event-categories") == 0) { const char* categories = argv[index + 1]; if (categories == nullptr) { @@ -3786,6 +3793,7 @@ static void ParseArgs(int* argc, } args_consumed += 1; trace_file_pattern = file_pattern; +#endif } else if (strcmp(arg, "--track-heap-objects") == 0) { track_heap_objects = true; } else if (strcmp(arg, "--throw-deprecation") == 0) { @@ -4595,19 +4603,13 @@ int Start(int argc, char** argv) { v8_platform.Initialize(v8_thread_pool_size); // Enable tracing when argv has --trace-events-enabled. - if (trace_enabled) { - fprintf(stderr, "Warning: Trace event is an experimental feature " - "and could change at any time.\n"); - v8_platform.StartTracingAgent(); - } + v8_platform.StartTracingAgent(); V8::Initialize(); performance::performance_v8_start = PERFORMANCE_NOW(); v8_initialized = true; const int exit_code = Start(uv_default_loop(), argc, argv, exec_argc, exec_argv); - if (trace_enabled) { - v8_platform.StopTracingAgent(); - } + v8_platform.StopTracingAgent(); v8_initialized = false; V8::Dispose(); diff --git a/src/node_config.cc b/src/node_config.cc index cac551ad2c410a..47667a2521e32d 100644 --- a/src/node_config.cc +++ b/src/node_config.cc @@ -82,6 +82,10 @@ static void InitConfig(Local target, } } +#if NODE_USE_V8_PLATFORM + READONLY_BOOLEAN_PROPERTY("trace_events_enabled"); +#endif + if (config_experimental_vm_modules) READONLY_BOOLEAN_PROPERTY("experimentalVMModules"); diff --git a/src/node_internals.h b/src/node_internals.h index 2faa6f93475ad7..3f72ca84673384 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -196,6 +196,8 @@ extern bool config_expose_internals; // it to stderr. extern std::string config_warning_file; // NOLINT(runtime/string) +extern std::string trace_enabled_categories; // NOLINT(runtime/string) + // Set in node.cc by ParseArgs when --pending-deprecation or // NODE_PENDING_DEPRECATION is used extern bool config_pending_deprecation; @@ -785,6 +787,9 @@ static inline const char *errno_string(int errorno) { TRACING_CATEGORY_NODE "." #one "," \ TRACING_CATEGORY_NODE "." #one "." #two +extern void StartTracing(const std::string& enabled_categories); +extern void StopTracing(); + } // namespace node diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index f269b32fbef869..1017fc2b3c286a 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -8,6 +8,7 @@ using v8::FunctionCallbackInfo; using v8::Int32; using v8::Local; using v8::Object; +using v8::String; using v8::Value; // The tracing APIs require category groups to be pointers to long-lived @@ -132,6 +133,41 @@ static void CategoryGroupEnabled(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(*category_group_enabled > 0); } +static void StartTracing(const FunctionCallbackInfo& args) { +#if NODE_USE_V8_PLATFORM + Environment* env = Environment::GetCurrent(args); + Utf8Value categories(env->isolate(), args[0]); + std::string enabled_categories; + if (categories.length() > 0) + enabled_categories = *categories; + + node::StartTracing(enabled_categories); +#elif + UNREACHABLE(); +#endif +} + +static void StopTracing(const FunctionCallbackInfo& args) { +#if NODE_USE_V8_PLATFORM + node::StopTracing(); +#elif + UNREACHABLE(); +#endif +} + +static void GetTracingCategories(const FunctionCallbackInfo& args) { +#if NODE_USE_V8_PLATFORM + Environment* env = Environment::GetCurrent(args); + if (!trace_enabled_categories.empty()) { + Local categories = + String::NewFromUtf8(env->isolate(), + trace_enabled_categories.data(), + v8::NewStringType::kNormal).ToLocalChecked(); + return args.GetReturnValue().Set(categories); + } +#endif +} + void InitializeTraceEvents(Local target, Local unused, Local context, @@ -140,6 +176,9 @@ void InitializeTraceEvents(Local target, env->SetMethod(target, "emit", Emit); env->SetMethod(target, "categoryGroupEnabled", CategoryGroupEnabled); + env->SetMethod(target, "startTracing", StartTracing); + env->SetMethod(target, "stopTracing", StopTracing); + env->SetMethod(target, "getTracingCategories", GetTracingCategories); } } // namespace node diff --git a/src/tracing/agent.cc b/src/tracing/agent.cc index 71e53e787a464e..0d059475ce6e81 100644 --- a/src/tracing/agent.cc +++ b/src/tracing/agent.cc @@ -13,55 +13,63 @@ namespace tracing { using v8::platform::tracing::TraceConfig; using std::string; -Agent::Agent(const std::string& log_file_pattern) { +Agent::Agent(const std::string& log_file_pattern) : + log_file_pattern_(log_file_pattern) { + tracing_controller_ = new TracingController(); + tracing_controller_->Initialize(nullptr); +} + +void Agent::InitializeOnce() { + if (initialized_) + return; int err = uv_loop_init(&tracing_loop_); CHECK_EQ(err, 0); NodeTraceWriter* trace_writer = new NodeTraceWriter( - log_file_pattern, &tracing_loop_); + log_file_pattern_, &tracing_loop_); TraceBuffer* trace_buffer = new NodeTraceBuffer( NodeTraceBuffer::kBufferChunks, trace_writer, &tracing_loop_); - tracing_controller_ = new TracingController(); tracing_controller_->Initialize(trace_buffer); } -void Agent::Start(const string& enabled_categories) { +void Agent::StartTracing(const string& enabled_categories) { TraceConfig* trace_config = new TraceConfig(); + tracing_controller_->StopTracing(); if (!enabled_categories.empty()) { + if (!started_) { + InitializeOnce(); + // This thread should be created *after* async handles are created + // (within NodeTraceWriter and NodeTraceBuffer constructors). + // Otherwise the thread could shut down prematurely. + int err = uv_thread_create(&thread_, ThreadCb, this); + CHECK_EQ(err, 0); + started_ = true; + } std::stringstream category_list(enabled_categories); while (category_list.good()) { std::string category; getline(category_list, category, ','); trace_config->AddIncludedCategory(category.c_str()); } - } else { - trace_config->AddIncludedCategory("v8"); - trace_config->AddIncludedCategory("node"); - trace_config->AddIncludedCategory("node.async_hooks"); + tracing_controller_->StartTracing(trace_config); } +} - // This thread should be created *after* async handles are created - // (within NodeTraceWriter and NodeTraceBuffer constructors). - // Otherwise the thread could shut down prematurely. - int err = uv_thread_create(&thread_, ThreadCb, this); - CHECK_EQ(err, 0); - - tracing_controller_->StartTracing(trace_config); - started_ = true; +void Agent::StopTracing() { + tracing_controller_->StopTracing(); } void Agent::Stop() { - if (!started_) { - return; - } // Perform final Flush on TraceBuffer. We don't want the tracing controller // to flush the buffer again on destruction of the V8::Platform. tracing_controller_->StopTracing(); tracing_controller_->Initialize(nullptr); - started_ = false; // Thread should finish when the tracing loop is stopped. - uv_thread_join(&thread_); + if (started_) { + uv_thread_join(&thread_); + started_ = false; + } } // static diff --git a/src/tracing/agent.h b/src/tracing/agent.h index 9d6bc4e90a35af..97e3171ce023cf 100644 --- a/src/tracing/agent.h +++ b/src/tracing/agent.h @@ -20,16 +20,22 @@ class TracingController : public v8::platform::tracing::TracingController { class Agent { public: explicit Agent(const std::string& log_file_pattern); - void Start(const std::string& enabled_categories); + void StartTracing(const std::string& enabled_categories); + void StopTracing(); void Stop(); TracingController* GetTracingController() { return tracing_controller_; } + uv_once_t init_once_ = UV_ONCE_INIT; + private: + void InitializeOnce(); static void ThreadCb(void* arg); + const std::string& log_file_pattern_; uv_thread_t thread_; uv_loop_t tracing_loop_; + bool initialized_ = false; bool started_ = false; TracingController* tracing_controller_ = nullptr; }; diff --git a/test/parallel/test-trace-events-module.js b/test/parallel/test-trace-events-module.js new file mode 100644 index 00000000000000..62454deca3e146 --- /dev/null +++ b/test/parallel/test-trace-events-module.js @@ -0,0 +1,65 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const cp = require('child_process'); +const path = require('path'); +const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); + +if (process.argv[2] === 'child') { + const trace_events = require('trace_events'); + const { performance } = require('perf_hooks'); + trace_events.setTracingCategories('node.perf.usertiming'); + performance.mark('A'); + performance.mark('B'); + performance.measure('A to B', 'A', 'B'); + trace_events.setTracingCategories(undefined); +} else { + tmpdir.refresh(); + process.chdir(tmpdir.path); + + const expectedMarks = ['A', 'B']; + const expectedBegins = [ + { cat: 'node.perf,node.perf.usertiming', name: 'A to B' } + ]; + const expectedEnds = [ + { cat: 'node.perf,node.perf.usertiming', name: 'A to B' } + ]; + + const proc = cp.fork(__filename, [ 'child' ]); + + proc.once('exit', common.mustCall(() => { + const file = path.join(tmpdir.path, 'node_trace.1.log'); + + assert(common.fileExists(file)); + fs.readFile(file, common.mustCall((err, data) => { + const traces = JSON.parse(data.toString()).traceEvents; + assert.strictEqual(traces.length, + expectedMarks.length + + expectedBegins.length + + expectedEnds.length); + + traces.forEach((trace) => { + assert.strictEqual(trace.pid, proc.pid); + switch (trace.ph) { + case 'R': + assert.strictEqual(trace.cat, 'node.perf,node.perf.usertiming'); + assert.strictEqual(trace.name, expectedMarks.shift()); + break; + case 'b': + const expectedBegin = expectedBegins.shift(); + assert.strictEqual(trace.cat, expectedBegin.cat); + assert.strictEqual(trace.name, expectedBegin.name); + break; + case 'e': + const expectedEnd = expectedEnds.shift(); + assert.strictEqual(trace.cat, expectedEnd.cat); + assert.strictEqual(trace.name, expectedEnd.name); + break; + default: + assert.fail('Unexpected trace event phase'); + } + }); + })); + })); +} From e3108b4a1eb30a05bd30e1eabcff0ecdbc541e5f Mon Sep 17 00:00:00 2001 From: James M Snell Date: Thu, 8 Mar 2018 09:10:52 -0800 Subject: [PATCH 2/6] [Squash] Add requested comment --- test/parallel/test-trace-events-module.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/parallel/test-trace-events-module.js b/test/parallel/test-trace-events-module.js index 62454deca3e146..3544466f6b237b 100644 --- a/test/parallel/test-trace-events-module.js +++ b/test/parallel/test-trace-events-module.js @@ -8,6 +8,13 @@ const tmpdir = require('../common/tmpdir'); if (process.argv[2] === 'child') { const trace_events = require('trace_events'); + // Note: this test is leveraging the fact that perf_hooks + // will emit a very limited number of predictable trace events + // that we can use to quickly verify that trace events are + // enabled. Using the v8 and node.async_hooks targets tend + // to be less predictable in terms of what is actually output + // to the file. That said, if necessary, this test could + // be modified to use any trace event output. const { performance } = require('perf_hooks'); trace_events.setTracingCategories('node.perf.usertiming'); performance.mark('A'); From 422580fe80f64b699f96cb9fe7f3039da8ec6e1c Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 9 Mar 2018 11:56:11 -0800 Subject: [PATCH 3/6] [Squash] Rework module API `trace_events.enableTracingCategories('v8', 'node')` `trace_events.disableTracingCategories('v8')` `trace_events.getTracingCategories()` // return an array --- doc/api/tracing.md | 52 ++++++++++++++++----- lib/trace_events.js | 30 ++++++++---- src/node.cc | 47 +++++++++++++------ src/node_internals.h | 9 ++-- src/node_trace_events.cc | 57 ++++++++++++++++------- src/tracing/agent.cc | 52 ++++++++++++++++----- src/tracing/agent.h | 21 +++++++-- test/parallel/test-trace-events-module.js | 15 ++++-- 8 files changed, 210 insertions(+), 73 deletions(-) diff --git a/doc/api/tracing.md b/doc/api/tracing.md index d8e5b42aafbd0a..24571489e0c426 100644 --- a/doc/api/tracing.md +++ b/doc/api/tracing.md @@ -26,7 +26,7 @@ node --trace-event-categories v8,node,node.async_hooks server.js ```js const trace_events = require('trace_events'); -trace_events.setTracingCategories('v8,node,node.async_hooks'); +trace_events.enableTracingCategories('v8', 'node,node.async_hooks'); ``` Running Node.js with tracing enabled will produce log files that can be opened @@ -38,7 +38,7 @@ be specified with `--trace-event-file-pattern` that accepts a template string that supports `${rotation}` and `${pid}`. For example: ```txt -node --trace-events-enabled --trace-event-file-pattern '${pid}-${rotation}.log' server.js +node --trace-event-file-pattern '${pid}-${rotation}.log' server.js ``` Starting with Node.js 10.0.0, the tracing system uses the same time source @@ -46,30 +46,60 @@ as the one used by `process.hrtime()` however the trace-event timestamps are expressed in microseconds, unlike `process.hrtime()` which returns nanoseconds. +Previous versions of Node.js required use of the `--trace-events-enabled` +command line flag to enable trace event capture. This flag is no longer +required to enable trace events. If it is used, however, trace events are +enabled using the default categories: `v8`, `node`, and `node.async_hooks`. + ## The `trace_events` module The `trace_events` module may be used to turn trace event reporting on and off. It is accessible using `require('trace_events')`. -### trace_events.setTracingCategories(categories) +### trace_events.disableTracingCategories(...categories) + +* `...categories` [string] One or more category names. + +Disables trace event capture for the given set of category names. + +An error will be thrown if trace event support is not enabled in the Node.js +binary. + +```js +const trace_events = require('trace_events'); +trace_events.disableTracingCategories('v8', 'node.async_hooks'); +``` + +To disable all currently enabled trace event categories, the +`trace_events.getTracingCategories()` method may be used together with +`trace_events.disableTracingCategories()`: + +```js +const trace_events = require('trace_events'); +trace_events.disableTracingCategories( + ...trace_events.getTracingCategories()); +``` + +### trace_events.enableTracingCategories(...categories) -* `categories` [string] A comma-separated list of category names. If - `categories` is `undefined`, `null`, or an empty string, capture of trace - events will be stopped. +* `...categories` [string] One or more category names. -Sets the currently enabled trace event category names and enables trace event -capture. +Enables trace event capture for the given set of category names. An error will be thrown if trace event support is not enabled in the Node.js binary. +```js +const trace_events = require('trace_events'); +trace_events.enableTracingCategories('v8', 'node.async_hooks'); +``` + ### trace_events.getTracingCategories() -* Return: [string] +* Return: {string[]} -Returns the current list of category names as a comma-separated list or -`undefined`. +Returns an Array of the currently enabled trace event categories. ```js const trace_events = require('trace_events'); diff --git a/lib/trace_events.js b/lib/trace_events.js index beae4ea80e25f5..22ae4d2deb8f3a 100644 --- a/lib/trace_events.js +++ b/lib/trace_events.js @@ -1,8 +1,8 @@ 'use strict'; const { - startTracing, - stopTracing, + enableTracingCategories: _enableTracingCategories, + disableTracingCategories: _disableTracingCategories, getTracingCategories } = process.binding('trace_events'); @@ -15,20 +15,32 @@ const { } } = require('internal/errors'); -function setTracingCategories(categories) { +function enableTracingCategories(...categories) { if (!trace_events_enabled) throw new ERR_TRACE_EVENTS_UNAVAILABLE(); - if (categories == null || categories === '') - return stopTracing(); + for (var n = 0; n < categories.length; n++) { + if (typeof categories[n] !== 'string') + throw new ERR_INVALID_ARG_TYPE('category', 'string'); + } + + _enableTracingCategories(categories); +} - if (typeof categories !== 'string') - throw new ERR_INVALID_ARG_TYPE('categories', 'string'); +function disableTracingCategories(...categories) { + if (!trace_events_enabled) + throw new ERR_TRACE_EVENTS_UNAVAILABLE(); + + for (var n = 0; n < categories.length; n++) { + if (typeof categories[n] !== 'string') + throw new ERR_INVALID_ARG_TYPE('category', 'string'); + } - startTracing(categories); + _disableTracingCategories(categories); } module.exports = { - setTracingCategories, + enableTracingCategories, + disableTracingCategories, getTracingCategories }; diff --git a/src/node.cc b/src/node.cc index e4dea81b9becae..f48fbed7b11ea4 100644 --- a/src/node.cc +++ b/src/node.cc @@ -190,8 +190,7 @@ static node_module* modlist_builtin; static node_module* modlist_internal; static node_module* modlist_linked; static node_module* modlist_addon; - -std::string trace_enabled_categories; // NOLINT(runtime/string) +static std::string trace_enabled_categories; // NOLINT(runtime/string) static std::string trace_file_pattern = // NOLINT(runtime/string) "node_trace.${rotation}.log"; static bool abort_on_uncaught_exception = false; @@ -312,9 +311,20 @@ static struct { } #endif // HAVE_INSPECTOR - void StartTracingAgent() { - if (!trace_enabled_categories.empty()) - tracing_agent_->StartTracing(trace_enabled_categories); + void EnableTracingCategories(const std::string& categories) { + tracing_agent_->EnableCategories(categories); + } + + void EnableTracingCategories(const std::vector categories) { + tracing_agent_->EnableCategories(categories); + } + + void DisableTracingCategories(const std::vector categories) { + tracing_agent_->DisableCategories(categories); + } + + const std::set& GetEnabledTracingCategories() { + return tracing_agent_->GetEnabledCategories(); } void StopTracing() { @@ -342,13 +352,20 @@ static struct { return true; } - void StartTracingAgent() {} + void EnableTracingCategories(const std::string& categories) {} + void EnableTracingCategories(const std::vector categories) {} + void DisableTracingCategories(const std::vector categories) {} + const std::set& GetEnabledTracingCategories() { + return categories_; + } void StopTracing() {} void StopTracingAgent() {} NodePlatform* Platform() { return nullptr; } + + std::set categories_; #endif // !NODE_USE_V8_PLATFORM #if !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR @@ -358,16 +375,20 @@ static struct { #endif // !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR } v8_platform; -void StartTracing(const std::string& enabled_categories) { - trace_enabled_categories = enabled_categories; - v8_platform.StartTracingAgent(); +void EnableTracingCategories(const std::vector& categories) { + v8_platform.EnableTracingCategories(categories); } -void StopTracing() { - trace_enabled_categories.erase(); - v8_platform.StopTracing(); +void DisableTracingCategories(const std::vector& categories) { + v8_platform.DisableTracingCategories(categories); } +const std::set& GetEnabledTracingCategories() { + return v8_platform.GetEnabledTracingCategories(); +} + +void StopTracing() { v8_platform.StopTracing(); } + #ifdef __POSIX__ static const unsigned kMaxSignal = 32; #endif @@ -4603,7 +4624,7 @@ int Start(int argc, char** argv) { v8_platform.Initialize(v8_thread_pool_size); // Enable tracing when argv has --trace-events-enabled. - v8_platform.StartTracingAgent(); + v8_platform.EnableTracingCategories(trace_enabled_categories); V8::Initialize(); performance::performance_v8_start = PERFORMANCE_NOW(); v8_initialized = true; diff --git a/src/node_internals.h b/src/node_internals.h index 3f72ca84673384..6604abf4eb8938 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -38,6 +38,7 @@ #include #include +#include // Custom constants used by both node_constants.cc and node_zlib.cc #define Z_MIN_WINDOWBITS 8 @@ -196,8 +197,6 @@ extern bool config_expose_internals; // it to stderr. extern std::string config_warning_file; // NOLINT(runtime/string) -extern std::string trace_enabled_categories; // NOLINT(runtime/string) - // Set in node.cc by ParseArgs when --pending-deprecation or // NODE_PENDING_DEPRECATION is used extern bool config_pending_deprecation; @@ -787,7 +786,11 @@ static inline const char *errno_string(int errorno) { TRACING_CATEGORY_NODE "." #one "," \ TRACING_CATEGORY_NODE "." #one "." #two -extern void StartTracing(const std::string& enabled_categories); +extern void EnableTracingCategories( + const std::vector& categories); +extern void DisableTracingCategories( + const std::vector& categories); +extern const std::set& GetEnabledTracingCategories(); extern void StopTracing(); } // namespace node diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index 1017fc2b3c286a..234f3274e16f50 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -3,6 +3,7 @@ namespace node { +using v8::Array; using v8::Context; using v8::FunctionCallbackInfo; using v8::Int32; @@ -133,23 +134,41 @@ static void CategoryGroupEnabled(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(*category_group_enabled > 0); } -static void StartTracing(const FunctionCallbackInfo& args) { +static void EnableTracingCategories(const FunctionCallbackInfo& args) { #if NODE_USE_V8_PLATFORM Environment* env = Environment::GetCurrent(args); - Utf8Value categories(env->isolate(), args[0]); - std::string enabled_categories; - if (categories.length() > 0) - enabled_categories = *categories; - - node::StartTracing(enabled_categories); + CHECK(args[0]->IsArray()); + Local categories = args[0].As(); + size_t length = categories->Length(); + if (length == 0) + return; + std::vector cats; + for (size_t n = 0; n < length; n++) { + Utf8Value val(env->isolate(), + categories->Get(env->context(), n).ToLocalChecked()); + cats.push_back(*val); + } + EnableTracingCategories(cats); #elif UNREACHABLE(); #endif } -static void StopTracing(const FunctionCallbackInfo& args) { +static void DisableTracingCategories(const FunctionCallbackInfo& args) { #if NODE_USE_V8_PLATFORM - node::StopTracing(); + Environment* env = Environment::GetCurrent(args); + CHECK(args[0]->IsArray()); + Local categories = args[0].As(); + size_t length = categories->Length(); + if (length == 0) + return; + std::vector cats; + for (size_t n = 0; n < length; n++) { + Utf8Value val(env->isolate(), + categories->Get(env->context(), n).ToLocalChecked()); + cats.push_back(*val); + } + DisableTracingCategories(cats); #elif UNREACHABLE(); #endif @@ -158,13 +177,16 @@ static void StopTracing(const FunctionCallbackInfo& args) { static void GetTracingCategories(const FunctionCallbackInfo& args) { #if NODE_USE_V8_PLATFORM Environment* env = Environment::GetCurrent(args); - if (!trace_enabled_categories.empty()) { - Local categories = - String::NewFromUtf8(env->isolate(), - trace_enabled_categories.data(), - v8::NewStringType::kNormal).ToLocalChecked(); - return args.GetReturnValue().Set(categories); + auto categories = GetEnabledTracingCategories(); + Local ret = Array::New(env->isolate(), categories.size()); + size_t n = 0; + for (auto it = categories.begin(); it != categories.end(); it++) { + ret->Set(env->context(), n++, + String::NewFromUtf8(env->isolate(), (*it).c_str(), + v8::NewStringType::kNormal).ToLocalChecked()) + .FromJust(); } + args.GetReturnValue().Set(ret); #endif } @@ -176,8 +198,9 @@ void InitializeTraceEvents(Local target, env->SetMethod(target, "emit", Emit); env->SetMethod(target, "categoryGroupEnabled", CategoryGroupEnabled); - env->SetMethod(target, "startTracing", StartTracing); - env->SetMethod(target, "stopTracing", StopTracing); + + env->SetMethod(target, "enableTracingCategories", EnableTracingCategories); + env->SetMethod(target, "disableTracingCategories", DisableTracingCategories); env->SetMethod(target, "getTracingCategories", GetTracingCategories); } diff --git a/src/tracing/agent.cc b/src/tracing/agent.cc index 0d059475ce6e81..01025e1c6fab61 100644 --- a/src/tracing/agent.cc +++ b/src/tracing/agent.cc @@ -1,17 +1,16 @@ #include "tracing/agent.h" - -#include -#include #include "tracing/node_trace_buffer.h" #include "tracing/node_trace_writer.h" - #include "env-inl.h" +#include +#include +#include + namespace node { namespace tracing { using v8::platform::tracing::TraceConfig; -using std::string; Agent::Agent(const std::string& log_file_pattern) : log_file_pattern_(log_file_pattern) { @@ -32,10 +31,9 @@ void Agent::InitializeOnce() { tracing_controller_->Initialize(trace_buffer); } -void Agent::StartTracing(const string& enabled_categories) { - TraceConfig* trace_config = new TraceConfig(); +void Agent::StartTracing() { tracing_controller_->StopTracing(); - if (!enabled_categories.empty()) { + if (!categories_.empty()) { if (!started_) { InitializeOnce(); // This thread should be created *after* async handles are created @@ -45,13 +43,45 @@ void Agent::StartTracing(const string& enabled_categories) { CHECK_EQ(err, 0); started_ = true; } - std::stringstream category_list(enabled_categories); + TraceConfig* trace_config = new TraceConfig(); + for (auto it = categories_.begin(); it != categories_.end(); it++) { + trace_config->AddIncludedCategory((*it).c_str()); + } + tracing_controller_->StartTracing(trace_config); + } +} + +void Agent::EnableCategories(const std::string& categories) { + if (!categories.empty()) { + std::stringstream category_list(categories); while (category_list.good()) { std::string category; getline(category_list, category, ','); - trace_config->AddIncludedCategory(category.c_str()); + categories_.insert(category); } - tracing_controller_->StartTracing(trace_config); + StartTracing(); + } +} + +void Agent::EnableCategories(const std::vector& categories) { + if (!categories.empty()) { + for (auto category = categories.begin(); + category != categories.end(); + category++) { + categories_.insert(*category); + } + StartTracing(); + } +} + +void Agent::DisableCategories(const std::vector& categories) { + if (!categories.empty()) { + for (auto category = categories.begin(); + category != categories.end(); + category++) { + categories_.erase(*category); + } + StartTracing(); } } diff --git a/src/tracing/agent.h b/src/tracing/agent.h index 97e3171ce023cf..8595d5bcc1a279 100644 --- a/src/tracing/agent.h +++ b/src/tracing/agent.h @@ -5,6 +5,10 @@ #include "uv.h" #include "v8.h" +#include +#include +#include + namespace node { namespace tracing { @@ -20,19 +24,28 @@ class TracingController : public v8::platform::tracing::TracingController { class Agent { public: explicit Agent(const std::string& log_file_pattern); - void StartTracing(const std::string& enabled_categories); + + void EnableCategories(const std::string& categories); + void EnableCategories(const std::vector& categories); + void DisableCategories(const std::vector& categories); + const std::set& GetEnabledCategories() const { + return categories_; + } + void StopTracing(); void Stop(); TracingController* GetTracingController() { return tracing_controller_; } - uv_once_t init_once_ = UV_ONCE_INIT; - private: - void InitializeOnce(); static void ThreadCb(void* arg); + void InitializeOnce(); + void StartTracing(); + const std::string& log_file_pattern_; + std::set categories_; + uv_thread_t thread_; uv_loop_t tracing_loop_; bool initialized_ = false; diff --git a/test/parallel/test-trace-events-module.js b/test/parallel/test-trace-events-module.js index 3544466f6b237b..3accd8ec701306 100644 --- a/test/parallel/test-trace-events-module.js +++ b/test/parallel/test-trace-events-module.js @@ -16,21 +16,25 @@ if (process.argv[2] === 'child') { // to the file. That said, if necessary, this test could // be modified to use any trace event output. const { performance } = require('perf_hooks'); - trace_events.setTracingCategories('node.perf.usertiming'); + assert.deepStrictEqual(trace_events.getTracingCategories(), []); + trace_events.enableTracingCategories('node.perf.usertiming'); + assert.deepStrictEqual(trace_events.getTracingCategories(), + ['node.perf.usertiming']); performance.mark('A'); performance.mark('B'); performance.measure('A to B', 'A', 'B'); - trace_events.setTracingCategories(undefined); + trace_events.disableTracingCategories('node.perf.usertiming'); + assert.deepStrictEqual(trace_events.getTracingCategories(), []); } else { tmpdir.refresh(); process.chdir(tmpdir.path); const expectedMarks = ['A', 'B']; const expectedBegins = [ - { cat: 'node.perf,node.perf.usertiming', name: 'A to B' } + { cat: 'node,node.perf,node.perf.usertiming', name: 'A to B' } ]; const expectedEnds = [ - { cat: 'node.perf,node.perf.usertiming', name: 'A to B' } + { cat: 'node,node.perf,node.perf.usertiming', name: 'A to B' } ]; const proc = cp.fork(__filename, [ 'child' ]); @@ -50,7 +54,8 @@ if (process.argv[2] === 'child') { assert.strictEqual(trace.pid, proc.pid); switch (trace.ph) { case 'R': - assert.strictEqual(trace.cat, 'node.perf,node.perf.usertiming'); + assert.strictEqual(trace.cat, + 'node,node.perf,node.perf.usertiming'); assert.strictEqual(trace.name, expectedMarks.shift()); break; case 'b': From d366cc6b8d2ea94bfa462e89d8e1fa13087d55a6 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 12 Mar 2018 10:51:39 -0700 Subject: [PATCH 4/6] [Squash] doc nits --- doc/api/tracing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api/tracing.md b/doc/api/tracing.md index 24571489e0c426..207fb020c77e22 100644 --- a/doc/api/tracing.md +++ b/doc/api/tracing.md @@ -59,7 +59,7 @@ It is accessible using `require('trace_events')`. ### trace_events.disableTracingCategories(...categories) -* `...categories` [string] One or more category names. +* `...categories` {string} One or more category names. Disables trace event capture for the given set of category names. @@ -83,7 +83,7 @@ trace_events.disableTracingCategories( ### trace_events.enableTracingCategories(...categories) -* `...categories` [string] One or more category names. +* `...categories` {string} One or more category names. Enables trace event capture for the given set of category names. @@ -97,7 +97,7 @@ trace_events.enableTracingCategories('v8', 'node.async_hooks'); ### trace_events.getTracingCategories() -* Return: {string[]} +* Returns: {string[]} Returns an Array of the currently enabled trace event categories. From b3cf556a1ec32c2a28c2334ad1ab504b256fa16b Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 12 Mar 2018 11:55:40 -0700 Subject: [PATCH 5/6] [Squash] c++ nits --- doc/api/errors.md | 3 +++ src/node.cc | 13 +++++++------ src/node_internals.h | 12 +++++------- src/node_trace_events.cc | 6 +++--- src/tracing/agent.cc | 17 +++++------------ src/tracing/agent.h | 6 +++--- 6 files changed, 26 insertions(+), 31 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index 6377e77d1247a9..fc205a71e91ee7 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1515,6 +1515,9 @@ An attempt was made to renegotiate TLS on a socket instance with TLS disabled. The trace events mechanism is not available for use in the Node.js binary. +This is the case when Node.js was compiled with the `--without-v8-platform` +flag. + ### ERR_TRANSFORM_ALREADY_TRANSFORMING diff --git a/src/node.cc b/src/node.cc index f48fbed7b11ea4..c1a1ae25597081 100644 --- a/src/node.cc +++ b/src/node.cc @@ -82,6 +82,7 @@ #include #include +#include #if defined(NODE_HAVE_I18N_SUPPORT) #include @@ -315,15 +316,15 @@ static struct { tracing_agent_->EnableCategories(categories); } - void EnableTracingCategories(const std::vector categories) { + void EnableTracingCategories(const std::vector& categories) { tracing_agent_->EnableCategories(categories); } - void DisableTracingCategories(const std::vector categories) { + void DisableTracingCategories(const std::vector& categories) { tracing_agent_->DisableCategories(categories); } - const std::set& GetEnabledTracingCategories() { + const std::unordered_set& GetEnabledTracingCategories() { return tracing_agent_->GetEnabledCategories(); } @@ -355,7 +356,7 @@ static struct { void EnableTracingCategories(const std::string& categories) {} void EnableTracingCategories(const std::vector categories) {} void DisableTracingCategories(const std::vector categories) {} - const std::set& GetEnabledTracingCategories() { + const std::unordered_set& GetEnabledTracingCategories() { return categories_; } void StopTracing() {} @@ -365,7 +366,7 @@ static struct { return nullptr; } - std::set categories_; + std::unordered_set categories_; #endif // !NODE_USE_V8_PLATFORM #if !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR @@ -383,7 +384,7 @@ void DisableTracingCategories(const std::vector& categories) { v8_platform.DisableTracingCategories(categories); } -const std::set& GetEnabledTracingCategories() { +const std::unordered_set& GetEnabledTracingCategories() { return v8_platform.GetEnabledTracingCategories(); } diff --git a/src/node_internals.h b/src/node_internals.h index 6604abf4eb8938..4b2d1415aafe96 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -38,7 +38,7 @@ #include #include -#include +#include // Custom constants used by both node_constants.cc and node_zlib.cc #define Z_MIN_WINDOWBITS 8 @@ -786,12 +786,10 @@ static inline const char *errno_string(int errorno) { TRACING_CATEGORY_NODE "." #one "," \ TRACING_CATEGORY_NODE "." #one "." #two -extern void EnableTracingCategories( - const std::vector& categories); -extern void DisableTracingCategories( - const std::vector& categories); -extern const std::set& GetEnabledTracingCategories(); -extern void StopTracing(); +void EnableTracingCategories(const std::vector& categories); +void DisableTracingCategories(const std::vector& categories); +const std::unordered_set& GetEnabledTracingCategories(); +void StopTracing(); } // namespace node diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index 234f3274e16f50..25c821de870cd4 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -177,12 +177,12 @@ static void DisableTracingCategories(const FunctionCallbackInfo& args) { static void GetTracingCategories(const FunctionCallbackInfo& args) { #if NODE_USE_V8_PLATFORM Environment* env = Environment::GetCurrent(args); - auto categories = GetEnabledTracingCategories(); + const auto& categories = GetEnabledTracingCategories(); Local ret = Array::New(env->isolate(), categories.size()); size_t n = 0; - for (auto it = categories.begin(); it != categories.end(); it++) { + for (const std::string& category : categories) { ret->Set(env->context(), n++, - String::NewFromUtf8(env->isolate(), (*it).c_str(), + String::NewFromUtf8(env->isolate(), category.c_str(), v8::NewStringType::kNormal).ToLocalChecked()) .FromJust(); } diff --git a/src/tracing/agent.cc b/src/tracing/agent.cc index 01025e1c6fab61..5eafbfd6b1bc21 100644 --- a/src/tracing/agent.cc +++ b/src/tracing/agent.cc @@ -44,8 +44,8 @@ void Agent::StartTracing() { started_ = true; } TraceConfig* trace_config = new TraceConfig(); - for (auto it = categories_.begin(); it != categories_.end(); it++) { - trace_config->AddIncludedCategory((*it).c_str()); + for (const std::string& category : categories_) { + trace_config->AddIncludedCategory(category.c_str()); } tracing_controller_->StartTracing(trace_config); } @@ -65,22 +65,15 @@ void Agent::EnableCategories(const std::string& categories) { void Agent::EnableCategories(const std::vector& categories) { if (!categories.empty()) { - for (auto category = categories.begin(); - category != categories.end(); - category++) { - categories_.insert(*category); - } + categories_.insert(categories.begin(), categories.end()); StartTracing(); } } void Agent::DisableCategories(const std::vector& categories) { if (!categories.empty()) { - for (auto category = categories.begin(); - category != categories.end(); - category++) { - categories_.erase(*category); - } + for (const std::string& category : categories) + categories_.erase(category); StartTracing(); } } diff --git a/src/tracing/agent.h b/src/tracing/agent.h index 8595d5bcc1a279..20d57c52456221 100644 --- a/src/tracing/agent.h +++ b/src/tracing/agent.h @@ -6,7 +6,7 @@ #include "v8.h" #include -#include +#include #include namespace node { @@ -28,7 +28,7 @@ class Agent { void EnableCategories(const std::string& categories); void EnableCategories(const std::vector& categories); void DisableCategories(const std::vector& categories); - const std::set& GetEnabledCategories() const { + const std::unordered_set& GetEnabledCategories() const { return categories_; } @@ -44,7 +44,7 @@ class Agent { void StartTracing(); const std::string& log_file_pattern_; - std::set categories_; + std::unordered_set categories_; uv_thread_t thread_; uv_loop_t tracing_loop_; From 03dcd2455f3deba04eb82ca8ee350646bd6983ae Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 12 Mar 2018 12:56:22 -0700 Subject: [PATCH 6/6] [Squash] Fix nits --- src/node_trace_events.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index 25c821de870cd4..adbc39003d6cb8 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -149,7 +149,7 @@ static void EnableTracingCategories(const FunctionCallbackInfo& args) { cats.push_back(*val); } EnableTracingCategories(cats); -#elif +#else UNREACHABLE(); #endif } @@ -169,7 +169,7 @@ static void DisableTracingCategories(const FunctionCallbackInfo& args) { cats.push_back(*val); } DisableTracingCategories(cats); -#elif +#else UNREACHABLE(); #endif }