Skip to content

Commit

Permalink
feat: fast span and trace id generation
Browse files Browse the repository at this point in the history
  • Loading branch information
dyladan committed Jul 24, 2020
1 parent 0f0c08a commit 4fa8e37
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 38 deletions.
44 changes: 13 additions & 31 deletions packages/opentelemetry-core/src/platform/browser/id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
declare type WindowWithMsCrypto = Window & {
msCrypto?: Crypto;
};
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 {
cryptoLib.getRandomValues(randomBytesArray);
return toHex(randomBytesArray.slice(0, TRACE_ID_BYTES));
}
export const randomTraceId = getIdGenerator(TRACE_ID_BYTES);

/** Returns a random 8-byte span ID formatted as a 16-char hex string. */
export function randomSpanId(): string {
cryptoLib.getRandomValues(randomBytesArray);
return toHex(randomBytesArray.slice(0, SPAN_ID_BYTES));
}

/**
* 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);
export const randomSpanId = getIdGenerator(SPAN_ID_BYTES);

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;
const SHARED_CHAR_CODES_ARRAY = Array(32);
function getIdGenerator(bytes: number): () => string {
return function generateId() {
for (let i = 0; i < bytes * 2; i++) {
SHARED_CHAR_CODES_ARRAY[i] = (Math.floor(Math.random() * 16)) + 48;
// valid hex characters in the range 48-57 and 97-102
if (SHARED_CHAR_CODES_ARRAY[i] >= 58) {
SHARED_CHAR_CODES_ARRAY[i] += 39
}
}
return String.fromCharCode.apply(null, SHARED_CHAR_CODES_ARRAY.slice(0, bytes * 2));
}

return String.fromCharCode.apply(null, chars);
}
18 changes: 11 additions & 7 deletions packages/opentelemetry-core/src/platform/node/id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,27 @@
* limitations under the License.
*/

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 crypto.randomBytes(TRACE_ID_BYTES).toString('hex');
}
export const randomTraceId = getIdGenerator(TRACE_ID_BYTES);

/**
* Returns a random 8-byte span ID formatted/encoded as a 16 lowercase hex
* characters corresponding to 64 bits.
*/
export function randomSpanId(): string {
return crypto.randomBytes(SPAN_ID_BYTES).toString('hex');
export const randomSpanId = getIdGenerator(SPAN_ID_BYTES);

const SHARED_BUFFER = Buffer.allocUnsafe(TRACE_ID_BYTES);
function getIdGenerator(bytes: number): () => string {
return function generateId() {
for (let i = 0; i < bytes; i++) {
SHARED_BUFFER[i] = Math.floor(Math.random() * 256);
}
return SHARED_BUFFER.slice(0, bytes).toString('hex');
}
}
1 change: 1 addition & 0 deletions packages/opentelemetry-core/test/platform/id.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { randomSpanId, randomTraceId } from '../../src/platform';
describe('randomTraceId', () => {
it('returns 32 character hex strings', () => {
const traceId = randomTraceId();
console.log(traceId);
assert.ok(traceId.match(/[a-f0-9]{32}/));
assert.ok(!traceId.match(/^0+$/));
});
Expand Down

0 comments on commit 4fa8e37

Please sign in to comment.