From f7b2e93dadd60649e1de21080f11f3bf131bcee6 Mon Sep 17 00:00:00 2001 From: Daniel Dyla Date: Fri, 28 Feb 2020 15:37:26 -0500 Subject: [PATCH 1/5] chore: faster trace id generation --- .../src/platform/browser/id.ts | 23 +++++++++++-------- .../src/platform/node/id.ts | 3 ++- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/opentelemetry-core/src/platform/browser/id.ts b/packages/opentelemetry-core/src/platform/browser/id.ts index ab1c8188ac..e5a701ab0e 100644 --- a/packages/opentelemetry-core/src/platform/browser/id.ts +++ b/packages/opentelemetry-core/src/platform/browser/id.ts @@ -21,24 +21,29 @@ declare type WindowWithMsCrypto = Window & { const cryptoLib = window.crypto || (window as WindowWithMsCrypto).msCrypto; const SPAN_ID_BYTES = 8; -const spanBytesArray = new Uint8Array(SPAN_ID_BYTES); +const TRACE_ID_BYTES = 16; /** Returns a random 16-byte trace ID formatted as a 32-char hex string. */ export function randomTraceId(): string { - return randomSpanId() + randomSpanId(); + return randomId(TRACE_ID_BYTES); } /** Returns a random 8-byte span ID formatted as a 16-char hex string. */ export function randomSpanId(): string { - let spanId = ''; - cryptoLib.getRandomValues(spanBytesArray); - for (let i = 0; i < SPAN_ID_BYTES; i++) { - const hexStr = spanBytesArray[i].toString(16); + return randomId(SPAN_ID_BYTES); +} + +const randomBytesArray = new Uint8Array(TRACE_ID_BYTES); +function randomId(byteLength: number): string { + let id = ''; + cryptoLib.getRandomValues(randomBytesArray); + for (let i = 0; i < byteLength; i++) { + const hexStr = randomBytesArray[i].toString(16); // Zero pad bytes whose hex values are single digit. - if (hexStr.length === 1) spanId += '0'; + if (hexStr.length === 1) id += '0'; - spanId += hexStr; + id += hexStr; } - return spanId; + return id; } diff --git a/packages/opentelemetry-core/src/platform/node/id.ts b/packages/opentelemetry-core/src/platform/node/id.ts index 75350e6eff..fa4cd6a916 100644 --- a/packages/opentelemetry-core/src/platform/node/id.ts +++ b/packages/opentelemetry-core/src/platform/node/id.ts @@ -17,13 +17,14 @@ import * as crypto from 'crypto'; const SPAN_ID_BYTES = 8; +const TRACE_ID_BYTES = 16; /** * Returns a random 16-byte trace ID formatted/encoded as a 32 lowercase hex * characters corresponding to 128 bits. */ export function randomTraceId(): string { - return randomSpanId() + randomSpanId(); + return crypto.randomBytes(TRACE_ID_BYTES).toString('hex'); } /** From 070260757f5eba2aa07b3290069aacbff516440e Mon Sep 17 00:00:00 2001 From: Daniel Dyla Date: Tue, 3 Mar 2020 09:37:00 -0500 Subject: [PATCH 2/5] chore: faster browser trace id gen --- .../src/platform/browser/id.ts | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/packages/opentelemetry-core/src/platform/browser/id.ts b/packages/opentelemetry-core/src/platform/browser/id.ts index e5a701ab0e..89fc0de3ff 100644 --- a/packages/opentelemetry-core/src/platform/browser/id.ts +++ b/packages/opentelemetry-core/src/platform/browser/id.ts @@ -22,28 +22,38 @@ const cryptoLib = window.crypto || (window as WindowWithMsCrypto).msCrypto; const SPAN_ID_BYTES = 8; const TRACE_ID_BYTES = 16; +const randomBytesArray = new Uint8Array(TRACE_ID_BYTES); /** Returns a random 16-byte trace ID formatted as a 32-char hex string. */ export function randomTraceId(): string { - return randomId(TRACE_ID_BYTES); + cryptoLib.getRandomValues(randomBytesArray); + return toHex(randomBytesArray.slice(0, TRACE_ID_BYTES)); } /** Returns a random 8-byte span ID formatted as a 16-char hex string. */ export function randomSpanId(): string { - return randomId(SPAN_ID_BYTES); + cryptoLib.getRandomValues(randomBytesArray); + return toHex(randomBytesArray.slice(0, SPAN_ID_BYTES)); } -const randomBytesArray = new Uint8Array(TRACE_ID_BYTES); -function randomId(byteLength: number): string { - let id = ''; - cryptoLib.getRandomValues(randomBytesArray); - for (let i = 0; i < byteLength; i++) { - const hexStr = randomBytesArray[i].toString(16); - // Zero pad bytes whose hex values are single digit. - if (hexStr.length === 1) id += '0'; +/** + * Get the hex string representation of a byte array + * + * @param byteArray + */ +function toHex(byteArray: Uint8Array) { + const chars: number[] = new Array(byteArray.length * 2); + const alpha = 'a'.charCodeAt(0) - 10; + const digit = '0'.charCodeAt(0); - id += hexStr; + let p = 0; + for (let i = 0; i < byteArray.length; i++) { + let nibble = (byteArray[i] >>> 4) & 0xf; + chars[p++] = nibble > 9 ? nibble + alpha : nibble + digit; + nibble = byteArray[i] & 0xf; + chars[p++] = nibble > 9 ? nibble + alpha : nibble + digit; } - return id; + + return String.fromCharCode.apply(null, chars); } From 1b0a87d6a74700e383531e89d6cf1d46c54d4c21 Mon Sep 17 00:00:00 2001 From: Daniel Dyla Date: Tue, 3 Mar 2020 09:43:22 -0500 Subject: [PATCH 3/5] chore: lint --- packages/opentelemetry-core/src/platform/browser/id.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/opentelemetry-core/src/platform/browser/id.ts b/packages/opentelemetry-core/src/platform/browser/id.ts index 89fc0de3ff..02af4b220e 100644 --- a/packages/opentelemetry-core/src/platform/browser/id.ts +++ b/packages/opentelemetry-core/src/platform/browser/id.ts @@ -36,11 +36,10 @@ export function randomSpanId(): string { return toHex(randomBytesArray.slice(0, SPAN_ID_BYTES)); } - /** * Get the hex string representation of a byte array - * - * @param byteArray + * + * @param byteArray */ function toHex(byteArray: Uint8Array) { const chars: number[] = new Array(byteArray.length * 2); From f539c9939d19d67a494fe62a81872c9572179838 Mon Sep 17 00:00:00 2001 From: Daniel Dyla Date: Tue, 3 Mar 2020 12:29:42 -0500 Subject: [PATCH 4/5] chore: expand id generation testing --- .../test/platform/id.test.ts | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/opentelemetry-core/test/platform/id.test.ts b/packages/opentelemetry-core/test/platform/id.test.ts index 4a7226d392..6163c95f5b 100644 --- a/packages/opentelemetry-core/test/platform/id.test.ts +++ b/packages/opentelemetry-core/test/platform/id.test.ts @@ -18,15 +18,31 @@ import * as assert from 'assert'; import { randomSpanId, randomTraceId } from '../../src/platform'; describe('randomTraceId', () => { - it('returns different 32-char hex strings', () => { + it('returns 32 character hex strings', () => { const traceId = randomTraceId(); assert.ok(traceId.match(/[a-f0-9]{32}/)); + assert.ok(!traceId.match(/^0+$/)) + }); + + it('returns different ids on each call', () => { + const traceId1 = randomTraceId(); + const traceId2 = randomTraceId(); + + assert.notDeepStrictEqual(traceId1, traceId2); }); }); describe('randomSpanId', () => { - it('returns different 16-char hex string', () => { + it('returns 16 character hex strings', () => { const spanId = randomSpanId(); assert.ok(spanId.match(/[a-f0-9]{16}/)); + assert.ok(!spanId.match(/^0+$/)) + }) + + it('returns different ids on each call', () => { + const spanId1 = randomSpanId(); + const spanId2 = randomSpanId(); + + assert.notDeepStrictEqual(spanId1, spanId2); }); }); From 2b27335d29e1187c9e9401fe481baf73238605cc Mon Sep 17 00:00:00 2001 From: Daniel Dyla Date: Tue, 3 Mar 2020 13:17:36 -0500 Subject: [PATCH 5/5] chore: lint --- packages/opentelemetry-core/test/platform/id.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/opentelemetry-core/test/platform/id.test.ts b/packages/opentelemetry-core/test/platform/id.test.ts index 6163c95f5b..8c4b7d0dc4 100644 --- a/packages/opentelemetry-core/test/platform/id.test.ts +++ b/packages/opentelemetry-core/test/platform/id.test.ts @@ -21,7 +21,7 @@ describe('randomTraceId', () => { it('returns 32 character hex strings', () => { const traceId = randomTraceId(); assert.ok(traceId.match(/[a-f0-9]{32}/)); - assert.ok(!traceId.match(/^0+$/)) + assert.ok(!traceId.match(/^0+$/)); }); it('returns different ids on each call', () => { @@ -36,8 +36,8 @@ describe('randomSpanId', () => { it('returns 16 character hex strings', () => { const spanId = randomSpanId(); assert.ok(spanId.match(/[a-f0-9]{16}/)); - assert.ok(!spanId.match(/^0+$/)) - }) + assert.ok(!spanId.match(/^0+$/)); + }); it('returns different ids on each call', () => { const spanId1 = randomSpanId();