@graphql-hive/gateway 2.0.0-next-d56e4a16201542cdbc486c0feb6d482a2a1a57a0 → 2.0.0-next-357c4246368d3cc93e4bd2d3df6e8a8f016491cd

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,6 +16,7 @@ var node_fs = require('node:fs');
16
16
  var node_http = require('node:http');
17
17
  var node_https = require('node:https');
18
18
  var utils$1 = require('@graphql-tools/utils');
19
+ var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
19
20
  var codeFileLoader = require('@graphql-tools/code-file-loader');
20
21
  var graphqlFileLoader = require('@graphql-tools/graphql-file-loader');
21
22
  var load = require('@graphql-tools/load');
@@ -25,6 +26,34 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
25
26
  var cluster__default = /*#__PURE__*/_interopDefault(cluster);
26
27
  var module__default = /*#__PURE__*/_interopDefault(module$1);
27
28
 
29
+ function getEnvStr(key, opts = {}) {
30
+ const globalThat = opts.globalThis ?? globalThis;
31
+ let variable = globalThat.process?.env?.[key] || // @ts-expect-error can exist in wrangler and maybe other runtimes
32
+ globalThat.env?.[key] || // @ts-expect-error can exist in deno
33
+ globalThat.Deno?.env?.get(key) || // @ts-expect-error could be
34
+ globalThat[key];
35
+ if (variable != null) {
36
+ variable += "";
37
+ } else {
38
+ variable = void 0;
39
+ }
40
+ return variable?.trim();
41
+ }
42
+ function getEnvBool(key, opts = {}) {
43
+ return strToBool(getEnvStr(key, opts));
44
+ }
45
+ function getNodeEnv(opts = {}) {
46
+ return getEnvStr("NODE_ENV", opts);
47
+ }
48
+ function strToBool(str) {
49
+ return ["1", "t", "true", "y", "yes", "on", "enabled"].includes(
50
+ (str || "").toLowerCase()
51
+ );
52
+ }
53
+ function isDebug() {
54
+ return getEnvBool("DEBUG");
55
+ }
56
+
28
57
  const unit = Object.create(null);
29
58
  const m = 60000, h = m * 60, d = h * 24, y = d * 365.25;
30
59
 
@@ -492,11 +521,83 @@ function handleFork(log, config) {
492
521
  return false;
493
522
  }
494
523
 
524
+ async function handleOpenTelemetryConfig(ctx, cliOpts) {
525
+ const accessToken = cliOpts.hiveTraceAccessToken;
526
+ const traceEndpoint = cliOpts.hiveTraceEndpoint;
527
+ const target = cliOpts.hiveTarget;
528
+ const openTelemetry = cliOpts.openTelemetry;
529
+ const exporterType = cliOpts.openTelemetryExporterType ?? "otlp-http";
530
+ const log = ctx.log.child("[OpenTelemetry] ");
531
+ if (openTelemetry || accessToken) {
532
+ log.debug(
533
+ { openTelemetry, exporterType, target, traceEndpoint },
534
+ "Initializing OpenTelemetry SDK"
535
+ );
536
+ return utils$1.fakePromise().then(async () => {
537
+ const { openTelemetrySetup, HiveTracingSpanProcessor, getEnvVar } = await import('@graphql-mesh/plugin-opentelemetry/setup');
538
+ const processors = [];
539
+ const logAttributes = {
540
+ traceEndpoints: [],
541
+ contextManager: false
542
+ };
543
+ let integrationName;
544
+ if (openTelemetry) {
545
+ const otelEndpoint = typeof openTelemetry === "string" ? openTelemetry : getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT", void 0);
546
+ log.debug({ exporterType, otelEndpoint }, "Setting up OTLP Exporter");
547
+ integrationName = "OpenTelemetry";
548
+ logAttributes.traceEndpoints.push({
549
+ url: otelEndpoint ?? null,
550
+ type: exporterType
551
+ });
552
+ log.debug({ type: exporterType }, "Loading OpenTelemetry exporter");
553
+ const { OTLPTraceExporter } = await import(`@opentelemetry/exporter-trace-${exporterType}`);
554
+ processors.push(
555
+ new sdkTraceBase.BatchSpanProcessor(new OTLPTraceExporter({ url: otelEndpoint }))
556
+ );
557
+ }
558
+ if (accessToken) {
559
+ log.debug({ target, traceEndpoint }, "Setting up Hive Tracing");
560
+ integrationName ??= "Hive Tracing";
561
+ if (!target) {
562
+ ctx.log.error(
563
+ 'Hive tracing needs a target. Please provide it through "--hive-target <target>"'
564
+ );
565
+ process.exit(1);
566
+ }
567
+ logAttributes.traceEndpoints.push({
568
+ url: traceEndpoint,
569
+ type: "hive tracing",
570
+ target
571
+ });
572
+ processors.push(
573
+ new HiveTracingSpanProcessor({
574
+ accessToken,
575
+ target,
576
+ endpoint: traceEndpoint
577
+ })
578
+ );
579
+ }
580
+ log.debug("Trying to load AsyncLocalStorage based Context Manager");
581
+ const contextManager = await import('@opentelemetry/context-async-hooks').then((module) => {
582
+ logAttributes.contextManager = true;
583
+ return new module.AsyncLocalStorageContextManager();
584
+ }).catch(() => null);
585
+ openTelemetrySetup({
586
+ traces: { processors },
587
+ contextManager
588
+ });
589
+ log.info(logAttributes, `${integrationName} integration is enabled`);
590
+ return true;
591
+ });
592
+ }
593
+ return false;
594
+ }
595
+
495
596
  function handleReportingConfig(ctx, loadedConfig, cliOpts) {
496
597
  const confOpts = {
497
598
  ...loadedConfig.reporting?.type === "hive" ? {
498
599
  hiveRegistryToken: loadedConfig.reporting.token,
499
- hiveUsageTarget: loadedConfig.reporting.target,
600
+ hiveTarget: loadedConfig.reporting.target,
500
601
  hiveUsageAccessToken: loadedConfig.reporting.token
501
602
  } : {},
502
603
  ...loadedConfig.reporting?.type === "graphos" ? {
@@ -504,32 +605,45 @@ function handleReportingConfig(ctx, loadedConfig, cliOpts) {
504
605
  apolloKey: loadedConfig.reporting.apiKey
505
606
  } : {}
506
607
  };
507
- const opts = { ...confOpts, ...cliOpts };
608
+ const opts = {
609
+ ...confOpts,
610
+ ...cliOpts,
611
+ hiveTarget: (
612
+ // cli arguments always take precedence over config
613
+ confOpts.hiveTarget ?? cliOpts.hiveTarget ?? cliOpts.hiveUsageTarget
614
+ )
615
+ };
508
616
  if (cliOpts.hiveRegistryToken && cliOpts.hiveUsageAccessToken) {
509
617
  ctx.log.error(
510
618
  'Cannot use "--hive-registry-token" with "--hive-usage-access-token". Please use "--hive-usage-target" and "--hive-usage-access-token" or the config instead.'
511
619
  );
512
620
  process.exit(1);
513
621
  }
514
- if (cliOpts.hiveRegistryToken && opts.hiveUsageTarget) {
622
+ if (cliOpts.hiveUsageTarget && cliOpts.hiveTarget) {
623
+ ctx.log.error(
624
+ 'Cannot use "--hive-usage-target" with "--hive-target". Please only use "--hive-target"'
625
+ );
626
+ process.exit(1);
627
+ }
628
+ if (cliOpts.hiveRegistryToken && opts.hiveTarget) {
515
629
  ctx.log.error(
516
630
  'Cannot use "--hive-registry-token" with a target. Please use "--hive-usage-target" and "--hive-usage-access-token" or the config instead.'
517
631
  );
518
632
  process.exit(1);
519
633
  }
520
- if (opts.hiveUsageTarget && !opts.hiveUsageAccessToken) {
634
+ if (opts.hiveTarget && !opts.hiveAccessToken && !opts.hiveUsageAccessToken && !opts.hiveTraceAccessToken) {
521
635
  ctx.log.error(
522
- 'Hive usage target needs an access token. Please provide it through the "--hive-usage-access-token <token>" option or the config.'
636
+ 'Hive usage target needs an access token. Please provide it through "--hive-access-token <token>", or specific "--hive-usage-access-token <token>" and "--hive-trace-access-token" options, or the config.'
523
637
  );
524
638
  process.exit(1);
525
639
  }
526
- if (opts.hiveUsageAccessToken && !opts.hiveUsageTarget) {
640
+ if ((opts.hiveAccessToken || opts.hiveUsageAccessToken || opts.hiveTraceAccessToken) && !opts.hiveTarget) {
527
641
  ctx.log.error(
528
- 'Hive usage access token needs a target. Please provide it through the "--hive-usage-target <target>" option or the config.'
642
+ 'Hive access token needs a target. Please provide it through the "--hive-target <target>" option or the config.'
529
643
  );
530
644
  process.exit(1);
531
645
  }
532
- const hiveUsageAccessToken = opts.hiveUsageAccessToken || opts.hiveRegistryToken;
646
+ const hiveUsageAccessToken = opts.hiveAccessToken || opts.hiveUsageAccessToken || opts.hiveRegistryToken;
533
647
  if (hiveUsageAccessToken) {
534
648
  if (opts.hiveUsageTarget) {
535
649
  ctx.log.info("Configuring Hive usage reporting");
@@ -540,7 +654,7 @@ function handleReportingConfig(ctx, loadedConfig, cliOpts) {
540
654
  ...loadedConfig.reporting,
541
655
  type: "hive",
542
656
  token: hiveUsageAccessToken,
543
- target: opts.hiveUsageTarget
657
+ target: opts.hiveTarget
544
658
  };
545
659
  }
546
660
  if (opts.apolloKey) {
@@ -568,17 +682,30 @@ const addCommand$2 = (ctx, cli) => cli.command("proxy").description(
568
682
  "path to the GraphQL schema file or a url from where to pull the schema"
569
683
  ).action(async function proxy(endpoint) {
570
684
  const {
685
+ opentelemetry,
686
+ opentelemetryExporterType,
571
687
  hiveCdnEndpoint,
572
688
  hiveCdnKey,
573
689
  hiveRegistryToken,
690
+ hiveTarget,
574
691
  hiveUsageTarget,
692
+ hiveAccessToken,
575
693
  hiveUsageAccessToken,
694
+ hiveTraceAccessToken,
695
+ hiveTraceEndpoint,
576
696
  maskedErrors,
577
697
  hivePersistedDocumentsEndpoint,
578
698
  hivePersistedDocumentsToken,
579
699
  ...opts
580
700
  } = this.optsWithGlobals();
581
701
  ctx.log.info(`Starting ${ctx.productName} ${ctx.version} in proxy mode`);
702
+ const openTelemetryEnabledByCLI = await handleOpenTelemetryConfig(ctx, {
703
+ openTelemetry: opentelemetry,
704
+ openTelemetryExporterType: opentelemetryExporterType,
705
+ hiveTarget,
706
+ hiveTraceAccessToken,
707
+ hiveTraceEndpoint
708
+ });
582
709
  const loadedConfig = await loadConfig({
583
710
  log: ctx.log,
584
711
  configPath: opts.configPath,
@@ -632,8 +759,11 @@ const addCommand$2 = (ctx, cli) => cli.command("proxy").description(
632
759
  const registryConfig = {};
633
760
  const reporting = handleReportingConfig(ctx, loadedConfig, {
634
761
  hiveRegistryToken,
762
+ hiveTarget,
635
763
  hiveUsageTarget,
764
+ hiveAccessToken,
636
765
  hiveUsageAccessToken,
766
+ hiveTraceAccessToken,
637
767
  // proxy can only do reporting to hive registry
638
768
  apolloGraphRef: void 0,
639
769
  apolloKey: void 0
@@ -654,7 +784,8 @@ const addCommand$2 = (ctx, cli) => cli.command("proxy").description(
654
784
  const builtinPlugins = await getBuiltinPluginsFromConfig(
655
785
  {
656
786
  ...loadedConfig,
657
- ...opts
787
+ ...opts,
788
+ openTelemetry: openTelemetryEnabledByCLI ? { ...loadedConfig.openTelemetry, traces: true } : loadedConfig.openTelemetry
658
789
  },
659
790
  {
660
791
  log: ctx.log,
@@ -729,15 +860,28 @@ const addCommand$1 = (ctx, cli) => cli.command("subgraph").description(
729
860
  'path to the subgraph schema file or a url from where to pull the subgraph schema (default: "subgraph.graphql")'
730
861
  ).action(async function subgraph(schemaPathOrUrl) {
731
862
  const {
863
+ opentelemetry,
864
+ opentelemetryExporterType,
732
865
  maskedErrors,
733
866
  hiveRegistryToken,
867
+ hiveTarget,
734
868
  hiveUsageTarget,
869
+ hiveAccessToken,
735
870
  hiveUsageAccessToken,
871
+ hiveTraceAccessToken,
872
+ hiveTraceEndpoint,
736
873
  hivePersistedDocumentsEndpoint,
737
874
  hivePersistedDocumentsToken,
738
875
  ...opts
739
876
  } = this.optsWithGlobals();
740
877
  ctx.log.info(`Starting ${ctx.productName} ${ctx.version} as subgraph`);
878
+ const openTelemetryEnabledByCLI = await handleOpenTelemetryConfig(ctx, {
879
+ openTelemetry: opentelemetry,
880
+ openTelemetryExporterType: opentelemetryExporterType,
881
+ hiveTarget,
882
+ hiveTraceAccessToken,
883
+ hiveTraceEndpoint
884
+ });
741
885
  const loadedConfig = await loadConfig({
742
886
  log: ctx.log,
743
887
  configPath: opts.configPath,
@@ -753,8 +897,11 @@ const addCommand$1 = (ctx, cli) => cli.command("subgraph").description(
753
897
  const registryConfig = {};
754
898
  const reporting = handleReportingConfig(ctx, loadedConfig, {
755
899
  hiveRegistryToken,
900
+ hiveTarget,
756
901
  hiveUsageTarget,
902
+ hiveAccessToken,
757
903
  hiveUsageAccessToken,
904
+ hiveTraceAccessToken,
758
905
  // subgraph can only do reporting to hive registry
759
906
  apolloGraphRef: void 0,
760
907
  apolloKey: void 0
@@ -775,7 +922,8 @@ const addCommand$1 = (ctx, cli) => cli.command("subgraph").description(
775
922
  const builtinPlugins = await getBuiltinPluginsFromConfig(
776
923
  {
777
924
  ...loadedConfig,
778
- ...opts
925
+ ...opts,
926
+ openTelemetry: openTelemetryEnabledByCLI ? { ...loadedConfig.openTelemetry, traces: true } : loadedConfig.openTelemetry
779
927
  },
780
928
  {
781
929
  log: ctx.log,
@@ -869,11 +1017,17 @@ const addCommand = (ctx, cli) => cli.command("supergraph").description(
869
1017
  ).env("APOLLO_SCHEMA_CONFIG_DELIVERY_ENDPOINT")
870
1018
  ).action(async function supergraph(schemaPathOrUrl) {
871
1019
  const {
1020
+ opentelemetry,
1021
+ opentelemetryExporterType,
872
1022
  hiveCdnEndpoint,
873
1023
  hiveCdnKey,
874
1024
  hiveRegistryToken,
875
1025
  hiveUsageTarget,
1026
+ hiveTarget,
1027
+ hiveAccessToken,
876
1028
  hiveUsageAccessToken,
1029
+ hiveTraceAccessToken,
1030
+ hiveTraceEndpoint,
877
1031
  maskedErrors,
878
1032
  apolloGraphRef,
879
1033
  apolloKey,
@@ -885,6 +1039,13 @@ const addCommand = (ctx, cli) => cli.command("supergraph").description(
885
1039
  ctx.log.info(
886
1040
  `Starting ${ctx.productName} ${ctx.version} with supergraph`
887
1041
  );
1042
+ const openTelemetryEnabledByCLI = await handleOpenTelemetryConfig(ctx, {
1043
+ openTelemetry: opentelemetry,
1044
+ openTelemetryExporterType: opentelemetryExporterType,
1045
+ hiveTarget,
1046
+ hiveTraceAccessToken,
1047
+ hiveTraceEndpoint
1048
+ });
888
1049
  const loadedConfig = await loadConfig({
889
1050
  log: ctx.log,
890
1051
  configPath: opts.configPath,
@@ -970,6 +1131,9 @@ const addCommand = (ctx, cli) => cli.command("supergraph").description(
970
1131
  }
971
1132
  const registryConfig = {};
972
1133
  const reporting = handleReportingConfig(ctx, loadedConfig, {
1134
+ hiveTarget,
1135
+ hiveAccessToken,
1136
+ hiveTraceAccessToken,
973
1137
  hiveRegistryToken,
974
1138
  hiveUsageTarget,
975
1139
  hiveUsageAccessToken,
@@ -992,7 +1156,8 @@ const addCommand = (ctx, cli) => cli.command("supergraph").description(
992
1156
  const builtinPlugins = await getBuiltinPluginsFromConfig(
993
1157
  {
994
1158
  ...loadedConfig,
995
- ...opts
1159
+ ...opts,
1160
+ openTelemetry: openTelemetryEnabledByCLI ? { ...loadedConfig.openTelemetry, traces: true } : loadedConfig.openTelemetry
996
1161
  },
997
1162
  {
998
1163
  log: ctx.log,
@@ -1044,7 +1209,7 @@ const addCommand = (ctx, cli) => cli.command("supergraph").description(
1044
1209
  process.exit(1);
1045
1210
  }
1046
1211
  return runSupergraph(ctx, config);
1047
- }).allowUnknownOption(process.env["NODE_ENV"] === "test").allowExcessArguments(process.env["NODE_ENV"] === "test");
1212
+ }).allowUnknownOption(getNodeEnv() === "test").allowExcessArguments(getNodeEnv() === "test");
1048
1213
  async function runSupergraph({ log }, config) {
1049
1214
  let absSchemaPath = null;
1050
1215
  if (typeof config.supergraph === "string" && utils$1.isValidPath(config.supergraph) && !utils.isUrl(config.supergraph)) {
@@ -1242,27 +1407,57 @@ let cli = new extraTypings.Command().configureHelp({
1242
1407
  // see here https://github.com/tj/commander.js/blob/970ecae402b253de691e6a9066fea22f38fe7431/lib/command.js#L655
1243
1408
  // @ts-expect-error
1244
1409
  null
1410
+ ).addOption(
1411
+ new extraTypings.Option(
1412
+ "--opentelemetry [exporter-endpoint]",
1413
+ `Enable OpenTelemetry integration with an exporter using this option's value as endpoint. By default, it uses OTLP HTTP, use "--opentelemetry-exporter-type" to change the default.`
1414
+ ).env("OPENTELEMETRY")
1415
+ ).addOption(
1416
+ new extraTypings.Option(
1417
+ "--opentelemetry-exporter-type <type>",
1418
+ `OpenTelemetry exporter type to use when setting up OpenTelemetry integration. Requires "--opentelemetry" to set the endpoint.`
1419
+ ).choices(["otlp-http", "otlp-grpc"]).default("otlp-http").env("OPENTELEMETRY_EXPORTER_TYPE")
1245
1420
  ).addOption(
1246
1421
  new extraTypings.Option(
1247
1422
  "--hive-registry-token <token>",
1248
- '[DEPRECATED: please use "--hive-usage-target" and "--hive-usage-access-token"] Hive registry token for usage metrics reporting'
1423
+ '[DEPRECATED: please use "--hive-target" and "--hive-access-token"] Hive registry token for usage metrics reporting'
1249
1424
  ).env("HIVE_REGISTRY_TOKEN")
1250
1425
  ).addOption(
1251
1426
  new extraTypings.Option(
1252
1427
  "--hive-usage-target <target>",
1253
- 'Hive registry target to which the usage data should be reported to. requires the "--hive-usage-access-token <token>" option'
1428
+ "[DEPRECATED] please use --hive-target instead."
1254
1429
  ).env("HIVE_USAGE_TARGET")
1430
+ ).addOption(
1431
+ new extraTypings.Option(
1432
+ "--hive-target <target>",
1433
+ 'Hive registry target to which the usage and tracing data should be reported to. Requires either "--hive-access-token <token>", "--hive-usage-access-token <token>" or "--hive-trace-access-token" option'
1434
+ ).env("HIVE_TARGET")
1435
+ ).addOption(
1436
+ new extraTypings.Option(
1437
+ "--hive-access-token <token>",
1438
+ 'Hive registry access token for usage metrics reporting and tracing. Enables both usage reporting and tracing. Requires the "--hive-target <target>" option'
1439
+ ).env("HIVE_ACCESS_TOKEN")
1255
1440
  ).addOption(
1256
1441
  new extraTypings.Option(
1257
1442
  "--hive-usage-access-token <token>",
1258
- 'Hive registry access token for usage metrics reporting. requires the "--hive-usage-target <target>" option'
1443
+ `Hive registry access token for usage reporting. Enables Hive usage report. Requires the "--hive-target <target>" option. It can't be used together with "--hive-access-token"`
1259
1444
  ).env("HIVE_USAGE_ACCESS_TOKEN")
1445
+ ).addOption(
1446
+ new extraTypings.Option(
1447
+ "--hive-trace-access-token <token>",
1448
+ `Hive registry access token for tracing. Enables Hive tracing. Requires the "--hive-target <target>" option. It can't be used together with "--hive-access-token"`
1449
+ ).env("HIVE_TRACE_ACCESS_TOKEN")
1450
+ ).addOption(
1451
+ new extraTypings.Option(
1452
+ "--hive-trace-endpoint <endpoint>",
1453
+ `Hive registry tracing endpoint.`
1454
+ ).env("HIVE_TRACE_ENDPOINT").default(`https://api.graphql-hive.com/otel/v1/traces`)
1260
1455
  ).option(
1261
1456
  "--hive-persisted-documents-endpoint <endpoint>",
1262
- '[EXPERIMENTAL] Hive CDN endpoint for fetching the persisted documents. requires the "--hive-persisted-documents-token <token>" option'
1457
+ '[EXPERIMENTAL] Hive CDN endpoint for fetching the persisted documents. Requires the "--hive-persisted-documents-token <token>" option'
1263
1458
  ).option(
1264
1459
  "--hive-persisted-documents-token <token>",
1265
- '[EXPERIMENTAL] Hive persisted documents CDN endpoint token. requires the "--hive-persisted-documents-endpoint <endpoint>" option'
1460
+ '[EXPERIMENTAL] Hive persisted documents CDN endpoint token. Requires the "--hive-persisted-documents-endpoint <endpoint>" option'
1266
1461
  ).addOption(
1267
1462
  new extraTypings.Option(
1268
1463
  "--hive-cdn-endpoint <endpoint>",
@@ -1286,9 +1481,11 @@ let cli = new extraTypings.Command().configureHelp({
1286
1481
  ).option("--disable-websockets", "Disable WebSockets support").addOption(
1287
1482
  new extraTypings.Option(
1288
1483
  "--jit",
1289
- "Enable Just-In-Time compilation of GraphQL documents"
1484
+ "Enable Just-In-Time compilation of GraphQL documents (env: JIT)"
1290
1485
  ).env("JIT")
1291
- );
1486
+ ).on("optionEnv:jit", function() {
1487
+ this.setOptionValueWithSource("jit", getEnvBool("JIT"), "env");
1488
+ });
1292
1489
  async function run(userCtx) {
1293
1490
  const ctx = {
1294
1491
  log: userCtx.log || new logger.Logger(),
@@ -1312,7 +1509,7 @@ async function run(userCtx) {
1312
1509
  function handleNodeWarnings() {
1313
1510
  const originalProcessEmitWarning = process.emitWarning.bind(process);
1314
1511
  process.emitWarning = function gatewayEmitWarning(warning, ...opts) {
1315
- if (["1", "y", "yes", "t", "true"].includes(String(process.env["DEBUG"]))) {
1512
+ if (isDebug()) {
1316
1513
  originalProcessEmitWarning(warning, ...opts);
1317
1514
  }
1318
1515
  };