feat(api): improve isValidSpanId, isValidTraceId performance (#5714)

Co-authored-by: Marc Pichler <marc.pichler@dynatrace.com>
This commit is contained in:
Siim Kallas 2025-06-13 15:48:31 +03:00 committed by GitHub
parent 62fbfd3d0d
commit f2cfd1327a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 4 deletions

View File

@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
### :rocket: (Enhancement)
* feat(api): improve isValidSpanId, isValidTraceId performance [#5714](https://github.com/open-telemetry/opentelemetry-js/pull/5714) @seemk
* feat(diag): change types in `DiagComponentLogger` from `any` to `unknown`[#5478](https://github.com/open-telemetry/opentelemetry-js/pull/5478) @loganrosen
### :bug: (Bug Fix)

View File

@ -18,21 +18,43 @@ import { NonRecordingSpan } from './NonRecordingSpan';
import { Span } from './span';
import { SpanContext } from './span_context';
const VALID_TRACEID_REGEX = /^([0-9a-f]{32})$/i;
const VALID_SPANID_REGEX = /^[0-9a-f]{16}$/i;
// Valid characters (0-9, a-f, A-F) are marked as 1.
const isHex = new Uint8Array([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
]);
function isValidHex(id: string, length: number): boolean {
// As of 1.9.0 the id was allowed to be a non-string value,
// even though it was not possible in the types.
if (typeof id !== 'string' || id.length !== length) return false;
let r = 0;
for (let i = 0; i < id.length; i += 4) {
r +=
(isHex[id.charCodeAt(i)] | 0) +
(isHex[id.charCodeAt(i + 1)] | 0) +
(isHex[id.charCodeAt(i + 2)] | 0) +
(isHex[id.charCodeAt(i + 3)] | 0);
}
return r === length;
}
/**
* @since 1.0.0
*/
export function isValidTraceId(traceId: string): boolean {
return VALID_TRACEID_REGEX.test(traceId) && traceId !== INVALID_TRACEID;
return isValidHex(traceId, 32) && traceId !== INVALID_TRACEID;
}
/**
* @since 1.0.0
*/
export function isValidSpanId(spanId: string): boolean {
return VALID_SPANID_REGEX.test(spanId) && spanId !== INVALID_SPANID;
return isValidHex(spanId, 16) && spanId !== INVALID_SPANID;
}
/**

View File

@ -37,6 +37,17 @@ describe('spancontext-utils', function () {
assert.ok(!context.isSpanContextValid(spanContext));
});
it('should return false when traceId is malformed', function () {
// 0x4141 is not a hex character, but doing a bitwise AND with 0xFF
// would yield a valid character 'A'.
const spanContext = {
traceId: 'd4cda95b652f4a1592b449d5929fda1\u4141',
spanId: '6e0c63257de34c92',
traceFlags: TraceFlags.NONE,
};
assert.ok(!context.isSpanContextValid(spanContext));
});
it('should return false when spanId is invalid', function () {
const spanContext = {
traceId: 'd4cda95b652f4a1592b449d5929fda1b',