Skip to content

Commit 6f98def

Browse files
feat: Add baggage key predicate to baggage span processor (#2212)
* feat: Add optional predicate func to baggage span processor * add default behaviour to contructor comments * rework processor to require predicate * use filter when selecting baggage keys * rename filter to predicate * add regex example and test * move types into types.ts --------- Co-authored-by: Jamie Danielson <jamiedanielson@honeycomb.io>
1 parent 96eb7dc commit 6f98def

File tree

5 files changed

+143
-12
lines changed

5 files changed

+143
-12
lines changed

packages/baggage-span-processor/README.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ npm install --save @opentelemetry/baggage-span-processor
2727

2828
### Usage
2929

30-
Add to the span processors during configuration:
30+
Add to the span processors that copies all baggage entries during configuration:
3131

3232
```javascript
33-
import { NodeSDK, tracing } from "@opentelemetry/sdk-node";
34-
import { BaggageSpanProcessor } from "@opentelemetry/baggage-span-processor";
33+
import { NodeSDK, tracing } from '@opentelemetry/sdk-node';
34+
import { ALLOW_ALL_BAGGAGE_KEYS, BaggageSpanProcessor } from '@opentelemetry/baggage-span-processor';
3535

3636
const spanProcessors = [
3737
new tracing.SimpleSpanProcessor(
3838
new tracing.ConsoleSpanExporter()),
39-
new BaggageSpanProcessor()];
39+
new BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS)];
4040

4141
const sdk = new NodeSDK({
4242
serviceName: "example-service",
@@ -46,6 +46,21 @@ const sdk = new NodeSDK({
4646
sdk.start();
4747
```
4848

49+
Alternatively, you can provide a custom baggage key predicate to select which baggage keys you want to copy.
50+
51+
For example, to only copy baggage entries that start with `my-key`:
52+
53+
```javascript
54+
new BaggageSpanProcessor((baggageKey: string) => key.startsWith('my-key'))
55+
```
56+
57+
For example, to only copy baggage entries that matches the regex `^key.+`:
58+
59+
```javascript
60+
const regex = new RegExp("^key.+")
61+
new BaggageSpanProcessor((baggageKey: string) => regex.test(baggageKey))
62+
```
63+
4964
## Useful links
5065

5166
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>

packages/baggage-span-processor/src/baggage-span-processor.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { BaggageKeyPredicate } from './types';
1718
import { Context, propagation } from '@opentelemetry/api';
1819
import {
1920
SpanProcessor,
@@ -43,6 +44,16 @@ import {
4344
* values will appear in all outgoing HTTP headers from the application.
4445
*/
4546
export class BaggageSpanProcessor implements SpanProcessor {
47+
private _keyPredicate: BaggageKeyPredicate;
48+
49+
/**
50+
* Constructs a new BaggageSpanProcessor instance.
51+
* @param keyPredicate A predicate that determines whether a baggage key-value pair should be added to new spans as a span attribute.
52+
*/
53+
constructor(keyPredicate: BaggageKeyPredicate) {
54+
this._keyPredicate = keyPredicate;
55+
}
56+
4657
/**
4758
* Forces to export all finished spans
4859
*/
@@ -57,11 +68,9 @@ export class BaggageSpanProcessor implements SpanProcessor {
5768
* @param span the Span that just started.
5869
*/
5970
onStart(span: Span, parentContext: Context): void {
60-
(propagation.getBaggage(parentContext)?.getAllEntries() ?? []).forEach(
61-
entry => {
62-
span.setAttribute(entry[0], entry[1].value);
63-
}
64-
);
71+
(propagation.getBaggage(parentContext)?.getAllEntries() ?? [])
72+
.filter(entry => this._keyPredicate(entry[0]))
73+
.forEach(entry => span.setAttribute(entry[0], entry[1].value));
6574
}
6675

6776
/**

packages/baggage-span-processor/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414
* limitations under the License.
1515
*/
1616

17-
export { BaggageSpanProcessor } from './baggage-span-processor';
17+
export * from './baggage-span-processor';
18+
export * from './types';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* A function that determines whether a baggage key-value pair should be added to new
19+
* spans as a span attribute.
20+
*/
21+
export type BaggageKeyPredicate = (baggageKey: string) => boolean;
22+
23+
/**
24+
* A {@link BaggageKeyPredicate} that includes all baggage keys.
25+
*/
26+
export const ALLOW_ALL_BAGGAGE_KEYS: BaggageKeyPredicate = (_: string) => true;

packages/baggage-span-processor/test/baggage-span-processor.test.ts

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
import { BaggageSpanProcessor } from '../src/baggage-span-processor';
18+
import { ALLOW_ALL_BAGGAGE_KEYS } from '../src/types';
1819
import {
1920
propagation,
2021
ROOT_CONTEXT,
@@ -24,8 +25,8 @@ import {
2425
import { BasicTracerProvider, Span } from '@opentelemetry/sdk-trace-base';
2526
import { expect } from 'expect';
2627

27-
describe('BaggageSpanProcessor', () => {
28-
const baggageProcessor = new BaggageSpanProcessor();
28+
describe('BaggageSpanProcessor with all keys filter', () => {
29+
const baggageProcessor = new BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS);
2930

3031
const bag = propagation.createBaggage({
3132
brand: { value: 'samsonite' },
@@ -72,3 +73,82 @@ describe('BaggageSpanProcessor', () => {
7273
await expect(baggageProcessor.shutdown()).resolves.not.toThrow();
7374
});
7475
});
76+
77+
describe('BaggageSpanProcessor with startWith key filter', () => {
78+
const baggageProcessor = new BaggageSpanProcessor((key: string) =>
79+
key.startsWith('brand')
80+
);
81+
82+
const bag = propagation.createBaggage({
83+
brand: { value: 'samsonite' },
84+
color: { value: 'blue' },
85+
});
86+
87+
const expectedAttrs = {
88+
brand: 'samsonite',
89+
};
90+
91+
let span: Span;
92+
93+
beforeEach(() => {
94+
span = new Span(
95+
new BasicTracerProvider().getTracer('baggage-testing'),
96+
ROOT_CONTEXT,
97+
'Edward W. Span',
98+
{
99+
traceId: 'e4cda95b652f4a1592b449d5929fda1b',
100+
spanId: '7e0c63257de34c92',
101+
traceFlags: TraceFlags.SAMPLED,
102+
},
103+
SpanKind.SERVER
104+
);
105+
});
106+
107+
it('should only add baggage entries that match filter', () => {
108+
expect(span.attributes).toEqual({});
109+
const ctx = propagation.setBaggage(ROOT_CONTEXT, bag);
110+
baggageProcessor.onStart(span, ctx);
111+
112+
expect(span.attributes).toEqual(expectedAttrs);
113+
});
114+
});
115+
116+
describe('BaggageSpanProcessor with regex key filter', () => {
117+
const regex = new RegExp('^col.+');
118+
const baggageProcessor = new BaggageSpanProcessor((key: string) =>
119+
regex.test(key)
120+
);
121+
122+
const bag = propagation.createBaggage({
123+
brand: { value: 'samsonite' },
124+
color: { value: 'blue' },
125+
});
126+
127+
const expectedAttrs = {
128+
color: 'blue',
129+
};
130+
131+
let span: Span;
132+
133+
beforeEach(() => {
134+
span = new Span(
135+
new BasicTracerProvider().getTracer('baggage-testing'),
136+
ROOT_CONTEXT,
137+
'Edward W. Span',
138+
{
139+
traceId: 'e4cda95b652f4a1592b449d5929fda1b',
140+
spanId: '7e0c63257de34c92',
141+
traceFlags: TraceFlags.SAMPLED,
142+
},
143+
SpanKind.SERVER
144+
);
145+
});
146+
147+
it('should only add baggage entries that match filter', () => {
148+
expect(span.attributes).toEqual({});
149+
const ctx = propagation.setBaggage(ROOT_CONTEXT, bag);
150+
baggageProcessor.onStart(span, ctx);
151+
152+
expect(span.attributes).toEqual(expectedAttrs);
153+
});
154+
});

0 commit comments

Comments
 (0)