diff --git a/src/nsolid/nsolid_api.cc b/src/nsolid/nsolid_api.cc index c25187873ab..b2c7b899ece 100644 --- a/src/nsolid/nsolid_api.cc +++ b/src/nsolid/nsolid_api.cc @@ -10,11 +10,13 @@ #include "util.h" #include "env-inl.h" #include "uv.h" +#include "node_debug.h" #include "node_internals.h" #include "node_external_reference.h" #include "memory_tracker-inl.h" #include "node_perf.h" #include "node_url.h" +#include "simdutf.h" #include "v8-fast-api-calls.h" #include @@ -93,6 +95,16 @@ constexpr size_t datapoints_q_max_size = 100; static const char* get_startuptime_name(const char* name); +static std::string OneByteToUtf8(const FastOneByteString& input) { + std::string out; + out.resize(input.length * 2); + + const size_t actual_length = simdutf::convert_latin1_to_utf8( + input.data, input.length, out.data()); + out.resize(actual_length); + return out; +} + EnvInst::EnvInst(Environment* env) : count_fields(), @@ -2474,10 +2486,11 @@ void BindingData::FastPushSpanDataString(v8::Local receiver, uint32_t trace_id, uint32_t type, const FastOneByteString& val) { + TRACK_V8_FAST_API_CALL("nsolid.pushSpanDataString"); PushSpanDataStringImpl(FromJSObject(receiver), trace_id, type, - std::string(val.data, val.length)); + OneByteToUtf8(val)); } @@ -2521,12 +2534,13 @@ void BindingData::FastPushSpanDataString3(v8::Local receiver, const FastOneByteString& val1, const FastOneByteString& val2, const FastOneByteString& val3) { + TRACK_V8_FAST_API_CALL("nsolid.pushSpanDataString3"); PushSpanDataStringImpl3(FromJSObject(receiver), - trace_id, - type, - std::string(val1.data, val1.length), - std::string(val2.data, val2.length), - std::string(val3.data, val3.length)); + trace_id, + type, + OneByteToUtf8(val1), + OneByteToUtf8(val2), + OneByteToUtf8(val3)); } void BindingData::PushSpanDataStringImpl3(BindingData* data, diff --git a/test/addons/nsolid-tracing/test-fast-api-string-latin1.js b/test/addons/nsolid-tracing/test-fast-api-string-latin1.js new file mode 100644 index 00000000000..b6dcd49819c --- /dev/null +++ b/test/addons/nsolid-tracing/test-fast-api-string-latin1.js @@ -0,0 +1,89 @@ +// Flags: --expose-internals --no-warnings --allow-natives-syntax +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); +const { internalBinding } = require('internal/test/binding'); +const { checkTracesOnExit } = require('../../common/nsolid-traces'); +const { setupNSolid } = require('./utils'); +const fixtures = require('../../common/fixtures'); +const addonBindingPath = require.resolve(`./build/${common.buildType}/binding`); +const addonBinding = require(addonBindingPath); + +const nsolidBinding = internalBinding('nsolid_api'); +const { nsolid_consts } = nsolidBinding; +const nsolid = require('nsolid'); +const api = require(require.resolve('@opentelemetry/api', + { paths: [fixtures.fixturesDir] })); + +const expectedTraces = [ + { + attributes: { + 'http.url': 'http://localhost/ma\u00f1ana', + }, + end_reason: addonBinding.kSpanEndOk, + name: 'Espa\u00f1a', + parentId: '0000000000000000', + thread_id: 0, + kind: addonBinding.kClient, + type: addonBinding.kSpanCustom, + status: { + code: api.SpanStatusCode.OK, + }, + }, +]; + +checkTracesOnExit(addonBinding, expectedTraces); + +setupNSolid({ lookup: false }, common.mustCall(() => { + if (!nsolid.otel.register(api)) { + throw new Error('Error registering api'); + } + + const tracer = api.trace.getTracer('test'); + const span = tracer.startSpan('initial_name', { kind: api.SpanKind.CLIENT }); + + function pushSpanName() { + nsolidBinding.pushSpanDataString(span.internalId, + nsolid_consts.kSpanName, + 'Espa\u00f1a'); + } + + function pushSpanUrl() { + nsolidBinding.pushSpanDataString3(span.internalId, + nsolid_consts.kSpanHttpReqUrl, + 'http:', + 'localhost', + '/ma\u00f1ana'); + } + + if (common.isDebug) { + const { getV8FastApiCallCount } = internalBinding('debug'); + assert.strictEqual(getV8FastApiCallCount('nsolid.pushSpanDataString'), 0); + assert.strictEqual(getV8FastApiCallCount('nsolid.pushSpanDataString3'), 0); + + eval('%PrepareFunctionForOptimization(pushSpanName)'); + pushSpanName(); + eval('%PrepareFunctionForOptimization(pushSpanUrl)'); + pushSpanUrl(); + + assert.strictEqual(getV8FastApiCallCount('nsolid.pushSpanDataString'), 0); + assert.strictEqual(getV8FastApiCallCount('nsolid.pushSpanDataString3'), 0); + + eval('%OptimizeFunctionOnNextCall(pushSpanName)'); + pushSpanName(); + eval('%OptimizeFunctionOnNextCall(pushSpanUrl)'); + pushSpanUrl(); + + assert.strictEqual(getV8FastApiCallCount('nsolid.pushSpanDataString'), 1); + assert.strictEqual(getV8FastApiCallCount('nsolid.pushSpanDataString3'), 1); + } else { + pushSpanName(); + pushSpanUrl(); + } + + span.setStatus({ code: api.SpanStatusCode.OK }); + span.end(); + + setTimeout(() => {}, 100); +})); diff --git a/test/addons/nsolid-tracing/test-otel-basic.js b/test/addons/nsolid-tracing/test-otel-basic.js index cb10375056f..5a847983b45 100644 --- a/test/addons/nsolid-tracing/test-otel-basic.js +++ b/test/addons/nsolid-tracing/test-otel-basic.js @@ -23,6 +23,7 @@ const expectedTraces = [ c: 3, d: 4, e: 5, + latin1: 'Espa\u00f1a', }, events: [ { @@ -69,6 +70,7 @@ setupNSolid(common.mustCall(() => { assert.strictEqual(span.updateName('my name'), span); assert.strictEqual(span.setAttributes({ c: 3, d: 4 }), span); assert.strictEqual(span.setAttribute('e', 5), span); + assert.strictEqual(span.setAttribute('latin1', 'Espa\u00f1a'), span); assert.strictEqual(span.addEvent('my_event 1', Date.now()), span); assert.strictEqual( span.addEvent('my_event 2', { attr1: 'val1', attr2: 'val2' }, Date.now()), diff --git a/test/agents/test-grpc-tracing.mjs b/test/agents/test-grpc-tracing.mjs index 93a7f90967a..0f797d5931e 100644 --- a/test/agents/test-grpc-tracing.mjs +++ b/test/agents/test-grpc-tracing.mjs @@ -53,6 +53,7 @@ const expectedCustomAttributes = (threadId) => { 'b': [ 'intValue', '2', false ], 'c': [ 'intValue', '3', false ], 'd': [ 'intValue', '4', false ], + 'latin1': [ 'stringValue', 'Espa\u00f1a', false ], 'e': [ 'arrayValue', [ { stringValue: 'abAD', value: 'stringValue' }, { stringValue: 'cdCF', value: 'stringValue' }, diff --git a/test/common/nsolid-grpc-agent/client.js b/test/common/nsolid-grpc-agent/client.js index 5acca808308..c8972dedc4f 100644 --- a/test/common/nsolid-grpc-agent/client.js +++ b/test/common/nsolid-grpc-agent/client.js @@ -98,6 +98,7 @@ function execCustomTrace() { const span = tracer.startSpan('initial_name', { attributes: { a: 1, b: 2 }, kind: api.SpanKind.CLIENT }); span.setAttributes({ c: 3, d: 4 }) + .setAttribute('latin1', 'Espa\u00f1a') .setAttribute('e', [ 'abAD', 'cdCF']) .addEvent('my_event 1', Date.now()) .addEvent('my_event 2', { attr1: 'val1', attr2: 'val2' }, Date.now());