-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
src: add trace events for env.cc #23674
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
| #include "node_context_data.h" | ||
| #include "node_worker.h" | ||
| #include "tracing/agent.h" | ||
| #include "tracing/traced_value.h" | ||
|
|
||
| #include <stdio.h> | ||
| #include <algorithm> | ||
|
|
@@ -33,6 +34,25 @@ using worker::Worker; | |
|
|
||
| #define kTraceCategoryCount 1 | ||
|
|
||
| // TODO(@jasnell): Likely useful to move this to util or node_internal to | ||
| // allow reuse. But since we're not reusing it yet... | ||
| class TraceEventScope { | ||
| public: | ||
| TraceEventScope(const char* category, | ||
| const char* name, | ||
| void* id) : category_(category), name_(name), id_(id) { | ||
| TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(category_, name_, id_); | ||
| } | ||
| ~TraceEventScope() { | ||
| TRACE_EVENT_NESTABLE_ASYNC_END0(category_, name_, id_); | ||
| } | ||
|
|
||
| private: | ||
| const char* category_; | ||
| const char* name_; | ||
| void* id_; | ||
| }; | ||
|
|
||
| int const Environment::kNodeContextTag = 0x6e6f64; | ||
| void* Environment::kNodeContextTagPtr = const_cast<void*>( | ||
| static_cast<const void*>(&Environment::kNodeContextTag)); | ||
|
|
@@ -223,6 +243,9 @@ Environment::~Environment() { | |
| delete[] heap_statistics_buffer_; | ||
| delete[] heap_space_statistics_buffer_; | ||
| delete[] http_parser_buffer_; | ||
|
|
||
| TRACE_EVENT_NESTABLE_ASYNC_END0( | ||
| TRACING_CATEGORY_NODE1(environment), "Environment", this); | ||
| } | ||
|
|
||
| void Environment::Start(const std::vector<std::string>& args, | ||
|
|
@@ -231,6 +254,23 @@ void Environment::Start(const std::vector<std::string>& args, | |
| HandleScope handle_scope(isolate()); | ||
| Context::Scope context_scope(context()); | ||
|
|
||
| if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( | ||
| TRACING_CATEGORY_NODE1(environment)) != 0) { | ||
| auto traced_value = tracing::TracedValue::Create(); | ||
| traced_value->BeginArray("args"); | ||
| for (const std::string& arg : args) | ||
| traced_value->AppendString(arg); | ||
| traced_value->EndArray(); | ||
| traced_value->BeginArray("exec_args"); | ||
| for (const std::string& arg : exec_args) | ||
| traced_value->AppendString(arg); | ||
| traced_value->EndArray(); | ||
| TRACE_EVENT_NESTABLE_ASYNC_BEGIN1( | ||
| TRACING_CATEGORY_NODE1(environment), | ||
| "Environment", this, | ||
| "args", std::move(traced_value)); | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Heads up … there’s a very good chance of the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I was wondering about that. Hmm... perhaps we should make args have their own dedicated trace event category... or even make it part of the process
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jasnell I think that depends… We’ve had a similar conversation in the node-report PR at #22712 – what arguments do we actually care about here? The ones passed on the original command line, to the Node.js CLI, or the one that this Node.js instance explicitly uses? The distinction matters for embedder use cases; But maybe, as a more practical example: I’d like to add support for something similar to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm thinking that the one that this Node.js instance explicitly uses... whichever are relevant to each specific |
||
|
|
||
| CHECK_EQ(0, uv_timer_init(event_loop(), timer_handle())); | ||
| uv_unref(reinterpret_cast<uv_handle_t*>(timer_handle())); | ||
|
|
||
|
|
@@ -400,6 +440,8 @@ void Environment::PrintSyncTrace() const { | |
| } | ||
|
|
||
| void Environment::RunCleanup() { | ||
| TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), | ||
| "RunCleanup", this); | ||
| CleanupHandles(); | ||
|
|
||
| while (!cleanup_hooks_.empty()) { | ||
|
|
@@ -431,6 +473,8 @@ void Environment::RunCleanup() { | |
| } | ||
|
|
||
| void Environment::RunBeforeExitCallbacks() { | ||
| TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), | ||
| "BeforeExit", this); | ||
| for (ExitCallback before_exit : before_exit_functions_) { | ||
| before_exit.cb_(before_exit.arg_); | ||
| } | ||
|
|
@@ -442,6 +486,8 @@ void Environment::BeforeExit(void (*cb)(void* arg), void* arg) { | |
| } | ||
|
|
||
| void Environment::RunAtExitCallbacks() { | ||
| TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), | ||
| "AtExit", this); | ||
| for (ExitCallback at_exit : at_exit_functions_) { | ||
| at_exit.cb_(at_exit.arg_); | ||
| } | ||
|
|
@@ -495,13 +541,16 @@ void Environment::EnvPromiseHook(v8::PromiseHookType type, | |
|
|
||
| Environment* env = Environment::GetCurrent(context); | ||
| if (env == nullptr) return; | ||
|
|
||
| TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), | ||
| "EnvPromiseHook", env); | ||
| for (const PromiseHookCallback& hook : env->promise_hooks_) { | ||
| hook.cb_(type, promise, parent, hook.arg_); | ||
| } | ||
| } | ||
|
|
||
| void Environment::RunAndClearNativeImmediates() { | ||
| TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), | ||
| "RunAndClearNativeImmediates", this); | ||
| size_t count = native_immediate_callbacks_.size(); | ||
| if (count > 0) { | ||
| size_t ref_count = 0; | ||
|
|
@@ -554,6 +603,8 @@ void Environment::ToggleTimerRef(bool ref) { | |
|
|
||
| void Environment::RunTimers(uv_timer_t* handle) { | ||
| Environment* env = Environment::from_timer_handle(handle); | ||
| TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), | ||
| "RunTimers", env); | ||
|
|
||
| if (!env->can_call_into_js()) | ||
| return; | ||
|
|
@@ -614,6 +665,8 @@ void Environment::RunTimers(uv_timer_t* handle) { | |
|
|
||
| void Environment::CheckImmediate(uv_check_t* handle) { | ||
| Environment* env = Environment::from_immediate_check_handle(handle); | ||
| TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), | ||
| "CheckImmediate", env); | ||
|
|
||
| if (env->immediate_info()->count() == 0) | ||
| return; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| // Flags: --no-warnings | ||
|
|
||
| 'use strict'; | ||
| const common = require('../common'); | ||
| const assert = require('assert'); | ||
jasnell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const cp = require('child_process'); | ||
| const path = require('path'); | ||
| const fs = require('fs'); | ||
| const tmpdir = require('../common/tmpdir'); | ||
|
|
||
| // This tests the emission of node.environment trace events | ||
|
|
||
| if (!common.isMainThread) | ||
| common.skip('process.chdir is not available in Workers'); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does that also apply to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It shouldn't, but that's a question for @addaleax and is a separate concern from this PR.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When using
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The chdir is there because of the generated trace event file. I'm inclined to leave the test as it is and refactor all of the trace event tests as a whole if this is the direction we want to go (they all follow this same pattern) |
||
|
|
||
| const names = new Set([ | ||
| 'Environment', | ||
| 'RunAndClearNativeImmediates', | ||
| 'CheckImmediate', | ||
| 'RunTimers', | ||
| 'BeforeExit', | ||
| 'RunCleanup', | ||
| 'AtExit' | ||
| ]); | ||
|
|
||
| if (process.argv[2] === 'child') { | ||
| // This is just so that the child has something to do. | ||
| 1 + 1; | ||
jasnell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // These ensure that the RunTimers, CheckImmediate, and | ||
| // RunAndClearNativeImmediates appear in the list. | ||
| setImmediate(() => { 1 + 1; }); | ||
| setTimeout(() => { 1 + 1; }, 1); | ||
| } else { | ||
| tmpdir.refresh(); | ||
| process.chdir(tmpdir.path); | ||
|
|
||
| const proc = cp.fork(__filename, | ||
| [ 'child' ], { | ||
| execArgv: [ | ||
| '--trace-event-categories', | ||
| 'node.environment' | ||
| ] | ||
| }); | ||
|
|
||
| proc.once('exit', common.mustCall(async () => { | ||
| const file = path.join(tmpdir.path, 'node_trace.1.log'); | ||
| const checkSet = new Set(); | ||
|
|
||
| assert(fs.existsSync(file)); | ||
| const data = await fs.promises.readFile(file); | ||
| JSON.parse(data.toString()).traceEvents | ||
| .filter((trace) => trace.cat !== '__metadata') | ||
| .forEach((trace) => { | ||
| assert.strictEqual(trace.pid, proc.pid); | ||
| assert(names.has(trace.name)); | ||
| checkSet.add(trace.name); | ||
| }); | ||
|
|
||
| assert.deepStrictEqual(names, checkSet); | ||
| })); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.