Skip to content
This repository has been archived by the owner on Oct 3, 2023. It is now read-only.

Commit

Permalink
Fix traceid validator (#879)
Browse files Browse the repository at this point in the history
* Fix comments in jaeger propagation validator

* Add support for 64Bit and 128Bit traceIds
Fix inject validators
Fix extract formatter for leading zero bugs
  • Loading branch information
philicious authored May 18, 2021
1 parent 8864dcf commit 2ee9c92
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 10 deletions.
11 changes: 8 additions & 3 deletions packages/opencensus-propagation-jaeger/src/jaeger-format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ import {
} from '@opencensus/core';
import * as crypto from 'crypto';
import * as uuid from 'uuid';
import { isValidSpanId, isValidTraceId } from './validators';
import {
formatTraceId,
formatSpanId,
isValidSpanId,
isValidTraceId,
} from './validators';

// TRACER_STATE_HEADER_NAME is the header key used for a span's serialized
// context.
Expand Down Expand Up @@ -57,8 +62,8 @@ export class JaegerFormat implements Propagation {
const tracerStateHeaderParts = tracerStateHeader.split(':');
if (tracerStateHeaderParts.length !== 4) return null;

const traceId = tracerStateHeaderParts[0];
const spanId = tracerStateHeaderParts[1];
const traceId = formatTraceId(tracerStateHeaderParts[0]);
const spanId = formatSpanId(tracerStateHeaderParts[1]);
const jflags = Number(
'0x' +
(isNaN(Number(tracerStateHeaderParts[3]))
Expand Down
37 changes: 30 additions & 7 deletions packages/opencensus-propagation-jaeger/src/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,25 @@ const compose = (...fns: ValidationFn[]): ValidationFn => {
};

/**
* Determines if the given traceId is valid based on section 2.2.2.1 of the
* Trace Context spec.
* Compose a set of validation functions into a single validation call.
*/
const orCompose = (...fns: ValidationFn[]): ValidationFn => {
return (value: string) => {
return fns.reduce((isValid, fn) => isValid || fn(value), false);
};
};

/**
* Determines if the given traceId is valid based on https://www.jaegertracing.io/docs/1.21/client-libraries/#value
*/
export const isValidTraceId = compose(
isHex,
isNotAllZeros,
isLength(32)
orCompose(isLength(32), isLength(16))
);

/**
* Determines if the given spanId is valid based on section 2.2.2.2 of the Trace
* Context spec.
* Determines if the given spanId is valid based on https://www.jaegertracing.io/docs/1.21/client-libraries/#value
*/
export const isValidSpanId = compose(
isHex,
Expand All @@ -74,10 +81,26 @@ export const isValidSpanId = compose(
);

/**
* Determines if the given option is valid based on section 2.2.3 of the Trace
* Context spec.
* Determines if the given option is valid based on https://www.jaegertracing.io/docs/1.21/client-libraries/#value
*/
export const isValidOption = compose(
isHex,
isLength(2)
);

/**
* Formats a traceId to 64Bit or 128Bit Hex and add leading zeroes
*/
export const formatTraceId = (id: string) => {
if (id.length > 16) {
return ('0000000000000000000000000000000' + id).substr(-32);
}
return ('000000000000000' + id).substr(-16);
};

/**
* Formats a spanId to 64Bit and add leading zeroes
*/
export const formatSpanId = (id: string) => {
return ('000000000000000' + id).substr(-16);
};
104 changes: 104 additions & 0 deletions packages/opencensus-propagation-jaeger/test/test-jaeger-format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,66 @@ describe('JaegerPropagation', () => {
);
assert.deepStrictEqual(jaegerFormat.extract(getter), spanContext);
});

it('should format traceId for 64Bit Hex id without leading zeros', () => {
const spanContext = jaegerFormat.generate();
spanContext.traceId = '70c2f20bd65603bd';
const getter = helperGetter(
`${spanContext.traceId}:${spanContext.spanId}::${spanContext.options}`
);
assert.deepStrictEqual(jaegerFormat.extract(getter), spanContext);
});

it('should format traceId for 64Bit Hex id with leading zeros when needed', () => {
const spanContext = jaegerFormat.generate();
spanContext.traceId = 'c2f20bd65603bd';
const compareSpanContext = { ...spanContext };
compareSpanContext.traceId = '00c2f20bd65603bd';
const getter = helperGetter(
`${spanContext.traceId}:${spanContext.spanId}::${spanContext.options}`
);
assert.deepStrictEqual(jaegerFormat.extract(getter), compareSpanContext);
});

it('should format traceId for 128Bit Hex id without leading zeros', () => {
const spanContext = jaegerFormat.generate();
spanContext.traceId = '929985345ae64c35acddd590f13ffc82';
const getter = helperGetter(
`${spanContext.traceId}:${spanContext.spanId}::${spanContext.options}`
);
assert.deepStrictEqual(jaegerFormat.extract(getter), spanContext);
});

it('should format traceId for 128Bit Hex id with leading zeros when needed', () => {
const spanContext = jaegerFormat.generate();
spanContext.traceId = '9985345ae64c35acddd590f13ffc82';
const compareSpanContext = { ...spanContext };
compareSpanContext.traceId = '009985345ae64c35acddd590f13ffc82';
const getter = helperGetter(
`${spanContext.traceId}:${spanContext.spanId}::${spanContext.options}`
);
assert.deepStrictEqual(jaegerFormat.extract(getter), compareSpanContext);
});
});

it('should format spanId without leading zeros', () => {
const spanContext = jaegerFormat.generate();
spanContext.spanId = '70c2f20bd65603bd';
const getter = helperGetter(
`${spanContext.traceId}:${spanContext.spanId}::${spanContext.options}`
);
assert.deepStrictEqual(jaegerFormat.extract(getter), spanContext);
});

it('should format spanId with leading zeros when needed', () => {
const spanContext = jaegerFormat.generate();
spanContext.spanId = 'c2f20bd65603bd';
const compareSpanContext = { ...spanContext };
compareSpanContext.spanId = '00c2f20bd65603bd';
const getter = helperGetter(
`${spanContext.traceId}:${spanContext.spanId}::${spanContext.options}`
);
assert.deepStrictEqual(jaegerFormat.extract(getter), compareSpanContext);
});

describe('inject', () => {
Expand Down Expand Up @@ -104,6 +164,50 @@ describe('JaegerPropagation', () => {
jaegerFormat.inject(setter, emptySpanContext);
assert.deepStrictEqual(jaegerFormat.extract(getter), null);
});

it('should inject spancontext with 64Bit traceID', () => {
const spanContext = {
traceId: '70c2f20bd65603bd',
spanId: '5ba4ceca5d0edd4c',
options: SAMPLED_VALUE,
};
const headers: { [key: string]: string | string[] | undefined } = {};
const setter: HeaderSetter = {
setHeader(name: string, value: string) {
headers[name] = value;
},
};
const getter: HeaderGetter = {
getHeader(name: string) {
return headers[name];
},
};

jaegerFormat.inject(setter, spanContext);
assert.deepStrictEqual(jaegerFormat.extract(getter), spanContext);
});

it('should inject spancontext with 128Bit traceID', () => {
const spanContext = {
traceId: '929985345ae64c35acddd590f13ffc82',
spanId: '5ba4ceca5d0edd4c',
options: SAMPLED_VALUE,
};
const headers: { [key: string]: string | string[] | undefined } = {};
const setter: HeaderSetter = {
setHeader(name: string, value: string) {
headers[name] = value;
},
};
const getter: HeaderGetter = {
getHeader(name: string) {
return headers[name];
},
};

jaegerFormat.inject(setter, spanContext);
assert.deepStrictEqual(jaegerFormat.extract(getter), spanContext);
});
});

// Same test as propagation-stackdriver.
Expand Down

0 comments on commit 2ee9c92

Please sign in to comment.