Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add keys operation to getter #1576

Merged
merged 11 commits into from
Oct 19, 2020
4 changes: 2 additions & 2 deletions benchmark/propagator.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ for (const setup of setups) {
api.setExtractedSpanContext(Context.ROOT_CONTEXT, {
traceId: 'd4cda95b652f4a1592b449d5929fda1b',
spanId: '6e0c63257de34c92'
}), setup.injectCarrier, api.defaultSetter);
}), setup.injectCarrier, api.defaultTextMapSetter);
})
.add('#Extract', function () {
propagator.extract(Context.ROOT_CONTEXT, setup.extractCarrier, api.defaultGetter);
propagator.extract(Context.ROOT_CONTEXT, setup.extractCarrier, api.defaultTextMapGetter);
});

// run async
Expand Down
2 changes: 1 addition & 1 deletion packages/opentelemetry-api/src/api/global-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,4 @@ export function makeGetter<T>(
* version. If the global API is not compatible with the API package
* attempting to get it, a NOOP API implementation will be returned.
*/
export const API_BACKWARDS_COMPATIBILITY_VERSION = 0;
export const API_BACKWARDS_COMPATIBILITY_VERSION = 1;
14 changes: 9 additions & 5 deletions packages/opentelemetry-api/src/api/propagation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
*/

import { Context } from '@opentelemetry/context-base';
import { defaultGetter, GetterFunction } from '../context/propagation/getter';
import { TextMapPropagator } from '../context/propagation/TextMapPropagator';
import { NOOP_TEXT_MAP_PROPAGATOR } from '../context/propagation/NoopTextMapPropagator';
import { defaultSetter, SetterFunction } from '../context/propagation/setter';
import {
defaultTextMapGetter,
defaultTextMapSetter,
TextMapGetter,
TextMapPropagator,
TextMapSetter,
} from '../context/propagation/TextMapPropagator';
import { ContextAPI } from './context';
import {
API_BACKWARDS_COMPATIBILITY_VERSION,
Expand Down Expand Up @@ -74,7 +78,7 @@ export class PropagationAPI {
*/
public inject<Carrier>(
carrier: Carrier,
setter: SetterFunction<Carrier> = defaultSetter,
setter: TextMapSetter<Carrier> = defaultTextMapSetter,
context: Context = contextApi.active()
): void {
return this._getGlobalPropagator().inject(context, carrier, setter);
Expand All @@ -89,7 +93,7 @@ export class PropagationAPI {
*/
public extract<Carrier>(
carrier: Carrier,
getter: GetterFunction<Carrier> = defaultGetter,
getter: TextMapGetter<Carrier> = defaultTextMapGetter,
context: Context = contextApi.active()
): Context {
return this._getGlobalPropagator().extract(context, carrier, getter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import { TextMapPropagator } from './TextMapPropagator';
*/
export class NoopTextMapPropagator implements TextMapPropagator {
/** Noop inject function does nothing */
inject(context: Context, carrier: unknown, setter: Function): void {}
inject(context: Context, carrier: unknown): void {}
/** Noop extract function does nothing and returns the input context */
extract(context: Context, carrier: unknown, getter: Function): Context {
extract(context: Context, carrier: unknown): Context {
return context;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
*/

import { Context } from '@opentelemetry/context-base';
import { SetterFunction } from './setter';
import { GetterFunction } from './getter';

/**
* Injects `Context` into and extracts it from carriers that travel
Expand All @@ -29,7 +27,7 @@ import { GetterFunction } from './getter';
* usually implemented via library-specific request interceptors, where the
* client-side injects values and the server-side extracts them.
*/
export interface TextMapPropagator {
export interface TextMapPropagator<Carrier = any> {
/**
* Injects values from a given `Context` into a carrier.
*
Expand All @@ -40,10 +38,14 @@ export interface TextMapPropagator {
* the wire.
* @param carrier the carrier of propagation fields, such as http request
* headers.
* @param setter a function which accepts a carrier, key, and value, which
* sets the key on the carrier to the value.
* @param setter an optional {@link TextMapSetter}. If undefined, values will be
* set by direct object assignment.
*/
inject(context: Context, carrier: unknown, setter: SetterFunction): void;
inject(
context: Context,
carrier: Carrier,
setter: TextMapSetter<Carrier>
): void;

/**
* Given a `Context` and a carrier, extract context values from a
Expand All @@ -54,8 +56,77 @@ export interface TextMapPropagator {
* the wire.
* @param carrier the carrier of propagation fields, such as http request
* headers.
* @param getter a function which accepts a carrier and a key, and returns
* the value from the carrier identified by the key.
* @param getter an optional {@link TextMapGetter}. If undefined, keys will be all
* own properties, and keys will be accessed by direct object access.
*/
extract(context: Context, carrier: unknown, getter: GetterFunction): Context;
extract(
context: Context,
carrier: Carrier,
getter: TextMapGetter<Carrier>
): Context;
}

/**
* A setter is specified by the caller to define a specific method
* to set key/value pairs on the carrier within a propagator.
*/
export interface TextMapSetter<Carrier = any> {
/**
* Callback used to set a key/value pair on an object.
*
* Should be called by the propagator each time a key/value pair
* should be set, and should set that key/value pair on the propagator.
*
* @param carrier object or class which carries key/value pairs
* @param key string key to modify
* @param value value to be set to the key on the carrier
*/
set(carrier: Carrier, key: string, value: string): void;
}

/**
* A getter is specified by the caller to define a specific method
* to get the value of a key from a carrier.
*/
export interface TextMapGetter<Carrier = any> {
/**
* Get a list of all keys available on the carrier.
*
* @param carrier
*/
keys(carrier: Carrier): string[];

/**
* Get the value of a specific key from the carrier.
*
* @param carrier
* @param key
*/
get(carrier: Carrier, key: string): undefined | string | string[];
}

export const defaultTextMapGetter: TextMapGetter = {
get(carrier, key) {
if (carrier == null) {
return undefined;
}
return carrier[key];
},

keys(carrier) {
if (carrier == null) {
return [];
}
return Object.keys(carrier);
},
};

export const defaultTextMapSetter: TextMapSetter = {
set(carrier, key, value) {
if (carrier == null) {
return;
}

carrier[key] = value;
},
};
31 changes: 0 additions & 31 deletions packages/opentelemetry-api/src/context/propagation/getter.ts

This file was deleted.

31 changes: 0 additions & 31 deletions packages/opentelemetry-api/src/context/propagation/setter.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/opentelemetry-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ export * from './common/Exception';
export * from './common/Logger';
export * from './common/Time';
export * from './context/context';
export * from './context/propagation/getter';
export * from './context/propagation/TextMapPropagator';
export * from './context/propagation/NoopTextMapPropagator';
export * from './context/propagation/setter';
export * from './correlation_context/CorrelationContext';
export * from './correlation_context/EntryValue';
export * from './metrics/BatchObserverResult';
Expand Down
35 changes: 16 additions & 19 deletions packages/opentelemetry-core/src/context/propagation/B3Propagator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

import {
Context,
GetterFunction,
TextMapGetter,
TextMapPropagator,
SetterFunction,
TextMapSetter,
TraceFlags,
getParentSpanContext,
setExtractedSpanContext,
Expand Down Expand Up @@ -63,20 +63,20 @@ function parseHeader(header: unknown) {
return Array.isArray(header) ? header[0] : header;
}

function getHeaderValue(carrier: unknown, getter: GetterFunction, key: string) {
const header = getter(carrier, key);
function getHeaderValue(carrier: unknown, getter: TextMapGetter, key: string) {
const header = getter.get(carrier, key);
return parseHeader(header);
}

function getTraceId(carrier: unknown, getter: GetterFunction): string {
function getTraceId(carrier: unknown, getter: TextMapGetter): string {
const traceId = getHeaderValue(carrier, getter, X_B3_TRACE_ID);
if (typeof traceId === 'string') {
return traceId.padStart(32, '0');
}
return '';
}

function getSpanId(carrier: unknown, getter: GetterFunction): string {
function getSpanId(carrier: unknown, getter: TextMapGetter): string {
const spanId = getHeaderValue(carrier, getter, X_B3_SPAN_ID);
if (typeof spanId === 'string') {
return spanId;
Expand All @@ -86,7 +86,7 @@ function getSpanId(carrier: unknown, getter: GetterFunction): string {

function getParentSpanId(
carrier: unknown,
getter: GetterFunction
getter: TextMapGetter
): string | undefined {
const spanId = getHeaderValue(carrier, getter, X_B3_PARENT_SPAN_ID);
if (typeof spanId === 'string') {
Expand All @@ -95,17 +95,14 @@ function getParentSpanId(
return;
}

function getDebug(
carrier: unknown,
getter: GetterFunction
): string | undefined {
function getDebug(carrier: unknown, getter: TextMapGetter): string | undefined {
const debug = getHeaderValue(carrier, getter, X_B3_FLAGS);
return debug === '1' ? '1' : undefined;
}

function getTraceFlags(
carrier: unknown,
getter: GetterFunction
getter: TextMapGetter
): TraceFlags | undefined {
const traceFlags = getHeaderValue(carrier, getter, X_B3_SAMPLED);
const debug = getDebug(carrier, getter);
Expand All @@ -124,7 +121,7 @@ function getTraceFlags(
* Based on: https://github.com/openzipkin/b3-propagation
*/
export class B3Propagator implements TextMapPropagator {
inject(context: Context, carrier: unknown, setter: SetterFunction) {
inject(context: Context, carrier: unknown, setter: TextMapSetter) {
const spanContext = getParentSpanContext(context);
if (!spanContext) return;
const parentSpanId = context.getValue(PARENT_SPAN_ID_KEY) as
Expand All @@ -136,19 +133,19 @@ export class B3Propagator implements TextMapPropagator {
isValidParentSpanID(parentSpanId)
) {
const debug = context.getValue(DEBUG_FLAG_KEY);
setter(carrier, X_B3_TRACE_ID, spanContext.traceId);
setter(carrier, X_B3_SPAN_ID, spanContext.spanId);
setter.set(carrier, X_B3_TRACE_ID, spanContext.traceId);
setter.set(carrier, X_B3_SPAN_ID, spanContext.spanId);
if (parentSpanId) {
setter(carrier, X_B3_PARENT_SPAN_ID, parentSpanId);
setter.set(carrier, X_B3_PARENT_SPAN_ID, parentSpanId);
}
// According to the B3 spec, if the debug flag is set,
// the sampled flag shouldn't be propagated as well.
if (debug === '1') {
setter(carrier, X_B3_FLAGS, debug);
setter.set(carrier, X_B3_FLAGS, debug);
} else if (spanContext.traceFlags !== undefined) {
// We set the header only if there is an existing sampling decision.
// Otherwise we will omit it => Absent.
setter(
setter.set(
carrier,
X_B3_SAMPLED,
(TraceFlags.SAMPLED & spanContext.traceFlags) === TraceFlags.SAMPLED
Expand All @@ -159,7 +156,7 @@ export class B3Propagator implements TextMapPropagator {
}
}

extract(context: Context, carrier: unknown, getter: GetterFunction): Context {
extract(context: Context, carrier: unknown, getter: TextMapGetter): Context {
const traceId = getTraceId(carrier, getter);
const spanId = getSpanId(carrier, getter);
const parentSpanId = getParentSpanId(carrier, getter);
Expand Down
Loading