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

Commit

Permalink
feat(tracing): include B3 propagator (#1352)
Browse files Browse the repository at this point in the history
  • Loading branch information
10xLaCroixDrinker authored Apr 1, 2024
1 parent 2d87f5f commit 6b6cd4b
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 12 deletions.
20 changes: 16 additions & 4 deletions __tests__/integration/one-app.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,7 @@ describe('Tests that require Docker setup', () => {
...defaultFetchOptions,
});
const htmlData = await response.text();
const traceId = response.headers.get('traceid');
const scriptContents = htmlData.match(
/<script id="initial-state" nonce=\S+>([^<]+)<\/script>/
)[1];
Expand All @@ -965,7 +966,10 @@ describe('Tests that require Docker setup', () => {
},
],
secretMessage: 'you are being watched',
traceparent: expect.any(String),
traceparent: expect.stringContaining(traceId),
xB3TraceId: traceId,
xB3TraceSpan: expect.any(String),
xB3Sampled: expect.any(String),
loadedOnServer: true,
});
});
Expand Down Expand Up @@ -1318,7 +1322,9 @@ describe('Tests that require Docker setup', () => {
)[1];
const initialState = scriptContents.match(/window\.__INITIAL_STATE__ = "([^<]+)";/)[1];
const state = transit.fromJSON(initialState.replace(/\\/g, ''));
const { traceparent } = state.getIn(['modules', 'ssr-frank', 'data']);
const {
traceparent, xB3TraceId, xB3TraceSpan, xB3Sampled,
} = state.getIn(['modules', 'ssr-frank', 'data']);

const resourceAttributes = trace.resourceSpans[0].resource.attributes.reduce(
(acc, attribute) => ({
Expand Down Expand Up @@ -1403,8 +1409,8 @@ describe('Tests that require Docker setup', () => {
});

expect(response.headers.get('traceid')).toBe(traceId);
expect(traceparent).toEqual(expect.stringContaining(traceId));

expect(xB3TraceId).toBe(traceId);
expect(traceparent).toBe(`00-${xB3TraceId}-${xB3TraceSpan}-0${xB3Sampled}`);
const httpSpans = getSpans('@opentelemetry/instrumentation-http', traceId);
expect(httpSpans.length).toBe(2);
const spans = getSpans('@autotelic/fastify-opentelemetry', traceId);
Expand Down Expand Up @@ -1811,6 +1817,9 @@ describe('Tests that can run against either local Docker setup or remote One App
posts: [{ id: 1, title: 'json-server', author: 'typicode' }],
secretMessage: null,
traceparent: null,
xB3TraceId: null,
xB3TraceSpan: null,
xB3Sampled: null,
loadedOnServer: false,
},
});
Expand All @@ -1835,6 +1844,9 @@ describe('Tests that can run against either local Docker setup or remote One App
posts: [{ id: 1, title: 'json-server', author: 'typicode' }],
secretMessage: null,
traceparent: null,
xB3TraceId: null,
xB3TraceSpan: null,
xB3Sampled: null,
loadedOnServer: false,
},
});
Expand Down
28 changes: 26 additions & 2 deletions __tests__/server/utils/tracer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,18 @@ import {
ConsoleSpanExporter,
NoopSpanProcessor,
} from '@opentelemetry/sdk-trace-base';
import { W3CTraceContextPropagator } from '@opentelemetry/core';
import {
CompositePropagator,
W3CTraceContextPropagator,
} from '@opentelemetry/core';
import {
B3Propagator,
B3InjectEncoding,
} from '@opentelemetry/propagator-b3';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';

jest.mock('@opentelemetry/core');
jest.mock('@opentelemetry/propagator-b3');
jest.mock('@opentelemetry/instrumentation');
jest.mock('@opentelemetry/instrumentation-http');
jest.mock('@opentelemetry/instrumentation-pino');
Expand Down Expand Up @@ -132,10 +140,26 @@ describe('tracer', () => {
tracerProvider: _tracerProvider,
instrumentations: [expect.any(HttpInstrumentation), expect.any(PinoInstrumentation)],
});
});

it('should configure the propagator', () => {
const { _tracerProvider } = setup({});
expect(_tracerProvider.register).toHaveBeenCalledTimes(1);
expect(_tracerProvider.register).toHaveBeenCalledWith(expect.objectContaining({
propagator: expect.any(W3CTraceContextPropagator),
propagator: expect.any(CompositePropagator),
}));
expect(CompositePropagator).toHaveBeenCalledTimes(1);
expect(CompositePropagator).toHaveBeenCalledWith({
propagators: [
expect.any(B3Propagator),
expect.any(W3CTraceContextPropagator),
],
});
expect(W3CTraceContextPropagator).toHaveBeenCalledTimes(1);
expect(B3Propagator).toHaveBeenCalledTimes(1);
expect(B3Propagator).toHaveBeenCalledWith({
injectEncoding: B3InjectEncoding.MULTI_HEADER,
});
});

it('should not trace outgoing requests that do not have a parent span', () => {
Expand Down
1 change: 1 addition & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"@opentelemetry/instrumentation": "^0.49.1",
"@opentelemetry/instrumentation-http": "^0.49.1",
"@opentelemetry/instrumentation-pino": "^0.36.0",
"@opentelemetry/propagator-b3": "^1.22.0",
"@opentelemetry/resources": "^1.22.0",
"@opentelemetry/sdk-trace-base": "^1.22.0",
"@opentelemetry/sdk-trace-node": "^1.22.0",
Expand Down
3 changes: 3 additions & 0 deletions prod-sample/api/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ server.use((req, res, next) => {
const secretMessage = req.headers['auth-token'] ? 'you are being watched' : 'unauthorised';
res.append('secret-message', secretMessage);
res.append('traceparent', req.headers.traceparent);
res.append('x-b3-traceid', req.headers['x-b3-traceid']);
res.append('x-b3-spanid', req.headers['x-b3-spanid']);
res.append('x-b3-sampled', req.headers['x-b3-sampled']);
next();
});
server.use(router);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@ const loadModuleData = async ({ store, fetchClient }) => {
}
store.dispatch({ type: FAKE_REQUEST });
const fastRes = await fetchClient('https://fast.api.frank/posts');
const secretMessage = fastRes.headers.get('secret-message');
const traceparent = fastRes.headers.get('traceparent');
const posts = await fastRes.json();
store.dispatch({
type: FAKE_SUCCESS,
data: {
posts,
secretMessage,
traceparent,
secretMessage: fastRes.headers.get('secret-message'),
traceparent: fastRes.headers.get('traceparent'),
xB3TraceId: fastRes.headers.get('x-b3-traceid'),
xB3TraceSpan: fastRes.headers.get('x-b3-spanid'),
xB3Sampled: fastRes.headers.get('x-b3-sampled'),
loadedOnServer: !global.BROWSER,
},
});
Expand Down
16 changes: 14 additions & 2 deletions src/server/utils/tracer.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ import {
NoopSpanProcessor,
} from '@opentelemetry/sdk-trace-base';
import { trace } from '@opentelemetry/api';
import { W3CTraceContextPropagator } from '@opentelemetry/core';
import {
CompositePropagator,
W3CTraceContextPropagator,
} from '@opentelemetry/core';
import {
B3Propagator,
B3InjectEncoding,
} from '@opentelemetry/propagator-b3';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
import {
Resource,
Expand Down Expand Up @@ -107,7 +114,12 @@ if (process.env.NODE_ENV === 'development' && argv.logLevel === 'trace') {
}

tracerProvider.register({
propagator: new W3CTraceContextPropagator(),
propagator: new CompositePropagator({
propagators: [
new B3Propagator({ injectEncoding: B3InjectEncoding.MULTI_HEADER }),
new W3CTraceContextPropagator(),
],
}),
});

['SIGINT', 'SIGTERM'].forEach((signalName) => process.on(signalName, async () => {
Expand Down

0 comments on commit 6b6cd4b

Please sign in to comment.