3030#include "node_debug_options.h"
3131#include "node_perf.h"
3232#include "node_context_data.h"
33+ #include "tracing/traced_value.h"
3334
3435#if defined HAVE_PERFCTR
3536#include "node_counters.h"
@@ -289,11 +290,106 @@ static v8::Isolate* node_isolate;
289290
290291DebugOptions debug_options;
291292
293+ // Ensures that __metadata trace events are only emitted
294+ // when tracing is enabled.
295+ class NodeTraceStateObserver :
296+ public v8::TracingController::TraceStateObserver {
297+ public:
298+ void OnTraceEnabled() override {
299+ char name_buffer[512];
300+ if (uv_get_process_title(name_buffer, sizeof(name_buffer)) == 0) {
301+ // Only emit the metadata event if the title can be retrieved
302+ // successfully. Ignore it otherwise.
303+ TRACE_EVENT_METADATA1("__metadata", "process_name",
304+ "name", TRACE_STR_COPY(name_buffer));
305+ }
306+ TRACE_EVENT_METADATA1("__metadata", "version",
307+ "node", NODE_VERSION_STRING);
308+ TRACE_EVENT_METADATA1("__metadata", "thread_name",
309+ "name", "JavaScriptMainThread");
310+
311+ auto trace_process = tracing::TracedValue::Create();
312+ trace_process->BeginDictionary("versions");
313+
314+ const char http_parser_version[] =
315+ NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
316+ "."
317+ NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)
318+ "."
319+ NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH);
320+
321+ const char node_napi_version[] = NODE_STRINGIFY(NAPI_VERSION);
322+ const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
323+
324+ trace_process->SetString("http_parser", http_parser_version);
325+ trace_process->SetString("node", NODE_VERSION_STRING);
326+ trace_process->SetString("v8", V8::GetVersion());
327+ trace_process->SetString("uv", uv_version_string());
328+ trace_process->SetString("zlib", ZLIB_VERSION);
329+ trace_process->SetString("ares", ARES_VERSION_STR);
330+ trace_process->SetString("modules", node_modules_version);
331+ trace_process->SetString("nghttp2", NGHTTP2_VERSION);
332+ trace_process->SetString("napi", node_napi_version);
333+
334+ #if HAVE_OPENSSL
335+ // Stupid code to slice out the version string.
336+ { // NOLINT(whitespace/braces)
337+ size_t i, j, k;
338+ int c;
339+ for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
340+ c = OPENSSL_VERSION_TEXT[i];
341+ if ('0' <= c && c <= '9') {
342+ for (j = i + 1; j < k; ++j) {
343+ c = OPENSSL_VERSION_TEXT[j];
344+ if (c == ' ')
345+ break;
346+ }
347+ break;
348+ }
349+ }
350+ trace_process->SetString("openssl",
351+ std::string(&OPENSSL_VERSION_TEXT[i], j - i));
352+ }
353+ #endif
354+ trace_process->EndDictionary();
355+
356+ trace_process->SetString("arch", NODE_ARCH);
357+ trace_process->SetString("platform", NODE_PLATFORM);
358+
359+ trace_process->BeginDictionary("release");
360+ trace_process->SetString("name", NODE_RELEASE);
361+ #if NODE_VERSION_IS_LTS
362+ trace_process->SetString("lts", NODE_VERSION_LTS_CODENAME);
363+ #endif
364+ trace_process->EndDictionary();
365+ TRACE_EVENT_METADATA1("__metadata", "node",
366+ "process", std::move(trace_process));
367+
368+ // This only runs the first time tracing is enabled
369+ controller_->RemoveTraceStateObserver(this);
370+ delete this;
371+ }
372+
373+ void OnTraceDisabled() override {
374+ // Do nothing here. This should never be called because the
375+ // observer removes itself when OnTraceEnabled() is called.
376+ UNREACHABLE();
377+ }
378+
379+ explicit NodeTraceStateObserver(v8::TracingController* controller) :
380+ controller_(controller) {}
381+ ~NodeTraceStateObserver() override {}
382+
383+ private:
384+ v8::TracingController* controller_;
385+ };
386+
292387static struct {
293388#if NODE_USE_V8_PLATFORM
294389 void Initialize(int thread_pool_size) {
295390 tracing_agent_.reset(new tracing::Agent(trace_file_pattern));
296391 auto controller = tracing_agent_->GetTracingController();
392+ controller->AddTraceStateObserver(new NodeTraceStateObserver(controller));
297393 tracing::TraceEventHelper::SetTracingController(controller);
298394 StartTracingAgent();
299395 platform_ = new NodePlatform(thread_pool_size, controller);
@@ -1992,7 +2088,6 @@ void SetupProcessObject(Environment* env,
19922088 READONLY_PROPERTY(versions,
19932089 "http_parser",
19942090 FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
1995-
19962091 // +1 to get rid of the leading 'v'
19972092 READONLY_PROPERTY(versions,
19982093 "node",
@@ -2015,11 +2110,9 @@ void SetupProcessObject(Environment* env,
20152110 versions,
20162111 "modules",
20172112 FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
2018-
20192113 READONLY_PROPERTY(versions,
20202114 "nghttp2",
20212115 FIXED_ONE_BYTE_STRING(env->isolate(), NGHTTP2_VERSION));
2022-
20232116 const char node_napi_version[] = NODE_STRINGIFY(NAPI_VERSION);
20242117 READONLY_PROPERTY(
20252118 versions,
@@ -3550,17 +3643,6 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
35503643 Environment env(isolate_data, context, v8_platform.GetTracingAgent());
35513644 env.Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
35523645
3553- char name_buffer[512];
3554- if (uv_get_process_title(name_buffer, sizeof(name_buffer)) == 0) {
3555- // Only emit the metadata event if the title can be retrieved successfully.
3556- // Ignore it otherwise.
3557- TRACE_EVENT_METADATA1("__metadata", "process_name", "name",
3558- TRACE_STR_COPY(name_buffer));
3559- }
3560- TRACE_EVENT_METADATA1("__metadata", "version", "node", NODE_VERSION_STRING);
3561- TRACE_EVENT_METADATA1("__metadata", "thread_name", "name",
3562- "JavaScriptMainThread");
3563-
35643646 const char* path = argc > 1 ? argv[1] : nullptr;
35653647 StartInspector(&env, path, debug_options);
35663648
0 commit comments