Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add BinaryFormat interface and implementation
- Loading branch information
1 parent
7b629d6
commit a9788a5
Showing
4 changed files
with
213 additions
and
0 deletions.
There are no files selected for viewing
95 changes: 95 additions & 0 deletions
95
packages/opentelemetry-core/src/context/propagation/BinaryTraceContext.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/** | ||
* Copyright 2019, OpenTelemetry Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import { BinaryFormat, SpanContext } from '@opentelemetry/types'; | ||
|
||
const VERSION_ID = 0; | ||
const TRACE_ID_FIELD_ID = 0; | ||
const SPAN_ID_FIELD_ID = 1; | ||
const TRACE_OPTION_FIELD_ID = 2; | ||
|
||
// Sizes are number of bytes. | ||
const ID_SIZE = 1; | ||
const TRACE_ID_SIZE = 16; | ||
const SPAN_ID_SIZE = 8; | ||
const TRACE_OPTION_SIZE = 1; | ||
|
||
const VERSION_ID_OFFSET = 0; | ||
const TRACE_ID_FIELD_ID_OFFSET = VERSION_ID_OFFSET + ID_SIZE; | ||
const TRACE_ID_OFFSET = TRACE_ID_FIELD_ID_OFFSET + ID_SIZE; | ||
const SPAN_ID_FIELD_ID_OFFSET = TRACE_ID_OFFSET + TRACE_ID_SIZE; | ||
const SPAN_ID_OFFSET = SPAN_ID_FIELD_ID_OFFSET + ID_SIZE; | ||
const TRACE_OPTION_FIELD_ID_OFFSET = SPAN_ID_OFFSET + SPAN_ID_SIZE; | ||
const TRACE_OPTIONS_OFFSET = TRACE_OPTION_FIELD_ID_OFFSET + ID_SIZE; | ||
|
||
const FORMAT_LENGTH = | ||
4 * ID_SIZE + TRACE_ID_SIZE + SPAN_ID_SIZE + TRACE_OPTION_SIZE; | ||
|
||
export class BinaryTraceContext implements BinaryFormat { | ||
toBytes(spanContext: SpanContext): Buffer { | ||
/** | ||
* 0 1 2 | ||
* 0 1 2345678901234567 8 90123456 7 8 | ||
* ------------------------------------- | ||
* | | | | | | | | | ||
* ------------------------------------- | ||
* ^ ^ ^ ^ ^ ^ ^ | ||
* | | | | | | `-- options value | ||
* | | | | | `---- options field ID (2) | ||
* | | | | `---------- spanID value | ||
* | | | `--------------- spanID field ID (1) | ||
* | | `--------------------------- traceID value | ||
* | `---------------------------------- 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) || 0, | ||
TRACE_OPTIONS_OFFSET | ||
); | ||
return result; | ||
} | ||
|
||
fromBytes(buffer: Buffer): SpanContext | null { | ||
const result: SpanContext = { traceId: '', spanId: '' }; | ||
// Length must be 29. | ||
if (buffer.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 | ||
) { | ||
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); | ||
return result; | ||
} | ||
} |
81 changes: 81 additions & 0 deletions
81
packages/opentelemetry-core/test/context/propagation/binarytracecontext.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/** | ||
* Copyright 2019, OpenTelemetry Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import * as assert from 'assert'; | ||
import { BinaryTraceContext } from '../../../src/context/propagation/BinaryTraceContext'; | ||
import { SpanContext } from '@opentelemetry/types'; | ||
|
||
describe('BinaryTraceContext', () => { | ||
const binaryTraceContext = new BinaryTraceContext(); | ||
const commonTraceId = 'd4cda95b652f4a1592b449d5929fda1b'; | ||
const commonSpanId = '75e8ed491aec7eca'; | ||
|
||
const testCases: Array<{ | ||
structured: SpanContext | null; | ||
binary: string; | ||
description: string; | ||
}> = [ | ||
{ | ||
structured: { | ||
traceId: commonTraceId, | ||
spanId: commonSpanId, | ||
traceOptions: 1, | ||
}, | ||
binary: `0000${commonTraceId}01${commonSpanId}02${'01'}`, | ||
description: 'span context with 64-bit span ID', | ||
}, | ||
{ | ||
structured: { traceId: commonTraceId, spanId: commonSpanId }, | ||
binary: `0000${commonTraceId}01${commonSpanId}02${'00'}`, | ||
description: 'span context with no traceOptions', | ||
}, | ||
{ | ||
structured: null, | ||
binary: '00', | ||
description: 'incomplete binary span context (by returning null)', | ||
}, | ||
{ | ||
structured: null, | ||
binary: '0'.repeat(58), | ||
description: 'bad binary span context (by returning null)', | ||
}, | ||
]; | ||
|
||
describe('toBytes', () => { | ||
testCases.forEach( | ||
testCase => | ||
testCase.structured && | ||
it(`should serialize ${testCase.description}`, () => { | ||
assert.deepStrictEqual( | ||
binaryTraceContext.toBytes(testCase.structured!).toString('hex'), | ||
testCase.binary | ||
); | ||
}) | ||
); | ||
}); | ||
|
||
describe('fromBytes', () => { | ||
testCases.forEach(testCase => | ||
it(`should deserialize ${testCase.description}`, () => { | ||
assert.deepStrictEqual( | ||
binaryTraceContext.fromBytes(Buffer.from(testCase.binary, 'hex')), | ||
testCase.structured && | ||
Object.assign({ traceOptions: 0 }, testCase.structured) | ||
); | ||
}) | ||
); | ||
}); | ||
}); |
36 changes: 36 additions & 0 deletions
36
packages/opentelemetry-types/src/context/propagation/BinaryFormat.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* Copyright 2019, OpenTelemetry Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import { SpanContext } from '../../trace/span_context'; | ||
|
||
/** | ||
* Formatter to serializing and deserializing a value with into a binary format. | ||
*/ | ||
export interface BinaryFormat { | ||
/** | ||
* Serialize the given span context into a Buffer. | ||
* @param spanContext The span context to serialize. | ||
*/ | ||
toBytes(spanContext: SpanContext): Buffer; | ||
|
||
/** | ||
* Deseralize the given span context from binary encoding. If the input is a | ||
* Buffer of incorrect size or unexpected fields, then this function will | ||
* return `null`. | ||
* @param buffer The span context to deserialize. | ||
*/ | ||
fromBytes(buffer: Buffer): SpanContext | null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters