From 0129dc3d228a218637eaa3b984b42002e4a30256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Louren=C3=A7o?= Date: Wed, 26 Jun 2024 18:42:06 -0300 Subject: [PATCH] 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. --- lib/internal/http.js | 6 ++-- src/node_trace_events.cc | 36 +++++++++++++++++++ ...ace-events-get-category-enabled-buffer.mjs | 35 ++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-trace-events-get-category-enabled-buffer.mjs diff --git a/lib/internal/http.js b/lib/internal/http.js index da1e8d3332de0e..1eaf0e70f4f8ac 100644 --- a/lib/internal/http.js +++ b/lib/internal/http.js @@ -8,7 +8,7 @@ const { } = primordials; const { setUnrefTimeout } = require('internal/timers'); -const { trace, isTraceCategoryEnabled } = internalBinding('trace_events'); +const { getCategoryEnabledBuffer, trace } = internalBinding('trace_events'); const { CHAR_LOWERCASE_B, CHAR_LOWERCASE_E, @@ -37,8 +37,10 @@ function getNextTraceEventId() { return ++traceEventId; } +const httpEnabled = getCategoryEnabledBuffer('node.http'); + function isTraceHTTPEnabled() { - return isTraceCategoryEnabled('node.http'); + return httpEnabled[0] > 0; } const traceEventCategory = 'node,node.http'; diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index a0f8f4de67dabb..7123a5681dae4c 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -16,6 +16,8 @@ namespace node { class ExternalReferenceRegistry; using v8::Array; +using v8::ArrayBuffer; +using v8::BackingStore; using v8::Context; using v8::Function; using v8::FunctionCallbackInfo; @@ -25,6 +27,7 @@ using v8::Local; using v8::NewStringType; using v8::Object; using v8::String; +using v8::Uint8Array; using v8::Value; class NodeCategorySet : public BaseObject { @@ -120,6 +123,34 @@ static void SetTraceCategoryStateUpdateHandler( env->set_trace_category_state_function(args[0].As()); } +static void GetCategoryEnabledBuffer( + const FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); + Environment* env = Environment::GetCurrent(args); + + CHECK(args[0]->IsString()); + + node::Utf8Value category_name(isolate, args[0]); + + const uint8_t* enabled_pointer = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( + category_name.out() + ); + uint8_t* enabled_pointer_cast = const_cast( + enabled_pointer + ); + + std::unique_ptr bs = ArrayBuffer::NewBackingStore( + enabled_pointer_cast, + sizeof(*enabled_pointer_cast), + [](void*, size_t, void*) {}, + nullptr + ); + auto ab = ArrayBuffer::New(isolate, std::move(bs)); + v8::Local u8 = v8::Uint8Array::New(ab, 0, 1); + + args.GetReturnValue().Set(u8); +} + void NodeCategorySet::Initialize(Local target, Local unused, Local context, @@ -132,6 +163,10 @@ void NodeCategorySet::Initialize(Local target, target, "setTraceCategoryStateUpdateHandler", SetTraceCategoryStateUpdateHandler); + SetMethod(context, + target, + "getCategoryEnabledBuffer", + GetCategoryEnabledBuffer); Local category_set = NewFunctionTemplate(isolate, NodeCategorySet::New); @@ -160,6 +195,7 @@ void NodeCategorySet::RegisterExternalReferences( ExternalReferenceRegistry* registry) { registry->Register(GetEnabledCategories); registry->Register(SetTraceCategoryStateUpdateHandler); + registry->Register(GetCategoryEnabledBuffer); registry->Register(NodeCategorySet::New); registry->Register(NodeCategorySet::Enable); registry->Register(NodeCategorySet::Disable); diff --git a/test/parallel/test-trace-events-get-category-enabled-buffer.mjs b/test/parallel/test-trace-events-get-category-enabled-buffer.mjs new file mode 100644 index 00000000000000..d44dd8f7d64aa9 --- /dev/null +++ b/test/parallel/test-trace-events-get-category-enabled-buffer.mjs @@ -0,0 +1,35 @@ +// Flags: --expose-internals + +import '../common/index.mjs'; +import { it } from 'node:test'; +import { createTracing, getEnabledCategories } from 'node:trace_events'; +import assert from 'node:assert'; + +import binding from 'internal/test/binding'; +const getCategoryEnabledBuffer = binding.internalBinding('trace_events').getCategoryEnabledBuffer; + +it('should track enabled/disabled categories', () => { + const random = Math.random().toString().slice(2); + const category = `node.${random}`; + + const buffer = getCategoryEnabledBuffer(category); + + const tracing = createTracing({ + categories: [category], + }); + + assert.ok(buffer[0] === 0, `the buffer[0] should start with value 0, got: ${buffer[0]}`); + + tracing.enable(); + + let currentCategories = getEnabledCategories(); + + assert.ok(currentCategories.includes(category), `the getEnabledCategories should include ${category}, got: ${currentCategories}`); + assert.ok(buffer[0] > 0, `the buffer[0] should be greater than 0, got: ${buffer[0]}`); + + tracing.disable(); + + currentCategories = getEnabledCategories(); + assert.ok(currentCategories === undefined, `the getEnabledCategories should return undefined, got: ${currentCategories}`); + assert.ok(buffer[0] === 0, `the buffer[0] should be 0, got: ${buffer[0]}`); +});