Skip to content

Commit

Permalink
Implement opentelemetry mutable baggage
Browse files Browse the repository at this point in the history
  • Loading branch information
diogotorres97 committed Oct 25, 2023
1 parent a1e8c2a commit 5cf0be3
Show file tree
Hide file tree
Showing 11 changed files with 591 additions and 5 deletions.
55 changes: 54 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"lint-staged"
],
"devDependencies": {
"@opentelemetry/api": "^1.6.0",
"@opentelemetry/core": "^1.17.1",
"@typescript-eslint/eslint-plugin": "^6.9.0",
"@typescript-eslint/parser": "^6.9.0",
"@vitest/coverage-v8": "^0.34.6",
Expand Down
11 changes: 10 additions & 1 deletion packages/opentelemetry-mutable-baggage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,14 @@
"baggage"
],
"author": "Uphold",
"license": "MIT"
"license": "MIT",
"dependencies": {
"@opentelemetry/core": "^1.17.1"
},
"peerDependencies": {
"@opentelemetry/api": ">=1 <2"
},
"devDependencies": {
"@opentelemetry/context-async-hooks": "^1.17.1"
}
}
55 changes: 55 additions & 0 deletions packages/opentelemetry-mutable-baggage/src/context-helpers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import { MutableBaggageImpl } from './mutable-baggage-impl';
import { ROOT_CONTEXT, context as contextApi } from '@opentelemetry/api';
import { createMutableBaggage, getMutableBaggage, setMutableBaggage } from './context-helpers';
import { describe, expect, it } from 'vitest';
import { getActiveMutableBaggage } from '.';

describe('getActiveMutableBaggage()', () => {
it('should return undefined if there is no mutable baggage in the active context', () => {
expect(getActiveMutableBaggage()).toBeUndefined();
});

it('should return the mutable baggage on the active context', async () => {
const context = setMutableBaggage(ROOT_CONTEXT, createMutableBaggage(new Map([['key', { value: 'foo' }]])));

contextApi.setGlobalContextManager(new AsyncHooksContextManager());

await contextApi.with(context, () => {
expect(getActiveMutableBaggage()).toBeInstanceOf(MutableBaggageImpl);
expect(getActiveMutableBaggage()?.getAllEntries()).toEqual([['key', { value: 'foo' }]]);
});
});
});

describe('getMutableBaggage()', () => {
it('should return undefined if there is no mutable baggage set on the context', () => {
expect(getMutableBaggage(ROOT_CONTEXT)).toBeUndefined();
});

it('should get the mutable baggage set on the context', () => {
const context = setMutableBaggage(ROOT_CONTEXT, createMutableBaggage(new Map([['key', { value: 'foo' }]])));

expect(getMutableBaggage(context)).toBeInstanceOf(MutableBaggageImpl);
expect(getMutableBaggage(context)?.getAllEntries()).toEqual([['key', { value: 'foo' }]]);
});
});

describe('createMutableBaggage()', () => {
it('should create a mutable baggage', () => {
const baggage = createMutableBaggage(new Map([['key', { value: 'foo' }]]));

expect(baggage).toBeInstanceOf(MutableBaggageImpl);
expect(baggage.getAllEntries()).toEqual([['key', { value: 'foo' }]]);
});
});

describe('setMutableBaggage()', () => {
it('should set a mutable baggage on a new context', () => {
const context = setMutableBaggage(ROOT_CONTEXT, createMutableBaggage(new Map([['key', { value: 'foo' }]])));

expect(context).not.toEqual(ROOT_CONTEXT);
expect(getMutableBaggage(context)).toBeInstanceOf(MutableBaggageImpl);
expect(getMutableBaggage(context)?.getAllEntries()).toEqual([['key', { value: 'foo' }]]);
});
});
16 changes: 16 additions & 0 deletions packages/opentelemetry-mutable-baggage/src/context-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { BaggageEntry, Context, context, createContextKey } from '@opentelemetry/api';
import { MutableBaggageImpl } from './mutable-baggage-impl';

const MUTTABLE_BAGGAGE_KEY = createContextKey('OpenTelemetry Mutable Baggage Key');

export const getActiveMutableBaggage = (): MutableBaggageImpl | undefined =>
(context.active().getValue(MUTTABLE_BAGGAGE_KEY) as MutableBaggageImpl) ?? undefined;

export const getMutableBaggage = (context: Context): MutableBaggageImpl | undefined =>
(context.getValue(MUTTABLE_BAGGAGE_KEY) as MutableBaggageImpl) ?? undefined;

export const createMutableBaggage = (entries: Map<string, BaggageEntry>): MutableBaggageImpl =>
new MutableBaggageImpl(entries);

export const setMutableBaggage = (context: Context, baggage: MutableBaggageImpl): Context =>
context.setValue(MUTTABLE_BAGGAGE_KEY, baggage);
9 changes: 7 additions & 2 deletions packages/opentelemetry-mutable-baggage/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { W3CMutableBaggagePropagator, getActiveMutableBaggage } from '.';
import { expect, it } from 'vitest';

it('adds 1 + 2 to equal 3', () => {
expect(3).toBe(3);
it('should export `W3CMutableBaggagePropagator()`', () => {
expect(W3CMutableBaggagePropagator).toBeDefined();
});

it('should export `getActiveMutableBaggage()`', () => {
expect(getActiveMutableBaggage).toBeDefined();
});
3 changes: 2 additions & 1 deletion packages/opentelemetry-mutable-baggage/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
console.log('ola, sou fofo2');
export { W3CMutableBaggagePropagator } from './w3c-mutable-baggage-propagator';
export { getActiveMutableBaggage } from './context-helpers';
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { MutableBaggageImpl } from './mutable-baggage-impl';
import { describe, expect, it } from 'vitest';

describe('constructor()', () => {
it('should create an instance with no entries', () => {
const mutableBaggageImpl = new MutableBaggageImpl();

expect(mutableBaggageImpl.getAllEntries().length).toEqual(0);
});

it('should create an instance with a set of entries', () => {
const entries = new Map([
['key1', { value: 'd4cda95b652f4a1592b449d5929fda1b' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]
]);
const mutableBaggageImpl = new MutableBaggageImpl(entries);

const allEntries = mutableBaggageImpl.getAllEntries();

expect(allEntries.length).toEqual(2);
expect(allEntries).toEqual([
['key1', { value: 'd4cda95b652f4a1592b449d5929fda1b' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]
]);
});
});

describe('getEntry()', () => {
const entries = new Map([
['key1', { value: 'd4cda95b652f4a1592b449d5929fda1b' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]
]);
const mutableBaggageImpl = new MutableBaggageImpl(entries);

it('should return undefined if the entry does not exist', () => {
expect(mutableBaggageImpl.getEntry('foo')).toBeUndefined();
});

it('should return the correct value if the entry exists', () => {
expect(mutableBaggageImpl.getEntry('key1')).toEqual({ value: 'd4cda95b652f4a1592b449d5929fda1b' });
});
});

describe('getAllEntries()', () => {
it('should return an empty array', () => {
const mutableBaggageImpl = new MutableBaggageImpl();

expect(mutableBaggageImpl.getAllEntries()).toEqual([]);
});

it('should return the entries set on the baggage', () => {
const entries = new Map([
['key1', { value: 'd4cda95b652f4a1592b449d5929fda1b' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]
]);
const mutableBaggageImpl = new MutableBaggageImpl(entries);

expect(mutableBaggageImpl.getAllEntries()).toEqual([
['key1', { value: 'd4cda95b652f4a1592b449d5929fda1b' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]
]);
});
});

describe('setEntry()', () => {
it('should add an entry', () => {
const mutableBaggageImpl = new MutableBaggageImpl();

mutableBaggageImpl.setEntry('foo', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' });

expect(mutableBaggageImpl.getAllEntries()).toEqual([['foo', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]]);
});

it('should update an entry', () => {
const entries = new Map([
['key1', { value: 'd4cda95b652f4a1592b449d5929fda1b' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]
]);
const mutableBaggageImpl = new MutableBaggageImpl(entries);

mutableBaggageImpl.setEntry('key1', { value: 'foo' });

expect(mutableBaggageImpl.getAllEntries()).toEqual([
['key1', { value: 'foo' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]
]);
});
});

describe('removeEntry()', () => {
it('should not remove an entry if does not exist', () => {
const mutableBaggageImpl = new MutableBaggageImpl();

mutableBaggageImpl.removeEntry('foo');

expect(mutableBaggageImpl.getAllEntries()).toEqual([]);
});

it('should remove an entry', () => {
const entries = new Map([
['key1', { value: 'd4cda95b652f4a1592b449d5929fda1b' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]
]);
const mutableBaggageImpl = new MutableBaggageImpl(entries);

mutableBaggageImpl.removeEntry('key1');

expect(mutableBaggageImpl.getAllEntries()).toEqual([['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]]);
});
});

describe('removeEntries()', () => {
it('should not remove entries if they do not exist', () => {
const mutableBaggageImpl = new MutableBaggageImpl();

mutableBaggageImpl.removeEntries('foo', 'biz');

expect(mutableBaggageImpl.getAllEntries()).toEqual([]);
});

it('should remove an entry', () => {
const entries = new Map([
['key1', { value: 'd4cda95b652f4a1592b449d5929fda1b' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }],
['key3', { value: 'biz' }]
]);
const mutableBaggageImpl = new MutableBaggageImpl(entries);

mutableBaggageImpl.removeEntries('key1', 'key2');

expect(mutableBaggageImpl.getAllEntries()).toEqual([['key3', { value: 'biz' }]]);
});
});

describe('clear()', () => {
it('should clear all entries', () => {
const entries = new Map([
['key1', { value: 'd4cda95b652f4a1592b449d5929fda1b' }],
['key2', { value: 'c88815a7-0fa9-4d95-a1f1-cdccce3c5c2a' }]
]);
const mutableBaggageImpl = new MutableBaggageImpl(entries);

expect(mutableBaggageImpl.getAllEntries()).toHaveLength(2);

mutableBaggageImpl.clear();

expect(mutableBaggageImpl.getAllEntries()).toHaveLength(0);
});
});
49 changes: 49 additions & 0 deletions packages/opentelemetry-mutable-baggage/src/mutable-baggage-impl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Baggage, BaggageEntry } from '@opentelemetry/api';

export class MutableBaggageImpl implements Baggage {
private entries: Map<string, BaggageEntry>;

constructor(entries?: Map<string, BaggageEntry>) {
this.entries = entries ? new Map(entries) : new Map();
}

getEntry(key: string): BaggageEntry | undefined {
const entry = this.entries.get(key);

if (!entry) {
return undefined;
}

return Object.assign({}, entry);
}

getAllEntries(): [string, BaggageEntry][] {
return Array.from(this.entries.entries()).map(([key, value]) => [key, value]);
}

setEntry(key: string, entry: BaggageEntry): MutableBaggageImpl {
this.entries.set(key, entry);

return this;
}

removeEntry(key: string): MutableBaggageImpl {
this.entries.delete(key);

return this;
}

removeEntries(...keys: string[]): MutableBaggageImpl {
for (const key of keys) {
this.entries.delete(key);
}

return this;
}

clear(): MutableBaggageImpl {
this.entries.clear();

return this;
}
}
Loading

0 comments on commit 5cf0be3

Please sign in to comment.