From df5083e5f9064a94c91e61887948127423dca3a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinicius=20Louren=C3=A7o?= <12551007+H4ad@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:40:22 -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. PR-URL: https://github.com/nodejs/node/pull/53602 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Yagiz Nizipli --- lib/internal/http.js | 6 ++- src/node_trace_events.cc | 27 ++++++++++++ ...race-events-get-category-enabled-buffer.js | 43 +++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-trace-events-get-category-enabled-buffer.js diff --git a/lib/internal/http.js b/lib/internal/http.js index 6fc0156bf5265f..251f51ec454f9c 100644 --- a/lib/internal/http.js +++ b/lib/internal/http.js @@ -6,7 +6,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, @@ -35,8 +35,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..9787b14352753c 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,27 @@ static void SetTraceCategoryStateUpdateHandler( env->set_trace_category_state_function(args[0].As()); } +static void GetCategoryEnabledBuffer(const FunctionCallbackInfo& args) { + CHECK(args[0]->IsString()); + + Isolate* isolate = args.GetIsolate(); + 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 +156,8 @@ void NodeCategorySet::Initialize(Local target, target, "setTraceCategoryStateUpdateHandler", SetTraceCategoryStateUpdateHandler); + SetMethod( + context, target, "getCategoryEnabledBuffer", GetCategoryEnabledBuffer); Local category_set = NewFunctionTemplate(isolate, NodeCategorySet::New); @@ -160,6 +186,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.js b/test/parallel/test-trace-events-get-category-enabled-buffer.js new file mode 100644 index 00000000000000..3017b8e6dc87d7 --- /dev/null +++ b/test/parallel/test-trace-events-get-category-enabled-buffer.js @@ -0,0 +1,43 @@ +'use strict'; +// Flags: --expose-internals + +const common = require('../common'); +const { it } = require('node:test'); + +try { + require('trace_events'); +} catch { + common.skip('missing trace events'); +} + +const { createTracing, getEnabledCategories } = require('trace_events'); +const assert = require('assert'); + +const binding = require('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]}`); +});