Skip to content

Commit

Permalink
Feat: Make ID generator configurable (open-telemetry#1331)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Dyla <dyladan@users.noreply.github.com>
  • Loading branch information
2 people authored and jonahrosenblum committed Aug 6, 2020
1 parent 0a0a487 commit 802c5ad
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 95 deletions.
1 change: 1 addition & 0 deletions packages/opentelemetry-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ export * from './trace/sampler/ParentOrElseSampler';
export * from './trace/sampler/ProbabilitySampler';
export * from './trace/spancontext-utils';
export * from './trace/TraceState';
export * from './trace/IdGenerator';
export * from './utils/url';
export * from './utils/wrap';
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright The 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 { IdGenerator } from '../../trace/IdGenerator';

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);

export class RandomIdGenerator implements IdGenerator {
/**
* Returns a random 16-byte trace ID formatted/encoded as a 32 lowercase hex
* characters corresponding to 128 bits.
*/
generateTraceId(): string {
cryptoLib.getRandomValues(randomBytesArray);
return this.toHex(randomBytesArray.slice(0, TRACE_ID_BYTES));
}

/**
* Returns a random 8-byte span ID formatted/encoded as a 16 lowercase hex
* characters corresponding to 64 bits.
*/
generateSpanId(): string {
cryptoLib.getRandomValues(randomBytesArray);
return this.toHex(randomBytesArray.slice(0, SPAN_ID_BYTES));
}

/**
* Get the hex string representation of a byte array
*
* @param byteArray
*/
private toHex(byteArray: Uint8Array) {
const chars: number[] = new Array(byteArray.length * 2);
const alpha = 'a'.charCodeAt(0) - 10;
const digit = '0'.charCodeAt(0);

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 String.fromCharCode.apply(null, chars);
}
}
56 changes: 0 additions & 56 deletions packages/opentelemetry-core/src/platform/browser/id.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/opentelemetry-core/src/platform/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
export * from './BasePlugin';
export * from './environment';
export * from './hex-to-base64';
export * from './id';
export * from './RandomIdGenerator';
export * from './performance';
export * from './sdk-info';
export * from './timer-util';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,25 @@
*/

import * as crypto from 'crypto';
import { IdGenerator } from '../../trace/IdGenerator';

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 class RandomIdGenerator implements IdGenerator {
/**
* Returns a random 16-byte trace ID formatted/encoded as a 32 lowercase hex
* characters corresponding to 128 bits.
*/
generateTraceId(): string {
return crypto.randomBytes(TRACE_ID_BYTES).toString('hex');
}

/**
* 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');
/**
* Returns a random 8-byte span ID formatted/encoded as a 16 lowercase hex
* characters corresponding to 64 bits.
*/
generateSpanId(): string {
return crypto.randomBytes(SPAN_ID_BYTES).toString('hex');
}
}
2 changes: 1 addition & 1 deletion packages/opentelemetry-core/src/platform/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
export * from './BasePlugin';
export * from './environment';
export * from './hex-to-base64';
export * from './id';
export * from './RandomIdGenerator';
export * from './performance';
export * from './sdk-info';
export * from './timer-util';
Expand Down
23 changes: 23 additions & 0 deletions packages/opentelemetry-core/src/trace/IdGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright The 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.
*/

/** IdGenerator provides an interface for generating Trace Id and Span Id */
export interface IdGenerator {
/** Returns a trace ID composed of 32 lowercase hex characters. */
generateTraceId(): string;
/** Returns a span ID composed of 16 lowercase hex characters. */
generateSpanId(): string;
}
8 changes: 4 additions & 4 deletions packages/opentelemetry-core/test/context/composite.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ import * as assert from 'assert';
import {
CompositePropagator,
HttpTraceContext,
randomSpanId,
randomTraceId,
RandomIdGenerator,
} from '../../src';
import {
getExtractedSpanContext,
Expand All @@ -49,8 +48,9 @@ describe('Composite Propagator', () => {
let spanId: string;

beforeEach(() => {
traceId = randomTraceId();
spanId = randomSpanId();
const idGenerator = new RandomIdGenerator();
traceId = idGenerator.generateTraceId();
spanId = idGenerator.generateSpanId();
});

describe('inject', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,41 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as assert from 'assert';
import { randomSpanId, randomTraceId } from '../../src/platform';
import { RandomIdGenerator } from '../../src/platform';

const idGenerator = new RandomIdGenerator();

describe('randomTraceId', () => {
let traceId1: string, traceId2: string;
beforeEach(() => {
traceId1 = idGenerator.generateTraceId();
traceId2 = idGenerator.generateTraceId();
});

it('returns 32 character hex strings', () => {
const traceId = randomTraceId();
assert.ok(traceId.match(/[a-f0-9]{32}/));
assert.ok(!traceId.match(/^0+$/));
assert.ok(traceId1.match(/[a-f0-9]{32}/));
assert.ok(!traceId1.match(/^0+$/));
});

it('returns different ids on each call', () => {
const traceId1 = randomTraceId();
const traceId2 = randomTraceId();

assert.notDeepStrictEqual(traceId1, traceId2);
});
});

describe('randomSpanId', () => {
let spanId1: string, spanId2: string;
beforeEach(() => {
spanId1 = idGenerator.generateSpanId();
spanId2 = idGenerator.generateSpanId();
});

it('returns 16 character hex strings', () => {
const spanId = randomSpanId();
assert.ok(spanId.match(/[a-f0-9]{16}/));
assert.ok(!spanId.match(/^0+$/));
assert.ok(spanId1.match(/[a-f0-9]{16}/));
assert.ok(!spanId1.match(/^0+$/));
});

it('returns different ids on each call', () => {
const spanId1 = randomSpanId();
const spanId2 = randomSpanId();

assert.notDeepStrictEqual(spanId1, spanId2);
});
});
10 changes: 6 additions & 4 deletions packages/opentelemetry-tracing/src/Tracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import {
InstrumentationLibrary,
isValid,
NoRecordingSpan,
randomSpanId,
randomTraceId,
IdGenerator,
RandomIdGenerator,
setActiveSpan,
} from '@opentelemetry/core';
import { Resource } from '@opentelemetry/resources';
Expand All @@ -38,6 +38,7 @@ import { mergeConfig } from './utility';
export class Tracer implements api.Tracer {
private readonly _sampler: api.Sampler;
private readonly _traceParams: TraceParams;
private readonly _idGenerator: IdGenerator;
readonly resource: Resource;
readonly instrumentationLibrary: InstrumentationLibrary;
readonly logger: api.Logger;
Expand All @@ -53,6 +54,7 @@ export class Tracer implements api.Tracer {
const localConfig = mergeConfig(config);
this._sampler = localConfig.sampler;
this._traceParams = localConfig.traceParams;
this._idGenerator = config.idGenerator || new RandomIdGenerator();
this.resource = _tracerProvider.resource;
this.instrumentationLibrary = instrumentationLibrary;
this.logger = config.logger || new ConsoleLogger(config.logLevel);
Expand All @@ -68,12 +70,12 @@ export class Tracer implements api.Tracer {
context = api.context.active()
): api.Span {
const parentContext = getParent(options, context);
const spanId = randomSpanId();
const spanId = this._idGenerator.generateSpanId();
let traceId;
let traceState;
if (!parentContext || !isValid(parentContext)) {
// New root span.
traceId = randomTraceId();
traceId = this._idGenerator.generateTraceId();
} else {
// New child span.
traceId = parentContext.traceId;
Expand Down
9 changes: 8 additions & 1 deletion packages/opentelemetry-tracing/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
*/

import { HttpTextPropagator, Logger, Sampler } from '@opentelemetry/api';
import { LogLevel } from '@opentelemetry/core';
import { LogLevel, IdGenerator } from '@opentelemetry/core';

import { ContextManager } from '@opentelemetry/context-base';
import { Resource } from '@opentelemetry/resources';

Expand Down Expand Up @@ -44,6 +45,12 @@ export interface TracerConfig {

/** Bool for whether or not graceful shutdown is enabled */
gracefulShutdown?: boolean;

/**
* Generator of trace and span IDs
* The default idGenerator generates random ids
*/
idGenerator?: IdGenerator;
}

/**
Expand Down

0 comments on commit 802c5ad

Please sign in to comment.