diff --git a/lib/internal/http.js b/lib/internal/http.js index b20b3cd229efcd..c26c322aafc64e 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 bd2eefafb68cbc..c4960ee1427e3b 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]}`); +});