Skip to content

Commit 0129dc3

Browse files
committed
src,lib: expose getCategoryEnabledBuffer to use on node.http
Instead call the C++ code every time we need to check for a trace category, now we get the C++ pointer to the flag that holds the info if the trace is enabled and return this pointer inside a buffer that we can use to call/check if the value is enabled. With this change, no C++ call is made and the access to the info happens in JS side, which has no perf penalty.
1 parent 53ac448 commit 0129dc3

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

lib/internal/http.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const {
88
} = primordials;
99

1010
const { setUnrefTimeout } = require('internal/timers');
11-
const { trace, isTraceCategoryEnabled } = internalBinding('trace_events');
11+
const { getCategoryEnabledBuffer, trace } = internalBinding('trace_events');
1212
const {
1313
CHAR_LOWERCASE_B,
1414
CHAR_LOWERCASE_E,
@@ -37,8 +37,10 @@ function getNextTraceEventId() {
3737
return ++traceEventId;
3838
}
3939

40+
const httpEnabled = getCategoryEnabledBuffer('node.http');
41+
4042
function isTraceHTTPEnabled() {
41-
return isTraceCategoryEnabled('node.http');
43+
return httpEnabled[0] > 0;
4244
}
4345

4446
const traceEventCategory = 'node,node.http';

src/node_trace_events.cc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ namespace node {
1616
class ExternalReferenceRegistry;
1717

1818
using v8::Array;
19+
using v8::ArrayBuffer;
20+
using v8::BackingStore;
1921
using v8::Context;
2022
using v8::Function;
2123
using v8::FunctionCallbackInfo;
@@ -25,6 +27,7 @@ using v8::Local;
2527
using v8::NewStringType;
2628
using v8::Object;
2729
using v8::String;
30+
using v8::Uint8Array;
2831
using v8::Value;
2932

3033
class NodeCategorySet : public BaseObject {
@@ -120,6 +123,34 @@ static void SetTraceCategoryStateUpdateHandler(
120123
env->set_trace_category_state_function(args[0].As<Function>());
121124
}
122125

126+
static void GetCategoryEnabledBuffer(
127+
const FunctionCallbackInfo<Value>& args) {
128+
Isolate* isolate = args.GetIsolate();
129+
Environment* env = Environment::GetCurrent(args);
130+
131+
CHECK(args[0]->IsString());
132+
133+
node::Utf8Value category_name(isolate, args[0]);
134+
135+
const uint8_t* enabled_pointer = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
136+
category_name.out()
137+
);
138+
uint8_t* enabled_pointer_cast = const_cast<uint8_t*>(
139+
enabled_pointer
140+
);
141+
142+
std::unique_ptr<BackingStore> bs = ArrayBuffer::NewBackingStore(
143+
enabled_pointer_cast,
144+
sizeof(*enabled_pointer_cast),
145+
[](void*, size_t, void*) {},
146+
nullptr
147+
);
148+
auto ab = ArrayBuffer::New(isolate, std::move(bs));
149+
v8::Local<Uint8Array> u8 = v8::Uint8Array::New(ab, 0, 1);
150+
151+
args.GetReturnValue().Set(u8);
152+
}
153+
123154
void NodeCategorySet::Initialize(Local<Object> target,
124155
Local<Value> unused,
125156
Local<Context> context,
@@ -132,6 +163,10 @@ void NodeCategorySet::Initialize(Local<Object> target,
132163
target,
133164
"setTraceCategoryStateUpdateHandler",
134165
SetTraceCategoryStateUpdateHandler);
166+
SetMethod(context,
167+
target,
168+
"getCategoryEnabledBuffer",
169+
GetCategoryEnabledBuffer);
135170

136171
Local<FunctionTemplate> category_set =
137172
NewFunctionTemplate(isolate, NodeCategorySet::New);
@@ -160,6 +195,7 @@ void NodeCategorySet::RegisterExternalReferences(
160195
ExternalReferenceRegistry* registry) {
161196
registry->Register(GetEnabledCategories);
162197
registry->Register(SetTraceCategoryStateUpdateHandler);
198+
registry->Register(GetCategoryEnabledBuffer);
163199
registry->Register(NodeCategorySet::New);
164200
registry->Register(NodeCategorySet::Enable);
165201
registry->Register(NodeCategorySet::Disable);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Flags: --expose-internals
2+
3+
import '../common/index.mjs';
4+
import { it } from 'node:test';
5+
import { createTracing, getEnabledCategories } from 'node:trace_events';
6+
import assert from 'node:assert';
7+
8+
import binding from 'internal/test/binding';
9+
const getCategoryEnabledBuffer = binding.internalBinding('trace_events').getCategoryEnabledBuffer;
10+
11+
it('should track enabled/disabled categories', () => {
12+
const random = Math.random().toString().slice(2);
13+
const category = `node.${random}`;
14+
15+
const buffer = getCategoryEnabledBuffer(category);
16+
17+
const tracing = createTracing({
18+
categories: [category],
19+
});
20+
21+
assert.ok(buffer[0] === 0, `the buffer[0] should start with value 0, got: ${buffer[0]}`);
22+
23+
tracing.enable();
24+
25+
let currentCategories = getEnabledCategories();
26+
27+
assert.ok(currentCategories.includes(category), `the getEnabledCategories should include ${category}, got: ${currentCategories}`);
28+
assert.ok(buffer[0] > 0, `the buffer[0] should be greater than 0, got: ${buffer[0]}`);
29+
30+
tracing.disable();
31+
32+
currentCategories = getEnabledCategories();
33+
assert.ok(currentCategories === undefined, `the getEnabledCategories should return undefined, got: ${currentCategories}`);
34+
assert.ok(buffer[0] === 0, `the buffer[0] should be 0, got: ${buffer[0]}`);
35+
});

0 commit comments

Comments
 (0)