Skip to content

Commit

Permalink
src,lib: expose getCategoryEnabledBuffer to use on node.http
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
H4ad committed Jun 26, 2024
1 parent 53ac448 commit 0129dc3
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 2 deletions.
6 changes: 4 additions & 2 deletions lib/internal/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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';
Expand Down
36 changes: 36 additions & 0 deletions src/node_trace_events.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -120,6 +123,34 @@ static void SetTraceCategoryStateUpdateHandler(
env->set_trace_category_state_function(args[0].As<Function>());
}

static void GetCategoryEnabledBuffer(
const FunctionCallbackInfo<Value>& 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<uint8_t*>(
enabled_pointer
);

std::unique_ptr<BackingStore> 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<Uint8Array> u8 = v8::Uint8Array::New(ab, 0, 1);

args.GetReturnValue().Set(u8);
}

void NodeCategorySet::Initialize(Local<Object> target,
Local<Value> unused,
Local<Context> context,
Expand All @@ -132,6 +163,10 @@ void NodeCategorySet::Initialize(Local<Object> target,
target,
"setTraceCategoryStateUpdateHandler",
SetTraceCategoryStateUpdateHandler);
SetMethod(context,
target,
"getCategoryEnabledBuffer",
GetCategoryEnabledBuffer);

Local<FunctionTemplate> category_set =
NewFunctionTemplate(isolate, NodeCategorySet::New);
Expand Down Expand Up @@ -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);
Expand Down
35 changes: 35 additions & 0 deletions test/parallel/test-trace-events-get-category-enabled-buffer.mjs
Original file line number Diff line number Diff line change
@@ -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]}`);
});

0 comments on commit 0129dc3

Please sign in to comment.