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

Commit

Permalink
Add support for gRPC tags propagation (#443)
Browse files Browse the repository at this point in the history
* Tags: gRPC propagation

* return null within the catch block
  • Loading branch information
mayurkale22 committed Mar 27, 2019
1 parent b5a49c1 commit c5a7d07
Show file tree
Hide file tree
Showing 12 changed files with 311 additions and 74 deletions.
23 changes: 12 additions & 11 deletions examples/tags/tag-context-example.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,40 @@
* limitations under the License.
*/

const core = require('@opencensus/core');
const {globalStats, MeasureUnit, TagMap} = require('@opencensus/core');

const K1 = { name: 'k1' };
const K2 = { name: 'k2' };
const V1 = { value: 'v1' };
const V2 = { value: 'v2' };

const mLatencyMs = core.globalStats.createMeasureDouble(
'm1', core.MeasureUnit.MS, '1st test metric'
const mLatencyMs = globalStats.createMeasureDouble(
'm1', MeasureUnit.MS, '1st test metric'
);

/** Main method. */
function main () {
const tags1 = new core.TagMap();
const tags1 = new TagMap();
tags1.set(K1, V1);

core.withTagContext(tags1, () => {
globalStats.withTagContext(tags1, () => {
console.log('Enter Scope 1');
printMap('Add Tags', tags1.tags);
printMap('Current Tags == Default + tags1:', core.getCurrentTagContext().tags);
printMap('Current Tags == Default + tags1:',
globalStats.getCurrentTagContext().tags);

const tags2 = new core.TagMap();
const tags2 = new TagMap();
tags2.set(K2, V2);
core.withTagContext(tags2, () => {
globalStats.withTagContext(tags2, () => {
console.log('Enter Scope 2');
printMap('Add Tags', tags2.tags);
printMap('Current Tags == Default + tags1 + tags2:', core.getCurrentTagContext().tags);
printMap('Current Tags == Default + tags1 + tags2:', globalStats.getCurrentTagContext().tags);

const measurement = { measure: mLatencyMs, value: 10 };
core.globalStats.record([measurement]);
globalStats.record([measurement]);
console.log('Close Scope 2');
});
printMap('Current Tags == Default + tags1:', core.getCurrentTagContext().tags);
printMap('Current Tags == Default + tags1:', globalStats.getCurrentTagContext().tags);
console.log('Close Scope 1');
});
}
Expand Down
1 change: 1 addition & 0 deletions packages/opencensus-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export * from './stats/bucket-boundaries';
export * from './stats/metric-utils';
export * from './tags/tag-map';
export * from './tags/tagger';
export * from './tags/propagation/binary-serializer';
export * from './tags/propagation/text-format';
export * from './resource/resource';

Expand Down
3 changes: 3 additions & 0 deletions packages/opencensus-core/src/internal/cls-ah.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class AsyncHooksNamespace implements CLSNamespace {
runAndReturn<T>(fn: Func<T>): T {
const oldContext = current;
current = {};
if (oldContext['current_tag_map']) {
current['current_tag_map'] = oldContext['current_tag_map'];
}
const res = fn();
current = oldContext;
return res;
Expand Down
2 changes: 2 additions & 0 deletions packages/opencensus-core/src/internal/cls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,5 @@ export function destroyNamespace(): void {
export function getNamespace(): CLS.Namespace {
return cls.getNamespace(TRACE_NAMESPACE);
}

export const contextManager = createNamespace();
25 changes: 23 additions & 2 deletions packages/opencensus-core/src/stats/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
import * as defaultLogger from '../common/console-logger';
import * as loggerTypes from '../common/types';
import {StatsEventListener} from '../exporters/types';
import * as cls from '../internal/cls';
import {Metric} from '../metrics/export/types';
import {Metrics} from '../metrics/metrics';
import {TagMap} from '../tags/tag-map';
import {getCurrentTagContext} from '../tags/tagger';
import * as tagger from '../tags/tagger';
import {TagKey} from '../tags/types';

import {MetricProducerForStats} from './metric-producer';
import {AggregationType, Measure, Measurement, MeasureType, MeasureUnit, Stats, View} from './types';
import {BaseView} from './view';
Expand All @@ -35,13 +37,16 @@ export class BaseStats implements Stats {
private logger: loggerTypes.Logger;
/** Singleton instance */
private static singletonInstance: BaseStats;
/** Manage context automatic propagation */
private contextManager: cls.Namespace;

/**
* Creates stats
* @param logger
*/
constructor(logger = defaultLogger) {
this.logger = logger.logger();
this.contextManager = cls.getNamespace();

// Create a new MetricProducerForStats and register it to
// MetricProducerManager when Stats is initialized.
Expand Down Expand Up @@ -189,7 +194,7 @@ export class BaseStats implements Stats {

if (!tags) {
// Record against implicit (current) context
tags = getCurrentTagContext();
tags = this.getCurrentTagContext();
}

for (const measurement of measurements) {
Expand All @@ -216,4 +221,20 @@ export class BaseStats implements Stats {
this.registeredViews = {};
this.statsEventListeners = [];
}

/**
* Enters the scope of code where the given `TagMap` is in the current context
* (replacing the previous `TagMap`).
* @param tags The TagMap to be set to the current context.
* @param fn Callback function.
* @returns The callback return.
*/
withTagContext<T>(tags: TagMap, fn: cls.Func<T>): T {
return tagger.withTagContext<T>(this.contextManager, tags, fn);
}

/** Gets the current tag context. */
getCurrentTagContext(): TagMap {
return tagger.getCurrentTagContext(this.contextManager);
}
}
13 changes: 13 additions & 0 deletions packages/opencensus-core/src/stats/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import {StatsEventListener} from '../exporters/types';
import * as cls from '../internal/cls';
import {Metric} from '../metrics/export/types';
import {TagMap} from '../tags/tag-map';
import {TagKey, TagValue} from '../tags/types';
Expand Down Expand Up @@ -98,6 +99,18 @@ export interface Stats {
* @param exporter An stats exporter
*/
unregisterExporter(exporter: StatsEventListener): void;

/**
* Enters the scope of code where the given `TagMap` is in the current context
* (replacing the previous `TagMap`).
* @param tags The TagMap to be set to the current context.
* @param fn Callback function.
* @returns The callback return.
*/
withTagContext<T>(tags: TagMap, fn: cls.Func<T>): T;

/** Gets the current tag context. */
getCurrentTagContext(): TagMap;
}

/**
Expand Down
32 changes: 21 additions & 11 deletions packages/opencensus-core/src/tags/tagger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,25 @@
import * as cls from '../internal/cls';
import {TagMap} from './tag-map';

const contextManager = cls.createNamespace();
export const EMPTY_TAG_MAP = new TagMap();
const CURRENT_TAG_MAP_KEY = 'current_tag_map';

/** Gets the current tag context. */
export function getCurrentTagContext(): TagMap {
export function getCurrentTagContext(contextManager: cls.Namespace): TagMap {
const tagsFromContext = contextManager.get(CURRENT_TAG_MAP_KEY);
if (tagsFromContext) {
return tagsFromContext as TagMap;
return makeDeepCopy(tagsFromContext as TagMap);
}
return EMPTY_TAG_MAP;
return new TagMap();
}

/**
* Sets the current tag context.
* @param tags The TagMap.
*/
export function setCurrentTagContext(tags: TagMap) {
contextManager.set(CURRENT_TAG_MAP_KEY, tags);
export function setCurrentTagContext(
contextManager: cls.Namespace, tags: TagMap) {
contextManager.set(CURRENT_TAG_MAP_KEY, makeDeepCopy(tags));
}

/**
Expand All @@ -45,8 +45,9 @@ export function setCurrentTagContext(tags: TagMap) {
* @param fn Callback function.
* @returns The callback return.
*/
export function withTagContext<T>(tags: TagMap, fn: cls.Func<T>): T {
const oldContext = getCurrentTagContext();
export function withTagContext<T>(
contextManager: cls.Namespace, tags: TagMap, fn: cls.Func<T>): T {
const oldContext = getCurrentTagContext(contextManager);
return contextManager.runAndReturn(() => {
const newContext = new TagMap();
for (const [tagKey, tagValue] of oldContext.tags) {
Expand All @@ -55,12 +56,21 @@ export function withTagContext<T>(tags: TagMap, fn: cls.Func<T>): T {
for (const [tagKey, tagValue] of tags.tags) {
newContext.set(tagKey, tagValue);
}
setCurrentTagContext(newContext);
setCurrentTagContext(contextManager, newContext);
return fn();
});
}

/** Clear the current tag context. */
export function clear() {
contextManager.set(CURRENT_TAG_MAP_KEY, EMPTY_TAG_MAP);
export function clear(contextManager: cls.Namespace) {
contextManager.set(CURRENT_TAG_MAP_KEY, new TagMap());
}

function makeDeepCopy(tags: TagMap) {
const tagsCopy = new TagMap();
for (const [tagKey, valueWithMetadata] of tags.tagsWithMetadata) {
tagsCopy.set(
tagKey, valueWithMetadata.tagValue, valueWithMetadata.tagMetadata);
}
return tagsCopy;
}
2 changes: 1 addition & 1 deletion packages/opencensus-core/src/trace/model/tracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class CoreTracer implements types.Tracer {
/** Constructs a new TraceImpl instance. */
constructor() {
this.activeLocal = false;
this.contextManager = cls.createNamespace();
this.contextManager = cls.getNamespace();
this.clearCurrentTrace();
this.activeTraceParams = {};
}
Expand Down
4 changes: 2 additions & 2 deletions packages/opencensus-core/test/test-stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ describe('Stats', () => {
tags.set(tagKeys[0], {value: 'value1'});
tags.set(tagKeys[1], {value: 'value2'});
const measurement = {measure, value: 1};
tagger.withTagContext(tags, () => {
globalStats.withTagContext(tags, () => {
globalStats.record([measurement]);
});

Expand All @@ -250,7 +250,7 @@ describe('Stats', () => {
const UNKNOWN_TAG_VALUE: TagValue = null;
globalStats.registerExporter(testExporter);
const measurement = {measure, value: 2211};
tagger.withTagContext(tagger.EMPTY_TAG_MAP, () => {
globalStats.withTagContext(tagger.EMPTY_TAG_MAP, () => {
globalStats.record([measurement]);
});

Expand Down
62 changes: 38 additions & 24 deletions packages/opencensus-core/test/test-tagger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@

import * as assert from 'assert';
import {TagMap} from '../src';
import * as cls from '../src/internal/cls';
import * as tagger from '../src/tags/tagger';

const contextManager = cls.getNamespace();

describe('tagger()', () => {
const tags1 = new TagMap();
tags1.set({name: 'key1'}, {value: 'value1'});
Expand Down Expand Up @@ -54,57 +57,68 @@ describe('tagger()', () => {
expectedTagsFrom1n3n4.set({name: 'key6'}, {value: 'value6'});

it('should return empty current tag context', () => {
tagger.withTagContext(tagger.EMPTY_TAG_MAP, () => {
tagger.withTagContext(contextManager, tagger.EMPTY_TAG_MAP, () => {
assert.deepStrictEqual(
tagger.getCurrentTagContext(), tagger.EMPTY_TAG_MAP);
tagger.getCurrentTagContext(contextManager), tagger.EMPTY_TAG_MAP);
});
});

it('should set current tag context', () => {
tagger.withTagContext(tags1, () => {
assert.deepStrictEqual(tagger.getCurrentTagContext(), tags1);
tagger.withTagContext(contextManager, tags1, () => {
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tags1);
});
assert.deepStrictEqual(tagger.getCurrentTagContext(), tagger.EMPTY_TAG_MAP);
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tagger.EMPTY_TAG_MAP);
});

it('should set nested current tag context', () => {
tagger.withTagContext(tags1, () => {
assert.deepStrictEqual(tagger.getCurrentTagContext(), tags1);
tagger.withTagContext(contextManager, tags1, () => {
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tags1);

tagger.withTagContext(tags2, () => {
tagger.withTagContext(contextManager, tags2, () => {
assert.deepStrictEqual(
tagger.getCurrentTagContext(), expectedMergedTags);
tagger.getCurrentTagContext(contextManager), expectedMergedTags);
});
assert.deepStrictEqual(tagger.getCurrentTagContext(), tags1);
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tags1);
});
assert.deepStrictEqual(tagger.getCurrentTagContext(), tagger.EMPTY_TAG_MAP);
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tagger.EMPTY_TAG_MAP);
});

it('should resolve tag conflicts', () => {
tagger.withTagContext(tags1, () => {
assert.deepStrictEqual(tagger.getCurrentTagContext(), tags1);
tagger.withTagContext(contextManager, tags1, () => {
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tags1);

tagger.withTagContext(tags3, () => {
tagger.withTagContext(contextManager, tags3, () => {
assert.deepStrictEqual(
tagger.getCurrentTagContext(), expectedTagsFrom1n3);
tagger.getCurrentTagContext(contextManager), expectedTagsFrom1n3);

tagger.withTagContext(tags4, () => {
tagger.withTagContext(contextManager, tags4, () => {
assert.deepStrictEqual(
tagger.getCurrentTagContext(), expectedTagsFrom1n3n4);
tagger.getCurrentTagContext(contextManager),
expectedTagsFrom1n3n4);
});
});
assert.deepStrictEqual(tagger.getCurrentTagContext(), tags1);
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tags1);
});
assert.deepStrictEqual(tagger.getCurrentTagContext(), tagger.EMPTY_TAG_MAP);
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tagger.EMPTY_TAG_MAP);
});

it('should clear current tag context', () => {
tagger.withTagContext(tags1, () => {
assert.deepStrictEqual(tagger.getCurrentTagContext(), tags1);
tagger.clear();
tagger.withTagContext(contextManager, tags1, () => {
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tags1);
tagger.clear(contextManager);
assert.deepStrictEqual(
tagger.getCurrentTagContext(), tagger.EMPTY_TAG_MAP);
tagger.getCurrentTagContext(contextManager), tagger.EMPTY_TAG_MAP);
});
assert.deepStrictEqual(tagger.getCurrentTagContext(), tagger.EMPTY_TAG_MAP);
assert.deepStrictEqual(
tagger.getCurrentTagContext(contextManager), tagger.EMPTY_TAG_MAP);
});
});
Loading

0 comments on commit c5a7d07

Please sign in to comment.