Skip to content

Commit

Permalink
trace_events: add more process metadata
Browse files Browse the repository at this point in the history
Now that TracedValue has landed, add more detailed
process `__metadata` including versions, arch, platform,
release detail, and argv/execArgv to the trace event
log.

PR-URL: #21785
Reviewed-By: Anna Henningsen <anna@addaleax.net>
  • Loading branch information
jasnell authored and targos committed Jul 19, 2018
1 parent 6af4f1f commit d7edee4
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 22 deletions.
110 changes: 96 additions & 14 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "node_debug_options.h"
#include "node_perf.h"
#include "node_context_data.h"
#include "tracing/traced_value.h"

#if defined HAVE_PERFCTR
#include "node_counters.h"
Expand Down Expand Up @@ -289,11 +290,106 @@ static v8::Isolate* node_isolate;

DebugOptions debug_options;

// Ensures that __metadata trace events are only emitted
// when tracing is enabled.
class NodeTraceStateObserver :
public v8::TracingController::TraceStateObserver {
public:
void OnTraceEnabled() override {
char name_buffer[512];
if (uv_get_process_title(name_buffer, sizeof(name_buffer)) == 0) {
// Only emit the metadata event if the title can be retrieved
// successfully. Ignore it otherwise.
TRACE_EVENT_METADATA1("__metadata", "process_name",
"name", TRACE_STR_COPY(name_buffer));
}
TRACE_EVENT_METADATA1("__metadata", "version",
"node", NODE_VERSION_STRING);
TRACE_EVENT_METADATA1("__metadata", "thread_name",
"name", "JavaScriptMainThread");

auto trace_process = tracing::TracedValue::Create();
trace_process->BeginDictionary("versions");

const char http_parser_version[] =
NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
"."
NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)
"."
NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH);

const char node_napi_version[] = NODE_STRINGIFY(NAPI_VERSION);
const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);

trace_process->SetString("http_parser", http_parser_version);
trace_process->SetString("node", NODE_VERSION_STRING);
trace_process->SetString("v8", V8::GetVersion());
trace_process->SetString("uv", uv_version_string());
trace_process->SetString("zlib", ZLIB_VERSION);
trace_process->SetString("ares", ARES_VERSION_STR);
trace_process->SetString("modules", node_modules_version);
trace_process->SetString("nghttp2", NGHTTP2_VERSION);
trace_process->SetString("napi", node_napi_version);

#if HAVE_OPENSSL
// Stupid code to slice out the version string.
{ // NOLINT(whitespace/braces)
size_t i, j, k;
int c;
for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
c = OPENSSL_VERSION_TEXT[i];
if ('0' <= c && c <= '9') {
for (j = i + 1; j < k; ++j) {
c = OPENSSL_VERSION_TEXT[j];
if (c == ' ')
break;
}
break;
}
}
trace_process->SetString("openssl",
std::string(&OPENSSL_VERSION_TEXT[i], j - i));
}
#endif
trace_process->EndDictionary();

trace_process->SetString("arch", NODE_ARCH);
trace_process->SetString("platform", NODE_PLATFORM);

trace_process->BeginDictionary("release");
trace_process->SetString("name", NODE_RELEASE);
#if NODE_VERSION_IS_LTS
trace_process->SetString("lts", NODE_VERSION_LTS_CODENAME);
#endif
trace_process->EndDictionary();
TRACE_EVENT_METADATA1("__metadata", "node",
"process", std::move(trace_process));

// This only runs the first time tracing is enabled
controller_->RemoveTraceStateObserver(this);
delete this;
}

void OnTraceDisabled() override {
// Do nothing here. This should never be called because the
// observer removes itself when OnTraceEnabled() is called.
UNREACHABLE();
}

explicit NodeTraceStateObserver(v8::TracingController* controller) :
controller_(controller) {}
~NodeTraceStateObserver() override {}

private:
v8::TracingController* controller_;
};

static struct {
#if NODE_USE_V8_PLATFORM
void Initialize(int thread_pool_size) {
tracing_agent_.reset(new tracing::Agent(trace_file_pattern));
auto controller = tracing_agent_->GetTracingController();
controller->AddTraceStateObserver(new NodeTraceStateObserver(controller));
tracing::TraceEventHelper::SetTracingController(controller);
StartTracingAgent();
platform_ = new NodePlatform(thread_pool_size, controller);
Expand Down Expand Up @@ -1992,7 +2088,6 @@ void SetupProcessObject(Environment* env,
READONLY_PROPERTY(versions,
"http_parser",
FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));

// +1 to get rid of the leading 'v'
READONLY_PROPERTY(versions,
"node",
Expand All @@ -2015,11 +2110,9 @@ void SetupProcessObject(Environment* env,
versions,
"modules",
FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));

READONLY_PROPERTY(versions,
"nghttp2",
FIXED_ONE_BYTE_STRING(env->isolate(), NGHTTP2_VERSION));

const char node_napi_version[] = NODE_STRINGIFY(NAPI_VERSION);
READONLY_PROPERTY(
versions,
Expand Down Expand Up @@ -3550,17 +3643,6 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
Environment env(isolate_data, context, v8_platform.GetTracingAgent());
env.Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);

char name_buffer[512];
if (uv_get_process_title(name_buffer, sizeof(name_buffer)) == 0) {
// Only emit the metadata event if the title can be retrieved successfully.
// Ignore it otherwise.
TRACE_EVENT_METADATA1("__metadata", "process_name", "name",
TRACE_STR_COPY(name_buffer));
}
TRACE_EVENT_METADATA1("__metadata", "version", "node", NODE_VERSION_STRING);
TRACE_EVENT_METADATA1("__metadata", "thread_name", "name",
"JavaScriptMainThread");

const char* path = argc > 1 ? argv[1] : nullptr;
StartInspector(&env, path, debug_options);

Expand Down
44 changes: 36 additions & 8 deletions test/parallel/test-trace-events-metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,53 @@ const proc = cp.spawn(process.execPath,
proc.once('exit', common.mustCall(() => {
assert(common.fileExists(FILE_NAME));
fs.readFile(FILE_NAME, common.mustCall((err, data) => {
const traces = JSON.parse(data.toString()).traceEvents;
const traces = JSON.parse(data.toString()).traceEvents
.filter((trace) => trace.cat === '__metadata');
assert(traces.length > 0);
assert(traces.some((trace) =>
trace.cat === '__metadata' && trace.name === 'thread_name' &&
trace.name === 'thread_name' &&
trace.args.name === 'JavaScriptMainThread'));
assert(traces.some((trace) =>
trace.cat === '__metadata' && trace.name === 'thread_name' &&
trace.name === 'thread_name' &&
trace.args.name === 'BackgroundTaskRunner'));
assert(traces.some((trace) =>
trace.cat === '__metadata' && trace.name === 'version' &&
trace.name === 'version' &&
trace.args.node === process.versions.node));

assert(traces.some((trace) =>
trace.name === 'node' &&
trace.args.process.versions.http_parser ===
process.versions.http_parser &&
trace.args.process.versions.node ===
process.versions.node &&
trace.args.process.versions.v8 ===
process.versions.v8 &&
trace.args.process.versions.uv ===
process.versions.uv &&
trace.args.process.versions.zlib ===
process.versions.zlib &&
trace.args.process.versions.ares ===
process.versions.ares &&
trace.args.process.versions.modules ===
process.versions.modules &&
trace.args.process.versions.nghttp2 ===
process.versions.nghttp2 &&
trace.args.process.versions.napi ===
process.versions.napi &&
trace.args.process.versions.openssl ===
process.versions.openssl &&
trace.args.process.arch === process.arch &&
trace.args.process.platform === process.platform &&
trace.args.process.release.name === process.release.name &&
(!process.release.lts ||
trace.args.process.release.lts === process.release.lts)));

if (!common.isSunOS) {
// Changing process.title is currently unsupported on SunOS/SmartOS
assert(traces.some((trace) =>
trace.cat === '__metadata' && trace.name === 'process_name' &&
trace.args.name === 'foo'));
trace.name === 'process_name' && trace.args.name === 'foo'));
assert(traces.some((trace) =>
trace.cat === '__metadata' && trace.name === 'process_name' &&
trace.args.name === 'bar'));
trace.name === 'process_name' && trace.args.name === 'bar'));
}
}));
}));

0 comments on commit d7edee4

Please sign in to comment.