Skip to content

Commit

Permalink
feat: add keys operation to getter (#1576)
Browse files Browse the repository at this point in the history
* feat: add keys operation to getter

* chore: lint

* chore: rename getter/setter to TextMapGetter/Setter

* chore: lint

* chore: use setter in fetch plugin

* chore: lint

* chore: remove logs
  • Loading branch information
dyladan authored Oct 19, 2020
1 parent 3f72613 commit 956604e
Show file tree
Hide file tree
Showing 25 changed files with 317 additions and 271 deletions.
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

import {
Context,
GetterFunction,
TextMapPropagator,
SetterFunction,
TraceFlags,
getParentSpanContext,
isSpanContextValid,
isValidSpanId,
isValidTraceId,
isSpanContextValid,
getParentSpanContext,
setExtractedSpanContext,
TextMapGetter,
TextMapPropagator,
TextMapSetter,
TraceFlags,
} from '@opentelemetry/api';
import { B3_DEBUG_FLAG_KEY } from './b3-common';

Expand All @@ -46,38 +46,35 @@ export 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;
}
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 @@ -96,21 +93,21 @@ function getTraceFlags(
* Based on: https://github.com/openzipkin/b3-propagation
*/
export class B3MultiPropagator implements TextMapPropagator {
inject(context: Context, carrier: unknown, setter: SetterFunction) {
inject(context: Context, carrier: unknown, setter: TextMapSetter) {
const spanContext = getParentSpanContext(context);
if (!spanContext || !isSpanContextValid(spanContext)) return;

const debug = context.getValue(B3_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);
// 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 @@ -120,7 +117,7 @@ export class B3MultiPropagator 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 traceFlags = getTraceFlags(carrier, getter) as TraceFlags;
Expand Down
Loading

0 comments on commit 956604e

Please sign in to comment.