Skip to content

Commit 0a842ea

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 0a842ea

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-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: 33 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,31 @@ 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+
uint8_t* enabled_pointer_cast = const_cast<uint8_t*>(
138+
enabled_pointer);
139+
140+
std::unique_ptr<BackingStore> bs = ArrayBuffer::NewBackingStore(
141+
enabled_pointer_cast,
142+
sizeof(*enabled_pointer_cast),
143+
[](void*, size_t, void*) {},
144+
nullptr);
145+
auto ab = ArrayBuffer::New(isolate, std::move(bs));
146+
v8::Local<Uint8Array> u8 = v8::Uint8Array::New(ab, 0, 1);
147+
148+
args.GetReturnValue().Set(u8);
149+
}
150+
123151
void NodeCategorySet::Initialize(Local<Object> target,
124152
Local<Value> unused,
125153
Local<Context> context,
@@ -132,6 +160,10 @@ void NodeCategorySet::Initialize(Local<Object> target,
132160
target,
133161
"setTraceCategoryStateUpdateHandler",
134162
SetTraceCategoryStateUpdateHandler);
163+
SetMethod(context,
164+
target,
165+
"getCategoryEnabledBuffer",
166+
GetCategoryEnabledBuffer);
135167

136168
Local<FunctionTemplate> category_set =
137169
NewFunctionTemplate(isolate, NodeCategorySet::New);
@@ -160,6 +192,7 @@ void NodeCategorySet::RegisterExternalReferences(
160192
ExternalReferenceRegistry* registry) {
161193
registry->Register(GetEnabledCategories);
162194
registry->Register(SetTraceCategoryStateUpdateHandler);
195+
registry->Register(GetCategoryEnabledBuffer);
163196
registry->Register(NodeCategorySet::New);
164197
registry->Register(NodeCategorySet::Enable);
165198
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)