diff --git a/.changeset/@graphql-hive_gateway-1611-dependencies.md b/.changeset/@graphql-hive_gateway-1611-dependencies.md new file mode 100644 index 000000000..1fe71295d --- /dev/null +++ b/.changeset/@graphql-hive_gateway-1611-dependencies.md @@ -0,0 +1,13 @@ +--- +'@graphql-hive/gateway': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-mesh/cache-redis@^0.105.0` ↗︎](https://www.npmjs.com/package/@graphql-mesh/cache-redis/v/0.105.0) (from `^0.104.14`, in `dependencies`) +- Updated dependency [`@graphql-tools/code-file-loader@^8.1.24` ↗︎](https://www.npmjs.com/package/@graphql-tools/code-file-loader/v/8.1.24) (from `^8.1.23`, in `dependencies`) +- Updated dependency [`@graphql-tools/graphql-file-loader@^8.1.4` ↗︎](https://www.npmjs.com/package/@graphql-tools/graphql-file-loader/v/8.1.4) (from `^8.1.3`, in `dependencies`) +- Updated dependency [`@graphql-tools/load@^8.1.4` ↗︎](https://www.npmjs.com/package/@graphql-tools/load/v/8.1.4) (from `^8.1.3`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) +- Updated dependency [`@graphql-yoga/render-graphiql@^5.16.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/render-graphiql/v/5.16.1) (from `^5.16.0`, in `dependencies`) +- Updated dependency [`graphql-yoga@^5.16.1` ↗︎](https://www.npmjs.com/package/graphql-yoga/v/5.16.1) (from `^5.16.0`, in `dependencies`) diff --git a/.changeset/@graphql-hive_gateway-runtime-1611-dependencies.md b/.changeset/@graphql-hive_gateway-runtime-1611-dependencies.md new file mode 100644 index 000000000..9dc3dbaf8 --- /dev/null +++ b/.changeset/@graphql-hive_gateway-runtime-1611-dependencies.md @@ -0,0 +1,12 @@ +--- +'@graphql-hive/gateway-runtime': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-apollo-usage-report@^0.11.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-apollo-usage-report/v/0.11.1) (from `^0.11.0`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-csrf-prevention@^3.16.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-csrf-prevention/v/3.16.1) (from `^3.16.0`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-defer-stream@^3.16.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-defer-stream/v/3.16.1) (from `^3.16.0`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-persisted-operations@^3.16.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-persisted-operations/v/3.16.1) (from `^3.16.0`, in `dependencies`) +- Updated dependency [`graphql-yoga@^5.16.1` ↗︎](https://www.npmjs.com/package/graphql-yoga/v/5.16.1) (from `^5.16.0`, in `dependencies`) diff --git a/.changeset/@graphql-hive_gateway-testing-1611-dependencies.md b/.changeset/@graphql-hive_gateway-testing-1611-dependencies.md new file mode 100644 index 000000000..11f56b8da --- /dev/null +++ b/.changeset/@graphql-hive_gateway-testing-1611-dependencies.md @@ -0,0 +1,8 @@ +--- +'@graphql-hive/gateway-testing': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) +- Updated dependency [`graphql-yoga@^5.16.1` ↗︎](https://www.npmjs.com/package/graphql-yoga/v/5.16.1) (from `^5.16.0`, in `dependencies`) diff --git a/.changeset/@graphql-hive_nestjs-1611-dependencies.md b/.changeset/@graphql-hive_nestjs-1611-dependencies.md new file mode 100644 index 000000000..a2cc7de95 --- /dev/null +++ b/.changeset/@graphql-hive_nestjs-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-hive/nestjs': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-hive_plugin-deduplicate-request-1611-dependencies.md b/.changeset/@graphql-hive_plugin-deduplicate-request-1611-dependencies.md new file mode 100644 index 000000000..785a16e8b --- /dev/null +++ b/.changeset/@graphql-hive_plugin-deduplicate-request-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-hive/plugin-deduplicate-request': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-hive_plugin-opentelemetry-1611-dependencies.md b/.changeset/@graphql-hive_plugin-opentelemetry-1611-dependencies.md new file mode 100644 index 000000000..74144ec09 --- /dev/null +++ b/.changeset/@graphql-hive_plugin-opentelemetry-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-hive/plugin-opentelemetry': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_fusion-runtime-1611-dependencies.md b/.changeset/@graphql-mesh_fusion-runtime-1611-dependencies.md new file mode 100644 index 000000000..023c9c717 --- /dev/null +++ b/.changeset/@graphql-mesh_fusion-runtime-1611-dependencies.md @@ -0,0 +1,10 @@ +--- +'@graphql-mesh/fusion-runtime': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.10`, in `dependencies`) +- Updated dependency [`@graphql-tools/merge@^9.1.3` ↗︎](https://www.npmjs.com/package/@graphql-tools/merge/v/9.1.3) (from `^9.1.2`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) +- Updated dependency [`graphql-yoga@^5.16.1` ↗︎](https://www.npmjs.com/package/graphql-yoga/v/5.16.1) (from `^5.16.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_hmac-upstream-signature-1611-dependencies.md b/.changeset/@graphql-mesh_hmac-upstream-signature-1611-dependencies.md new file mode 100644 index 000000000..95923be7a --- /dev/null +++ b/.changeset/@graphql-mesh_hmac-upstream-signature-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-mesh/hmac-upstream-signature': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_plugin-jwt-auth-1611-dependencies.md b/.changeset/@graphql-mesh_plugin-jwt-auth-1611-dependencies.md new file mode 100644 index 000000000..aa0bd532b --- /dev/null +++ b/.changeset/@graphql-mesh_plugin-jwt-auth-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-mesh/plugin-jwt-auth': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-yoga/plugin-jwt@^3.10.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-jwt/v/3.10.1) (from `^3.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_plugin-prometheus-1611-dependencies.md b/.changeset/@graphql-mesh_plugin-prometheus-1611-dependencies.md new file mode 100644 index 000000000..a15069999 --- /dev/null +++ b/.changeset/@graphql-mesh_plugin-prometheus-1611-dependencies.md @@ -0,0 +1,8 @@ +--- +'@graphql-mesh/plugin-prometheus': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) +- Updated dependency [`@graphql-yoga/plugin-prometheus@^6.11.1` ↗︎](https://www.npmjs.com/package/@graphql-yoga/plugin-prometheus/v/6.11.1) (from `^6.11.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_transport-common-1611-dependencies.md b/.changeset/@graphql-mesh_transport-common-1611-dependencies.md new file mode 100644 index 000000000..02ddebe58 --- /dev/null +++ b/.changeset/@graphql-mesh_transport-common-1611-dependencies.md @@ -0,0 +1,8 @@ +--- +'@graphql-mesh/transport-common': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.10`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_transport-http-1611-dependencies.md b/.changeset/@graphql-mesh_transport-http-1611-dependencies.md new file mode 100644 index 000000000..202f7f033 --- /dev/null +++ b/.changeset/@graphql-mesh_transport-http-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-mesh/transport-http': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_transport-http-callback-1611-dependencies.md b/.changeset/@graphql-mesh_transport-http-callback-1611-dependencies.md new file mode 100644 index 000000000..c97a4731c --- /dev/null +++ b/.changeset/@graphql-mesh_transport-http-callback-1611-dependencies.md @@ -0,0 +1,8 @@ +--- +'@graphql-mesh/transport-http-callback': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) +- Updated dependency [`@whatwg-node/fetch@^0.10.12` ↗︎](https://www.npmjs.com/package/@whatwg-node/fetch/v/0.10.12) (from `^0.10.11`, in `dependencies`) diff --git a/.changeset/@graphql-mesh_transport-ws-1611-dependencies.md b/.changeset/@graphql-mesh_transport-ws-1611-dependencies.md new file mode 100644 index 000000000..9dbeee379 --- /dev/null +++ b/.changeset/@graphql-mesh_transport-ws-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-mesh/transport-ws': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-tools_batch-delegate-1611-dependencies.md b/.changeset/@graphql-tools_batch-delegate-1611-dependencies.md new file mode 100644 index 000000000..e412c8b9b --- /dev/null +++ b/.changeset/@graphql-tools_batch-delegate-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/batch-delegate': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-tools_batch-execute-1611-dependencies.md b/.changeset/@graphql-tools_batch-execute-1611-dependencies.md new file mode 100644 index 000000000..f7574e492 --- /dev/null +++ b/.changeset/@graphql-tools_batch-execute-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/batch-execute': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-tools_delegate-1611-dependencies.md b/.changeset/@graphql-tools_delegate-1611-dependencies.md new file mode 100644 index 000000000..a62c1ad1b --- /dev/null +++ b/.changeset/@graphql-tools_delegate-1611-dependencies.md @@ -0,0 +1,10 @@ +--- +'@graphql-tools/delegate': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.10`, in `dependencies`) +- Updated dependency [`@graphql-tools/schema@^10.0.27` ↗︎](https://www.npmjs.com/package/@graphql-tools/schema/v/10.0.27) (from `^10.0.26`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) +- Removed dependency [`dset@^3.1.2` ↗︎](https://www.npmjs.com/package/dset/v/3.1.2) (from `dependencies`) diff --git a/.changeset/@graphql-tools_executor-common-1611-dependencies.md b/.changeset/@graphql-tools_executor-common-1611-dependencies.md new file mode 100644 index 000000000..f9bcbaf45 --- /dev/null +++ b/.changeset/@graphql-tools_executor-common-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/executor-common': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-tools_executor-graphql-ws-1611-dependencies.md b/.changeset/@graphql-tools_executor-graphql-ws-1611-dependencies.md new file mode 100644 index 000000000..0cc2b1457 --- /dev/null +++ b/.changeset/@graphql-tools_executor-graphql-ws-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/executor-graphql-ws': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-tools_executor-http-1611-dependencies.md b/.changeset/@graphql-tools_executor-http-1611-dependencies.md new file mode 100644 index 000000000..16c8902a3 --- /dev/null +++ b/.changeset/@graphql-tools_executor-http-1611-dependencies.md @@ -0,0 +1,8 @@ +--- +'@graphql-tools/executor-http': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) +- Updated dependency [`@whatwg-node/fetch@^0.10.12` ↗︎](https://www.npmjs.com/package/@whatwg-node/fetch/v/0.10.12) (from `^0.10.11`, in `dependencies`) diff --git a/.changeset/@graphql-tools_federation-1611-dependencies.md b/.changeset/@graphql-tools_federation-1611-dependencies.md new file mode 100644 index 000000000..c92ea69c4 --- /dev/null +++ b/.changeset/@graphql-tools_federation-1611-dependencies.md @@ -0,0 +1,11 @@ +--- +'@graphql-tools/federation': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.10`, in `dependencies`) +- Updated dependency [`@graphql-tools/merge@^9.1.3` ↗︎](https://www.npmjs.com/package/@graphql-tools/merge/v/9.1.3) (from `^9.1.2`, in `dependencies`) +- Updated dependency [`@graphql-tools/schema@^10.0.27` ↗︎](https://www.npmjs.com/package/@graphql-tools/schema/v/10.0.27) (from `^10.0.26`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) +- Updated dependency [`@whatwg-node/fetch@^0.10.12` ↗︎](https://www.npmjs.com/package/@whatwg-node/fetch/v/0.10.12) (from `^0.10.11`, in `dependencies`) diff --git a/.changeset/@graphql-tools_stitch-1611-dependencies.md b/.changeset/@graphql-tools_stitch-1611-dependencies.md new file mode 100644 index 000000000..50e09878d --- /dev/null +++ b/.changeset/@graphql-tools_stitch-1611-dependencies.md @@ -0,0 +1,10 @@ +--- +'@graphql-tools/stitch': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/executor@^1.4.11` ↗︎](https://www.npmjs.com/package/@graphql-tools/executor/v/1.4.11) (from `^1.4.10`, in `dependencies`) +- Updated dependency [`@graphql-tools/merge@^9.1.3` ↗︎](https://www.npmjs.com/package/@graphql-tools/merge/v/9.1.3) (from `^9.1.2`, in `dependencies`) +- Updated dependency [`@graphql-tools/schema@^10.0.27` ↗︎](https://www.npmjs.com/package/@graphql-tools/schema/v/10.0.27) (from `^10.0.26`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-tools_stitching-directives-1611-dependencies.md b/.changeset/@graphql-tools_stitching-directives-1611-dependencies.md new file mode 100644 index 000000000..1e873705f --- /dev/null +++ b/.changeset/@graphql-tools_stitching-directives-1611-dependencies.md @@ -0,0 +1,7 @@ +--- +'@graphql-tools/stitching-directives': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/@graphql-tools_wrap-1611-dependencies.md b/.changeset/@graphql-tools_wrap-1611-dependencies.md new file mode 100644 index 000000000..ea5fdc86f --- /dev/null +++ b/.changeset/@graphql-tools_wrap-1611-dependencies.md @@ -0,0 +1,8 @@ +--- +'@graphql-tools/wrap': patch +--- + +dependencies updates: + +- Updated dependency [`@graphql-tools/schema@^10.0.27` ↗︎](https://www.npmjs.com/package/@graphql-tools/schema/v/10.0.27) (from `^10.0.26`, in `dependencies`) +- Updated dependency [`@graphql-tools/utils@^10.10.1` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.10.1) (from `^10.10.0`, in `dependencies`) diff --git a/.changeset/thirty-wasps-design.md b/.changeset/thirty-wasps-design.md new file mode 100644 index 000000000..a0b698adf --- /dev/null +++ b/.changeset/thirty-wasps-design.md @@ -0,0 +1,5 @@ +--- +'@graphql-hive/plugin-opentelemetry': minor +--- + +It is now possible to fully configure the OpenTelemetry setup when using `hiveTracingSetup`. You can now provide a `resource` and a `samplingRate` (among other options). diff --git a/e2e/opentelemetry/opentelemetry.e2e.ts b/e2e/opentelemetry/opentelemetry.e2e.ts index 344b69665..723224273 100644 --- a/e2e/opentelemetry/opentelemetry.e2e.ts +++ b/e2e/opentelemetry/opentelemetry.e2e.ts @@ -253,7 +253,7 @@ describe('OpenTelemetry', () => { const { execute } = await gateway({ supergraph, env: { - DISABLED_OPENTELEMETRY_SETUP: '1', + DISABLE_OPENTELEMETRY_SETUP: '1', OTEL_SERVICE_NAME: serviceName, OTEL_SERVICE_VERSION: '1.0.0', }, diff --git a/packages/gateway/src/commands/handleOpenTelemetryCLIOpts.ts b/packages/gateway/src/commands/handleOpenTelemetryCLIOpts.ts index a1851d6b2..2e96ebfe8 100644 --- a/packages/gateway/src/commands/handleOpenTelemetryCLIOpts.ts +++ b/packages/gateway/src/commands/handleOpenTelemetryCLIOpts.ts @@ -1,4 +1,3 @@ -import { fakePromise } from '@graphql-tools/utils'; import { BatchSpanProcessor, SpanProcessor, @@ -31,108 +30,119 @@ export async function handleOpenTelemetryCLIOpts( 'Initializing OpenTelemetry SDK', ); - return fakePromise().then(async () => { - const { openTelemetrySetup, HiveTracingSpanProcessor } = await import( - '@graphql-hive/plugin-opentelemetry/setup' - ); - const processors: SpanProcessor[] = []; - - const logAttributes = { - traceEndpoints: [] as { - url: string | null; - type?: string; - target?: string; - }[], - contextManager: false, + const { openTelemetrySetup, HiveTracingSpanProcessor } = await import( + '@graphql-hive/plugin-opentelemetry/setup' + ); + const processors: SpanProcessor[] = []; + + const logAttributes = { + traceEndpoints: [] as { + url: string | null; + type?: string; + target?: string; + }[], + contextManager: false, + }; + + let integration: { name: string; source: { flag: string; env: string } }; + + if (openTelemetry) { + const otelEndpoint = + typeof openTelemetry === 'string' + ? openTelemetry + : getEnvStr('OTEL_EXPORTER_OTLP_ENDPOINT'); + + log.debug({ exporterType, otelEndpoint }, 'Setting up OTLP Exporter'); + + integration = { + name: 'OpenTelemetry', + source: { flag: '--opentelemetry', env: 'OPENTELEMETRY' }, }; - let integrationName: string; + logAttributes.traceEndpoints.push({ + url: otelEndpoint ?? null, + type: exporterType, + }); - if (openTelemetry) { - const otelEndpoint = - typeof openTelemetry === 'string' - ? openTelemetry - : getEnvStr('OTEL_EXPORTER_OTLP_ENDPOINT'); + log.debug({ type: exporterType }, 'Loading OpenTelemetry exporter'); - log.debug({ exporterType, otelEndpoint }, 'Setting up OTLP Exporter'); + const { OTLPTraceExporter } = await import( + `@opentelemetry/exporter-trace-${exporterType}` + ); - integrationName = 'OpenTelemetry'; - logAttributes.traceEndpoints.push({ - url: otelEndpoint ?? null, - type: exporterType, - }); + processors.push( + new BatchSpanProcessor(new OTLPTraceExporter({ url: otelEndpoint })), + ); + } - log.debug({ type: exporterType }, 'Loading OpenTelemetry exporter'); + if (accessToken) { + log.debug({ target, traceEndpoint }, 'Setting up Hive Tracing'); - const { OTLPTraceExporter } = await import( - `@opentelemetry/exporter-trace-${exporterType}` - ); - - processors.push( - new BatchSpanProcessor(new OTLPTraceExporter({ url: otelEndpoint })), + integration ??= { + name: 'Hive Tracing', + source: { + flag: '--hive-trace-access-token', + env: 'HIVE_TRACE_ACCESS_TOKEN', + }, + }; + if (!target) { + ctx.log.error( + 'Hive tracing needs a target. Please provide it through "--hive-target "', ); + process.exit(1); } - if (accessToken) { - log.debug({ target, traceEndpoint }, 'Setting up Hive Tracing'); - - integrationName ??= 'Hive Tracing'; - if (!target) { - ctx.log.error( - 'Hive tracing needs a target. Please provide it through "--hive-target "', - ); - process.exit(1); - } + logAttributes.traceEndpoints.push({ + url: traceEndpoint, + type: 'hive tracing', + target, + }); - logAttributes.traceEndpoints.push({ - url: traceEndpoint, - type: 'hive tracing', + processors.push( + new HiveTracingSpanProcessor({ + accessToken, target, - }); - - processors.push( - new HiveTracingSpanProcessor({ - accessToken, - target, - endpoint: traceEndpoint, - }), - ); - } - - log.debug('Trying to load AsyncLocalStorage based Context Manager'); - - const contextManager = await import('@opentelemetry/context-async-hooks') - .then((module) => { - logAttributes.contextManager = true; - return new module.AsyncLocalStorageContextManager(); - }) - .catch(() => null); - - openTelemetrySetup({ - log, - traces: { processors }, - resource: await detectResource().catch((err) => { - if ( - err && - typeof err === 'object' && - 'code' in err && - err.code === 'ERR_MODULE_NOT_FOUND' - ) { - ctx.log.warn( - err, - `NodeJS modules necessary for environment detection is missing, please install it to auto-detect the environment`, - ); - return undefined; - } - throw err; + endpoint: traceEndpoint, }), - contextManager, - }); - - log.info(logAttributes, `${integrationName!} integration is enabled`); - - return true; + ); + } + + log.debug('Trying to load AsyncLocalStorage based Context Manager'); + + const contextManager = await import('@opentelemetry/context-async-hooks') + .then((module) => { + logAttributes.contextManager = true; + return new module.AsyncLocalStorageContextManager(); + }) + .catch(() => null); + + openTelemetrySetup({ + log, + traces: { processors }, + resource: await detectResource().catch((err) => { + if ( + err && + typeof err === 'object' && + 'code' in err && + err.code === 'ERR_MODULE_NOT_FOUND' + ) { + ctx.log.warn( + err, + `NodeJS modules necessary for environment detection is missing, please install it to auto-detect the environment`, + ); + return undefined; + } + throw err; + }), + contextManager, + _initialization: { + name: integration!.name, + source: `cli flag (${integration!.source.flag}) or environment variables (${integration!.source.env})`, + logAttributes, + }, }); + + return true; } return false; diff --git a/packages/plugins/opentelemetry/src/setup.ts b/packages/plugins/opentelemetry/src/setup.ts index c39a6421b..833c108a1 100644 --- a/packages/plugins/opentelemetry/src/setup.ts +++ b/packages/plugins/opentelemetry/src/setup.ts @@ -120,54 +120,77 @@ type SamplingOptions = samplingRate?: number; }; -type OpentelemetrySetupOptions = TracingOptions & - SamplingOptions & { - /** - * The Resource that will be used to create the Trace Provider. - * Can be either a Resource instance, or an simple object with service name and version - */ - resource?: Resource | { serviceName: string; serviceVersion: string }; - /** - * The Context Manager to be used to track OTEL Context. - * If possible, use `AsyncLocalStorageContextManager` from `@opentelemetry/context-async-hooks`. - */ - contextManager: ContextManager | null; - /** - * A custom list of propagators that will replace the default ones (Trace Context and Baggage) - */ - propagators?: TextMapPropagator[]; - /** - * The general limits of OTEL attributes. - */ - generalLimits?: GeneralLimits; - /** - * The Logger to be used by this utility. - * A child of this logger will be used for OTEL diag API, unless `configureDiagLogger` is false - */ - log?: Logger; - /** - * Configure Opentelemetry `diag` API to use Gateway's logger. - * - * @default true - * - * Note: Logger configuration respects OTEL environment variables standard. - * This means that the logger will be enabled only if `OTEL_LOG_LEVEL` variable is set. - */ - configureDiagLogger?: boolean; - }; +type BaseOptions = { + /** + * The Resource that will be used to create the Trace Provider. + * Can be either a Resource instance, or an simple object with service name and version + */ + resource?: Resource | { serviceName: string; serviceVersion: string }; + /** + * The Context Manager to be used to track OTEL Context. + * If possible, use `AsyncLocalStorageContextManager` from `@opentelemetry/context-async-hooks`. + */ + contextManager: ContextManager | null; + /** + * A custom list of propagators that will replace the default ones (Trace Context and Baggage) + */ + propagators?: TextMapPropagator[]; + /** + * The general limits of OTEL attributes. + */ + generalLimits?: GeneralLimits; + /** + * The Logger to be used by this utility. + * A child of this logger will be used for OTEL diag API, unless `configureDiagLogger` is false + */ + log?: Logger; + /** + * Configure Opentelemetry `diag` API to use Gateway's logger. + * + * @default true + * + * Note: Logger configuration respects OTEL environment variables standard. + * This means that the logger will be enabled only if `OTEL_LOG_LEVEL` variable is set. + */ + configureDiagLogger?: boolean; + + /** @internal */ + _initialization?: typeof initialized & { logAttributes: Attributes }; +}; + +type OpentelemetrySetupOptions = TracingOptions & SamplingOptions & BaseOptions; +let initialized: false | { name: string; source: string } = false; export function openTelemetrySetup(options: OpentelemetrySetupOptions) { const log = options.log || new Logger(); + if (initialized) { + log.error( + `${initialized.name} integration has already been initialized by ${initialized.source}`, + ); + throw new Error( + `${initialized.name} integration already initialized. See previous logs for more information`, + ); + } + + initialized = options._initialization || { + name: 'OpenTelemetry', + source: `\`openTelemetrySetup\` utility function call ${getStackTrace()}`, + }; + if (getEnvBool('OTEL_SDK_DISABLED')) { log.warn( - 'OpenTelemetry integration is disabled because `OTEL_SDK_DISABLED` environment variable is truthy', + `${initialized.name} integration is disabled because \`OTEL_SDK_DISABLED\` environment variable is truthy`, ); return; } - const logAttributes: Attributes = { registrationResults: {} }; - let logMessage = 'OpenTelemetry integration is enabled'; + const logAttributes: Attributes = { + ...options._initialization?.logAttributes, + registrationResults: {}, + }; + + let logMessage = `${initialized.name} integration is enabled`; if (options.configureDiagLogger !== false) { // If the log level is not explicitly set, we use VERBOSE to let Hive Logger log level feature filter logs accordingly. @@ -221,26 +244,21 @@ export function openTelemetrySetup(options: OpentelemetrySetupOptions) { logAttributes['console'] = true; } - const baseResource = resourceFromAttributes({ - [ATTR_SERVICE_NAME]: - options.resource && 'serviceName' in options.resource - ? options.resource?.serviceName - : getEnvStr('OTEL_SERVICE_NAME') || - '@graphql-hive/plugin-opentelemetry', - [ATTR_SERVICE_VERSION]: - options.resource && 'serviceVersion' in options.resource - ? options.resource?.serviceVersion - : getEnvStr('OTEL_SERVICE_VERSION') || - globalThis.__OTEL_PLUGIN_VERSION__ || - 'unknown', - ['hive.gateway.version']: globalThis.__VERSION__, - ['hive.otel.version']: globalThis.__OTEL_PLUGIN_VERSION__ || 'unknown', - }); - - const resource = - options.resource && !('serviceName' in options.resource) - ? baseResource.merge(options.resource) - : baseResource; + const resource = createResource( + resourceFromAttributes({ + [ATTR_SERVICE_NAME]: + getEnvStr('OTEL_SERVICE_NAME') || + '@graphql-hive/plugin-opentelemetry', + [ATTR_SERVICE_VERSION]: + getEnvStr('OTEL_SERVICE_VERSION') || + globalThis.__OTEL_PLUGIN_VERSION__ || + 'unknown', + ['hive.gateway.version']: globalThis.__VERSION__, + ['hive.otel.version']: + globalThis.__OTEL_PLUGIN_VERSION__ || 'unknown', + }), + options.resource, + ); logAttributes['resource'] = resource.attributes; logAttributes['sampling'] = options.sampler @@ -300,51 +318,69 @@ export type HiveTracingOptions = { target?: string } & ( } ); -export function hiveTracingSetup( - config: HiveTracingOptions & { - contextManager: ContextManager | null; - log?: Logger; - }, -) { - const log = config.log || new Logger(); - config.target ??= getEnvStr('HIVE_TARGET'); +export type HiveTracingSetupOptions = BaseOptions & + HiveTracingOptions & + SamplingOptions & + TracerOptions; - if (!config.target) { +export function hiveTracingSetup(options: HiveTracingSetupOptions) { + const log = options.log || new Logger(); + options.target ??= getEnvStr('HIVE_TARGET'); + + if (!options.target) { throw new Error( 'You must specify the Hive Registry `target`. Either provide `target` option or `HIVE_TARGET` environment variable.', ); } - const logAttributes: Attributes = { target: config.target }; + const logAttributes: Attributes = { + ...options._initialization?.logAttributes, + target: options.target, + }; - if (!config.processor) { - config.accessToken ??= + if (!options.processor) { + options.accessToken ??= getEnvStr('HIVE_TRACING_ACCESS_TOKEN') ?? getEnvStr('HIVE_ACCESS_TOKEN'); - if (!config.accessToken) { + if (!options.accessToken) { throw new Error( 'You must specify the Hive Registry `accessToken`. Either provide `accessToken` option or `HIVE_ACCESS_TOKEN`/`HIVE_TRACE_ACCESS_TOKEN` environment variable.', ); } - logAttributes['endpoint'] = config.endpoint; - logAttributes['batching'] = config.batching; + logAttributes['endpoint'] = options.endpoint; + logAttributes['batching'] = options.batching; } openTelemetrySetup({ + ...options, log, - contextManager: config.contextManager, - resource: resourceFromAttributes({ - 'hive.target_id': config.target, - }), + resource: createResource( + resourceFromAttributes({ + 'hive.target_id': options.target, + [ATTR_SERVICE_NAME]: getEnvStr('OTEL_SERVICE_NAME') || 'hive-gateway', + [ATTR_SERVICE_VERSION]: + getEnvStr('OTEL_SERVICE_VERSION') || + globalThis.__OTEL_PLUGIN_VERSION__ || + 'unknown', + }), + options.resource, + ), traces: { processors: [ - new HiveTracingSpanProcessor(config as HiveTracingSpanProcessorOptions), + new HiveTracingSpanProcessor( + options as HiveTracingSpanProcessorOptions, + ), ], + spanLimits: options.spanLimits, + console: options.console, + }, + _initialization: options._initialization || { + name: 'Hive Tracing', + source: `\`hiveTracingSetup\` utility function call ${getStackTrace()}`, + logAttributes, }, }); - - log.info(logAttributes, 'Hive Tracing integration has been enabled'); } export type BatchingConfig = boolean | BufferConfig; @@ -363,3 +399,41 @@ function resolveBatchingConfig( return new BatchSpanProcessor(exporter, value); } } + +function createResource( + baseResource: Resource, + userResource?: OpentelemetrySetupOptions['resource'], +): Resource { + if (!userResource) { + return baseResource; + } + + if ('serviceName' in userResource) { + return baseResource.merge( + resourceFromAttributes({ + [ATTR_SERVICE_NAME]: userResource.serviceName, + [ATTR_SERVICE_VERSION]: userResource.serviceVersion, + }), + ); + } + + return baseResource.merge(userResource); +} + +/** + * Returns the call site of the calling function and the upper stack trace. + */ +function getStackTrace(): string { + // slice(3) to remove the error message + getStackTrace() call + calling function call + return (new Error().stack ?? '').split('\n').slice(3).join('\n').trim(); +} + +/** + * Reset OpenTelemetry setup by disabling `trace`, `context` and `propagation` OpenTelemetry APIs. + */ +export function disable() { + trace.disable(); + context.disable(); + propagation.disable(); + initialized = false; +} diff --git a/packages/plugins/opentelemetry/tests/utils.ts b/packages/plugins/opentelemetry/tests/utils.ts index d4c8dd3a3..73f77d1ec 100644 --- a/packages/plugins/opentelemetry/tests/utils.ts +++ b/packages/plugins/opentelemetry/tests/utils.ts @@ -32,6 +32,7 @@ import { createSchema, createYoga, type GraphQLParams } from 'graphql-yoga'; import { expect } from 'vitest'; import { hive } from '../src/api'; import type { OpenTelemetryGatewayPluginOptions } from '../src/plugin'; +import * as otelSetup from '../src/setup'; export async function buildTestGateway( options: { @@ -332,6 +333,7 @@ export const disableAll = () => { diag.disable(); logs.disable(); hive.disable(); + otelSetup.disable(); }; export class MockLogRecordExporter implements LogRecordExporter {