From 531c497abb1df6315bcf92971fa343d1671e5a58 Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Wed, 10 Jul 2019 21:41:17 -0700 Subject: [PATCH] Use ArrayBuffer instead of Buffer --- .../context/propagation/BinaryTraceContext.ts | 67 ++++++++++------- .../test/context/BinaryTraceContext.test.ts | 74 +++++++++++++++++-- .../src/context/propagation/BinaryFormat.ts | 4 +- 3 files changed, 110 insertions(+), 35 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/BinaryTraceContext.ts b/packages/opentelemetry-core/src/context/propagation/BinaryTraceContext.ts index b97142d9adb..75c6f57a3ab 100644 --- a/packages/opentelemetry-core/src/context/propagation/BinaryTraceContext.ts +++ b/packages/opentelemetry-core/src/context/propagation/BinaryTraceContext.ts @@ -39,7 +39,7 @@ const FORMAT_LENGTH = 4 * ID_SIZE + TRACE_ID_SIZE + SPAN_ID_SIZE + TRACE_OPTION_SIZE; export class BinaryTraceContext implements BinaryFormat { - toBytes(spanContext: SpanContext): Buffer { + toBytes(spanContext: SpanContext): Uint8Array { /** * 0 1 2 * 0 1 2345678901234567 8 90123456 7 8 @@ -55,41 +55,56 @@ export class BinaryTraceContext implements BinaryFormat { * | `---------------------------------- traceID field ID (0) * `------------------------------------ version (0) */ - const result = Buffer.alloc(FORMAT_LENGTH, 0); - result.write(spanContext.traceId, TRACE_ID_OFFSET, TRACE_ID_SIZE, 'hex'); - result.writeUInt8(SPAN_ID_FIELD_ID, SPAN_ID_FIELD_ID_OFFSET); - result.write(spanContext.spanId, SPAN_ID_OFFSET, SPAN_ID_SIZE, 'hex'); - result.writeUInt8(TRACE_OPTION_FIELD_ID, TRACE_OPTION_FIELD_ID_OFFSET); - result.writeUInt8( - Number(spanContext.traceOptions) || TraceOptions.UNSAMPLED, - TRACE_OPTIONS_OFFSET - ); - return result; + const traceId = spanContext.traceId; + const spanId = spanContext.spanId; + const buf = new Uint8Array(FORMAT_LENGTH); + let j = TRACE_ID_OFFSET; + for (let i = TRACE_ID_OFFSET; i < SPAN_ID_FIELD_ID_OFFSET; i++) { + // tslint:disable-next-line:ban Needed to parse hexadecimal. + buf[j++] = parseInt(traceId.substr((i - TRACE_ID_OFFSET) * 2, 2), 16); + } + buf[j++] = SPAN_ID_FIELD_ID; + for (let i = SPAN_ID_OFFSET; i < TRACE_OPTION_FIELD_ID_OFFSET; i++) { + // tslint:disable-next-line:ban Needed to parse hexadecimal. + buf[j++] = parseInt(spanId.substr((i - SPAN_ID_OFFSET) * 2, 2), 16); + } + buf[j++] = TRACE_OPTION_FIELD_ID; + buf[j++] = Number(spanContext.traceOptions) || TraceOptions.UNSAMPLED; + return buf; } - fromBytes(buffer: Buffer): SpanContext | null { + fromBytes(buf: Uint8Array): SpanContext | null { const result: SpanContext = { traceId: '', spanId: '' }; // Length must be 29. - if (buffer.length !== FORMAT_LENGTH) { - return null; - } + if (buf.length !== FORMAT_LENGTH) return null; // Check version and field numbers. if ( - buffer.readUInt8(VERSION_ID_OFFSET) !== VERSION_ID || - buffer.readUInt8(TRACE_ID_FIELD_ID_OFFSET) !== TRACE_ID_FIELD_ID || - buffer.readUInt8(SPAN_ID_FIELD_ID_OFFSET) !== SPAN_ID_FIELD_ID || - buffer.readUInt8(TRACE_OPTION_FIELD_ID_OFFSET) !== TRACE_OPTION_FIELD_ID + buf[VERSION_ID_OFFSET] !== VERSION_ID || + buf[TRACE_ID_FIELD_ID_OFFSET] !== TRACE_ID_FIELD_ID || + buf[SPAN_ID_FIELD_ID_OFFSET] !== SPAN_ID_FIELD_ID || + buf[TRACE_OPTION_FIELD_ID_OFFSET] !== TRACE_OPTION_FIELD_ID ) { return null; } // See serializeSpanContext for byte offsets. - result.traceId = buffer - .slice(TRACE_ID_OFFSET, SPAN_ID_FIELD_ID_OFFSET) - .toString('hex'); - result.spanId = buffer - .slice(SPAN_ID_OFFSET, TRACE_OPTION_FIELD_ID_OFFSET) - .toString('hex'); - result.traceOptions = buffer.readUInt8(TRACE_OPTIONS_OFFSET); + result.traceId = toHex(buf.slice(TRACE_ID_OFFSET, SPAN_ID_FIELD_ID_OFFSET)); + result.spanId = toHex( + buf.slice(SPAN_ID_OFFSET, TRACE_OPTION_FIELD_ID_OFFSET) + ); + result.traceOptions = buf[TRACE_OPTIONS_OFFSET]; return result; } } + +function toHex(buff: Uint8Array) { + let out = ''; + for (let i = 0; i < buff.length; ++i) { + const n = buff[i]; + if (n < 16) { + out += '0' + n.toString(16); + } else { + out += n.toString(16); + } + } + return out; +} diff --git a/packages/opentelemetry-core/test/context/BinaryTraceContext.test.ts b/packages/opentelemetry-core/test/context/BinaryTraceContext.test.ts index a2a27afff82..226735d79c0 100644 --- a/packages/opentelemetry-core/test/context/BinaryTraceContext.test.ts +++ b/packages/opentelemetry-core/test/context/BinaryTraceContext.test.ts @@ -25,7 +25,7 @@ describe('BinaryTraceContext', () => { const testCases: Array<{ structured: SpanContext | null; - binary: string; + binary: Uint8Array; description: string; }> = [ { @@ -34,22 +34,82 @@ describe('BinaryTraceContext', () => { spanId: commonSpanId, traceOptions: TraceOptions.SAMPLED, }, - binary: `0000${commonTraceId}01${commonSpanId}02${'01'}`, + binary: new Uint8Array([ + 0, + 0, + 212, + 205, + 169, + 91, + 101, + 47, + 74, + 21, + 146, + 180, + 73, + 213, + 146, + 159, + 218, + 27, + 1, + 117, + 232, + 237, + 73, + 26, + 236, + 126, + 202, + 2, + 1, + ]), description: 'span context with 64-bit span ID', }, { structured: { traceId: commonTraceId, spanId: commonSpanId }, - binary: `0000${commonTraceId}01${commonSpanId}02${'00'}`, + binary: new Uint8Array([ + 0, + 0, + 212, + 205, + 169, + 91, + 101, + 47, + 74, + 21, + 146, + 180, + 73, + 213, + 146, + 159, + 218, + 27, + 1, + 117, + 232, + 237, + 73, + 26, + 236, + 126, + 202, + 2, + 0, + ]), description: 'span context with no traceOptions', }, { structured: null, - binary: '00', + binary: new Uint8Array([0, 0]), description: 'incomplete binary span context (by returning null)', }, { structured: null, - binary: '0'.repeat(58), + binary: new Uint8Array(58), description: 'bad binary span context (by returning null)', }, ]; @@ -60,7 +120,7 @@ describe('BinaryTraceContext', () => { testCase.structured && it(`should serialize ${testCase.description}`, () => { assert.deepStrictEqual( - binaryTraceContext.toBytes(testCase.structured!).toString('hex'), + binaryTraceContext.toBytes(testCase.structured!), testCase.binary ); }) @@ -71,7 +131,7 @@ describe('BinaryTraceContext', () => { testCases.forEach(testCase => it(`should deserialize ${testCase.description}`, () => { assert.deepStrictEqual( - binaryTraceContext.fromBytes(Buffer.from(testCase.binary, 'hex')), + binaryTraceContext.fromBytes(testCase.binary), testCase.structured && Object.assign( { traceOptions: TraceOptions.UNSAMPLED }, diff --git a/packages/opentelemetry-types/src/context/propagation/BinaryFormat.ts b/packages/opentelemetry-types/src/context/propagation/BinaryFormat.ts index 2ae194a61c9..16f270592aa 100644 --- a/packages/opentelemetry-types/src/context/propagation/BinaryFormat.ts +++ b/packages/opentelemetry-types/src/context/propagation/BinaryFormat.ts @@ -24,7 +24,7 @@ export interface BinaryFormat { * Serialize the given span context into a Buffer. * @param spanContext The span context to serialize. */ - toBytes(spanContext: SpanContext): Buffer; + toBytes(spanContext: SpanContext): ArrayBuffer; /** * Deseralize the given span context from binary encoding. If the input is a @@ -32,5 +32,5 @@ export interface BinaryFormat { * return `null`. * @param buffer The span context to deserialize. */ - fromBytes(buffer: Buffer): SpanContext | null; + fromBytes(buffer: ArrayBuffer): SpanContext | null; }