Skip to content

Commit 208ff35

Browse files
committed
fix traces: false not being respected
1 parent bff65e1 commit 208ff35

File tree

2 files changed

+95
-51
lines changed

2 files changed

+95
-51
lines changed

packages/plugins/opentelemetry/src/plugin.ts

Lines changed: 80 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,9 @@ export function useOpenTelemetry(
246246
const inheritContext = options.inheritContext ?? true;
247247
const propagateContext = options.propagateContext ?? true;
248248
let useContextManager: boolean;
249-
const traces = typeof options.traces === 'object' ? options.traces : {};
250249

251250
let tracer: Tracer;
251+
let traces: TracesConfig | undefined;
252252
let initSpan: Context | null;
253253

254254
// TODO: Make it const once Yoga has the Hive Logger
@@ -257,19 +257,7 @@ export function useOpenTelemetry(
257257

258258
pluginLogger?.info('Enabled');
259259

260-
if (options.traces !== false) {
261-
const httpSpanConfig =
262-
options.traces === true ? null : options.traces?.spans?.http;
263-
264-
// Only override http filter if it's not disabled or already a function
265-
if (httpSpanConfig ?? true === true) {
266-
options.traces = {
267-
...(options.traces as object),
268-
spans: { http: defaultHttpFilter },
269-
};
270-
}
271-
}
272-
260+
// Resolve tracing configuration. `undefined` means disabled
273261
function isParentEnabled(state: State): boolean {
274262
const parentState = getMostSpecificState(state);
275263
return !parentState || !!parentState.otel;
@@ -312,25 +300,15 @@ export function useOpenTelemetry(
312300

313301
pluginLogger?.info('Initializing');
314302

315-
tracer = traces.tracer || trace.getTracer('gateway');
303+
tracer = traces?.tracer ?? trace.getTracer('gateway');
304+
traces = resolveTracesConfig(options, useContextManager, pluginLogger);
316305

317306
initSpan = trace.setSpan(
318307
context.active(),
319308
tracer.startSpan('gateway.initialization', {
320309
startTime: initializationTime,
321310
}),
322311
);
323-
324-
if (!useContextManager) {
325-
if (traces.spans?.schema) {
326-
pluginLogger?.warn(
327-
'Schema loading spans are disabled because no context manager is available',
328-
);
329-
}
330-
331-
traces.spans = traces.spans ?? {};
332-
traces.spans.schema = false;
333-
}
334312
}
335313

336314
const plugin = withState<
@@ -357,15 +335,15 @@ export function useOpenTelemetry(
357335
},
358336
instrumentation: {
359337
request({ state: { forRequest }, request }, wrapped) {
360-
if (!shouldTrace(traces.spans?.http, { request })) {
361-
return wrapped();
362-
}
363-
364-
const url = getURL(request);
365-
366338
return unfakePromise(
367339
preparation$
368340
.then(() => {
341+
if (!traces || !shouldTrace(traces.spans?.http, { request })) {
342+
return wrapped();
343+
}
344+
345+
const url = getURL(request);
346+
369347
const ctx = inheritContext
370348
? propagation.extract(
371349
context.active(),
@@ -400,6 +378,7 @@ export function useOpenTelemetry(
400378
wrapped,
401379
) {
402380
if (
381+
!traces ||
403382
!isParentEnabled(parentState) ||
404383
!shouldTrace(traces.spans?.graphql, { context: gqlCtx })
405384
) {
@@ -432,6 +411,7 @@ export function useOpenTelemetry(
432411

433412
context({ state, context: gqlCtx }, wrapped) {
434413
if (
414+
!traces ||
435415
!isParentEnabled(state) ||
436416
!shouldTrace(traces.spans?.graphqlContextBuilding, {
437417
context: gqlCtx,
@@ -463,6 +443,7 @@ export function useOpenTelemetry(
463443

464444
parse({ state, context: gqlCtx }, wrapped) {
465445
if (
446+
!traces ||
466447
!isParentEnabled(state) ||
467448
!shouldTrace(traces.spans?.graphqlParse, { context: gqlCtx })
468449
) {
@@ -490,6 +471,7 @@ export function useOpenTelemetry(
490471

491472
validate({ state, context: gqlCtx }, wrapped) {
492473
if (
474+
!traces ||
493475
!isParentEnabled(state) ||
494476
!shouldTrace(traces.spans?.graphqlValidate, { context: gqlCtx })
495477
) {
@@ -518,6 +500,7 @@ export function useOpenTelemetry(
518500

519501
execute({ state, context: gqlCtx }, wrapped) {
520502
if (
503+
!traces ||
521504
!isParentEnabled(state) ||
522505
!shouldTrace(traces.spans?.graphqlExecute, { context: gqlCtx })
523506
) {
@@ -560,6 +543,7 @@ export function useOpenTelemetry(
560543
const isIntrospection = !executionRequest.context.params;
561544

562545
if (
546+
!traces ||
563547
!isParentEnabled(parentState) ||
564548
parentState.forOperation?.skipExecuteSpan ||
565549
!shouldTrace(
@@ -618,15 +602,16 @@ export function useOpenTelemetry(
618602
state = getState(getRetryInfo(executionRequest));
619603
}
620604

621-
if (
622-
!isParentEnabled(state) ||
623-
!shouldTrace(traces.spans?.upstreamFetch, { executionRequest })
624-
) {
625-
return wrapped();
626-
}
627-
628605
return unfakePromise(
629606
preparation$.then(() => {
607+
if (
608+
!traces ||
609+
!isParentEnabled(state) ||
610+
!shouldTrace(traces.spans?.upstreamFetch, { executionRequest })
611+
) {
612+
return wrapped();
613+
}
614+
630615
const { forSubgraphExecution } = state;
631616
const ctx = createUpstreamHttpFetchSpan({
632617
ctx: getContext(state),
@@ -654,12 +639,12 @@ export function useOpenTelemetry(
654639
},
655640

656641
schema(_, wrapped) {
657-
if (!shouldTrace(traces.spans?.schema, null)) {
658-
return wrapped();
659-
}
660-
661642
return unfakePromise(
662643
preparation$.then(() => {
644+
if (!traces || !shouldTrace(traces.spans?.schema, null)) {
645+
return wrapped();
646+
}
647+
663648
const ctx = createSchemaLoadingSpan({
664649
ctx: initSpan ?? ROOT_CONTEXT,
665650
tracer,
@@ -699,7 +684,7 @@ export function useOpenTelemetry(
699684
// When running in a runtime without a context manager, we have to keep track of the
700685
// span correlated to a log manually. For now, we just link all logs for a request to
701686
// the HTTP root span
702-
if (!useContextManager) {
687+
if (traces && !useContextManager) {
703688
const requestId =
704689
// TODO: serverContext.log will not be available in Yoga, this will be fixed when Hive Logger is integrated into Yoga
705690
serverContext.log?.attrs?.[
@@ -736,6 +721,7 @@ export function useOpenTelemetry(
736721
},
737722

738723
onCacheGet: (payload) =>
724+
traces &&
739725
shouldTrace(traces.events?.cache, { key: payload.key, action: 'read' })
740726
? {
741727
onCacheMiss: () => recordCacheEvent('miss', payload),
@@ -746,6 +732,7 @@ export function useOpenTelemetry(
746732
: undefined,
747733

748734
onCacheSet: (payload) =>
735+
traces &&
749736
shouldTrace(traces.events?.cache, { key: payload.key, action: 'write' })
750737
? {
751738
onCacheSetDone: () => recordCacheEvent('write', payload),
@@ -755,7 +742,8 @@ export function useOpenTelemetry(
755742
: undefined,
756743

757744
onResponse({ response, state, serverContext }) {
758-
state.forRequest.otel &&
745+
traces &&
746+
state.forRequest.otel &&
759747
setResponseAttributes(state.forRequest.otel.root, response);
760748

761749
// Clean up Logging context tracking for runtimes without context manager
@@ -774,6 +762,7 @@ export function useOpenTelemetry(
774762

775763
onParams({ state, context: gqlCtx, params }) {
776764
if (
765+
!traces ||
777766
!isParentEnabled(state) ||
778767
!shouldTrace(traces.spans?.graphql, { context: gqlCtx })
779768
) {
@@ -786,6 +775,7 @@ export function useOpenTelemetry(
786775

787776
onExecutionResult({ result, context: gqlCtx, state }) {
788777
if (
778+
!traces ||
789779
!isParentEnabled(state) ||
790780
!shouldTrace(traces.spans?.graphql, { context: gqlCtx })
791781
) {
@@ -797,6 +787,7 @@ export function useOpenTelemetry(
797787

798788
onParse({ state, context: gqlCtx }) {
799789
if (
790+
!traces ||
800791
!isParentEnabled(state) ||
801792
!shouldTrace(traces.spans?.graphqlParse, { context: gqlCtx })
802793
) {
@@ -822,6 +813,7 @@ export function useOpenTelemetry(
822813

823814
onValidate({ state, context: gqlCtx, params }) {
824815
if (
816+
!traces ||
825817
!isParentEnabled(state) ||
826818
!shouldTrace(traces.spans?.graphqlValidate, { context: gqlCtx })
827819
) {
@@ -839,10 +831,7 @@ export function useOpenTelemetry(
839831
},
840832

841833
onExecute({ state, args }) {
842-
if (!isParentEnabled(state)) {
843-
return;
844-
}
845-
834+
// Check for execute span is done in `instrument.execute`
846835
if (state.forOperation.skipExecuteSpan) {
847836
return;
848837
}
@@ -896,6 +885,7 @@ export function useOpenTelemetry(
896885
}
897886

898887
if (
888+
!traces ||
899889
!isParentEnabled(state) ||
900890
!shouldTrace(traces.spans?.upstreamFetch, { executionRequest })
901891
) {
@@ -917,12 +907,14 @@ export function useOpenTelemetry(
917907
},
918908

919909
onSchemaChange(payload) {
920-
setSchemaAttributes(payload);
921-
922910
if (initSpan) {
923911
trace.getSpan(initSpan)?.end();
924912
initSpan = null;
925913
}
914+
915+
if (!traces || !shouldTrace(traces?.spans?.schema, null)) {
916+
setSchemaAttributes(payload);
917+
}
926918
},
927919

928920
onDispose() {
@@ -983,3 +975,40 @@ export const defaultHttpFilter: SpansConfig['http'] = ({ request }) => {
983975

984976
return true;
985977
};
978+
979+
/**
980+
* Resolves the traces config.
981+
* Returns `undefined` if tracing is disabled
982+
*/
983+
function resolveTracesConfig(
984+
options: OpenTelemetryGatewayPluginOptions,
985+
useContextManager: boolean,
986+
log?: Logger,
987+
): TracesConfig | undefined {
988+
if (options.traces === false) {
989+
return undefined;
990+
}
991+
992+
let traces: TracesConfig =
993+
typeof options.traces === 'object' ? options.traces : {};
994+
995+
traces.spans ??= {};
996+
997+
// Only override http filter if it's not disabled or already a function
998+
if (traces.spans.http ?? true === true) {
999+
traces.spans = { ...traces.spans, http: defaultHttpFilter };
1000+
}
1001+
1002+
// Schema span is only working with a context manager, otherwise we can't correlate its sub-spans
1003+
if (!useContextManager) {
1004+
if (traces.spans.schema) {
1005+
log?.warn(
1006+
'Schema loading spans are disabled because no context manager is available',
1007+
);
1008+
}
1009+
1010+
traces.spans.schema = false;
1011+
}
1012+
1013+
return traces;
1014+
}

packages/plugins/opentelemetry/tests/useOpenTelemetry.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,21 @@ describe('useOpenTelemetry', () => {
609609
allExpectedSpans.forEach(spanExporter.assertNoSpanWithName);
610610
});
611611

612+
it('should not trace prometheus metrics scraping by default', async () => {
613+
await using gateway = await buildTestGatewayForCtx({
614+
options: {
615+
traces: {
616+
spans: { schema: false },
617+
},
618+
},
619+
});
620+
await gateway.fetch('/metrics');
621+
await gateway.fetch('/not-found');
622+
623+
spanExporter.assertNoSpanWithName('GET /metrics');
624+
spanExporter.assertSpanWithName('GET /not-found');
625+
});
626+
612627
it('should not trace graphql operation if disable', async () => {
613628
await using gateway = await buildTestGatewayForCtx({
614629
options: {

0 commit comments

Comments
 (0)