src: add trace events for env.cc
PR-URL: https://github.com/nodejs/node/pull/23674 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com> Reviewed-By: Matheus Marchini <mat@mmarchini.me>
This commit is contained in:
parent
92d67fefe2
commit
72a48a2a0a
@ -18,6 +18,7 @@ The available categories are:
|
|||||||
The [`async_hooks`] events have a unique `asyncId` and a special `triggerId`
|
The [`async_hooks`] events have a unique `asyncId` and a special `triggerId`
|
||||||
`triggerAsyncId` property.
|
`triggerAsyncId` property.
|
||||||
* `node.bootstrap` - Enables capture of Node.js bootstrap milestones.
|
* `node.bootstrap` - Enables capture of Node.js bootstrap milestones.
|
||||||
|
* `node.environment` - Enables capture of Node.js Environment milestones.
|
||||||
* `node.fs.sync` - Enables capture of trace data for file system sync methods.
|
* `node.fs.sync` - Enables capture of trace data for file system sync methods.
|
||||||
* `node.perf` - Enables capture of [Performance API] measurements.
|
* `node.perf` - Enables capture of [Performance API] measurements.
|
||||||
* `node.perf.usertiming` - Enables capture of only Performance API User Timing
|
* `node.perf.usertiming` - Enables capture of only Performance API User Timing
|
||||||
|
55
src/env.cc
55
src/env.cc
@ -7,6 +7,7 @@
|
|||||||
#include "node_context_data.h"
|
#include "node_context_data.h"
|
||||||
#include "node_worker.h"
|
#include "node_worker.h"
|
||||||
#include "tracing/agent.h"
|
#include "tracing/agent.h"
|
||||||
|
#include "tracing/traced_value.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -33,6 +34,25 @@ using worker::Worker;
|
|||||||
|
|
||||||
#define kTraceCategoryCount 1
|
#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;
|
int const Environment::kNodeContextTag = 0x6e6f64;
|
||||||
void* Environment::kNodeContextTagPtr = const_cast<void*>(
|
void* Environment::kNodeContextTagPtr = const_cast<void*>(
|
||||||
static_cast<const void*>(&Environment::kNodeContextTag));
|
static_cast<const void*>(&Environment::kNodeContextTag));
|
||||||
@ -224,6 +244,9 @@ Environment::~Environment() {
|
|||||||
delete[] heap_statistics_buffer_;
|
delete[] heap_statistics_buffer_;
|
||||||
delete[] heap_space_statistics_buffer_;
|
delete[] heap_space_statistics_buffer_;
|
||||||
delete[] http_parser_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,
|
void Environment::Start(const std::vector<std::string>& args,
|
||||||
@ -232,6 +255,23 @@ void Environment::Start(const std::vector<std::string>& args,
|
|||||||
HandleScope handle_scope(isolate());
|
HandleScope handle_scope(isolate());
|
||||||
Context::Scope context_scope(context());
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
CHECK_EQ(0, uv_timer_init(event_loop(), timer_handle()));
|
CHECK_EQ(0, uv_timer_init(event_loop(), timer_handle()));
|
||||||
uv_unref(reinterpret_cast<uv_handle_t*>(timer_handle()));
|
uv_unref(reinterpret_cast<uv_handle_t*>(timer_handle()));
|
||||||
|
|
||||||
@ -401,6 +441,8 @@ void Environment::PrintSyncTrace() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Environment::RunCleanup() {
|
void Environment::RunCleanup() {
|
||||||
|
TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
|
||||||
|
"RunCleanup", this);
|
||||||
CleanupHandles();
|
CleanupHandles();
|
||||||
|
|
||||||
while (!cleanup_hooks_.empty()) {
|
while (!cleanup_hooks_.empty()) {
|
||||||
@ -432,6 +474,8 @@ void Environment::RunCleanup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Environment::RunBeforeExitCallbacks() {
|
void Environment::RunBeforeExitCallbacks() {
|
||||||
|
TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
|
||||||
|
"BeforeExit", this);
|
||||||
for (ExitCallback before_exit : before_exit_functions_) {
|
for (ExitCallback before_exit : before_exit_functions_) {
|
||||||
before_exit.cb_(before_exit.arg_);
|
before_exit.cb_(before_exit.arg_);
|
||||||
}
|
}
|
||||||
@ -443,6 +487,8 @@ void Environment::BeforeExit(void (*cb)(void* arg), void* arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Environment::RunAtExitCallbacks() {
|
void Environment::RunAtExitCallbacks() {
|
||||||
|
TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
|
||||||
|
"AtExit", this);
|
||||||
for (ExitCallback at_exit : at_exit_functions_) {
|
for (ExitCallback at_exit : at_exit_functions_) {
|
||||||
at_exit.cb_(at_exit.arg_);
|
at_exit.cb_(at_exit.arg_);
|
||||||
}
|
}
|
||||||
@ -496,13 +542,16 @@ void Environment::EnvPromiseHook(v8::PromiseHookType type,
|
|||||||
|
|
||||||
Environment* env = Environment::GetCurrent(context);
|
Environment* env = Environment::GetCurrent(context);
|
||||||
if (env == nullptr) return;
|
if (env == nullptr) return;
|
||||||
|
TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
|
||||||
|
"EnvPromiseHook", env);
|
||||||
for (const PromiseHookCallback& hook : env->promise_hooks_) {
|
for (const PromiseHookCallback& hook : env->promise_hooks_) {
|
||||||
hook.cb_(type, promise, parent, hook.arg_);
|
hook.cb_(type, promise, parent, hook.arg_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::RunAndClearNativeImmediates() {
|
void Environment::RunAndClearNativeImmediates() {
|
||||||
|
TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
|
||||||
|
"RunAndClearNativeImmediates", this);
|
||||||
size_t count = native_immediate_callbacks_.size();
|
size_t count = native_immediate_callbacks_.size();
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
size_t ref_count = 0;
|
size_t ref_count = 0;
|
||||||
@ -555,6 +604,8 @@ void Environment::ToggleTimerRef(bool ref) {
|
|||||||
|
|
||||||
void Environment::RunTimers(uv_timer_t* handle) {
|
void Environment::RunTimers(uv_timer_t* handle) {
|
||||||
Environment* env = Environment::from_timer_handle(handle);
|
Environment* env = Environment::from_timer_handle(handle);
|
||||||
|
TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
|
||||||
|
"RunTimers", env);
|
||||||
|
|
||||||
if (!env->can_call_into_js())
|
if (!env->can_call_into_js())
|
||||||
return;
|
return;
|
||||||
@ -615,6 +666,8 @@ void Environment::RunTimers(uv_timer_t* handle) {
|
|||||||
|
|
||||||
void Environment::CheckImmediate(uv_check_t* handle) {
|
void Environment::CheckImmediate(uv_check_t* handle) {
|
||||||
Environment* env = Environment::from_immediate_check_handle(handle);
|
Environment* env = Environment::from_immediate_check_handle(handle);
|
||||||
|
TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
|
||||||
|
"CheckImmediate", env);
|
||||||
|
|
||||||
if (env->immediate_info()->count() == 0)
|
if (env->immediate_info()->count() == 0)
|
||||||
return;
|
return;
|
||||||
|
61
test/parallel/test-trace-events-environment.js
Normal file
61
test/parallel/test-trace-events-environment.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Flags: --no-warnings
|
||||||
|
|
||||||
|
'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');
|
||||||
|
|
||||||
|
// This tests the emission of node.environment trace events
|
||||||
|
|
||||||
|
if (!common.isMainThread)
|
||||||
|
common.skip('process.chdir is not available in Workers');
|
||||||
|
|
||||||
|
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;
|
||||||
|
// 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);
|
||||||
|
}));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user