apollo.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. var {
  2. _optionalChain
  3. } = require('@sentry/utils');
  4. Object.defineProperty(exports, '__esModule', { value: true });
  5. const utils = require('@sentry/utils');
  6. const debugBuild = require('../../common/debug-build.js');
  7. const nodeUtils = require('./utils/node-utils.js');
  8. /** Tracing integration for Apollo */
  9. class Apollo {
  10. /**
  11. * @inheritDoc
  12. */
  13. static __initStatic() {this.id = 'Apollo';}
  14. /**
  15. * @inheritDoc
  16. */
  17. /**
  18. * @inheritDoc
  19. */
  20. constructor(
  21. options = {
  22. useNestjs: false,
  23. },
  24. ) {
  25. this.name = Apollo.id;
  26. this._useNest = !!options.useNestjs;
  27. }
  28. /** @inheritdoc */
  29. loadDependency() {
  30. if (this._useNest) {
  31. this._module = this._module || utils.loadModule('@nestjs/graphql');
  32. } else {
  33. this._module = this._module || utils.loadModule('apollo-server-core');
  34. }
  35. return this._module;
  36. }
  37. /**
  38. * @inheritDoc
  39. */
  40. setupOnce(_, getCurrentHub) {
  41. if (nodeUtils.shouldDisableAutoInstrumentation(getCurrentHub)) {
  42. debugBuild.DEBUG_BUILD && utils.logger.log('Apollo Integration is skipped because of instrumenter configuration.');
  43. return;
  44. }
  45. if (this._useNest) {
  46. const pkg = this.loadDependency();
  47. if (!pkg) {
  48. debugBuild.DEBUG_BUILD && utils.logger.error('Apollo-NestJS Integration was unable to require @nestjs/graphql package.');
  49. return;
  50. }
  51. /**
  52. * Iterate over resolvers of NestJS ResolversExplorerService before schemas are constructed.
  53. */
  54. utils.fill(
  55. pkg.GraphQLFactory.prototype,
  56. 'mergeWithSchema',
  57. function (orig) {
  58. return function (
  59. ...args
  60. ) {
  61. utils.fill(this.resolversExplorerService, 'explore', function (orig) {
  62. return function () {
  63. const resolvers = utils.arrayify(orig.call(this));
  64. const instrumentedResolvers = instrumentResolvers(resolvers, getCurrentHub);
  65. return instrumentedResolvers;
  66. };
  67. });
  68. return orig.call(this, ...args);
  69. };
  70. },
  71. );
  72. } else {
  73. const pkg = this.loadDependency();
  74. if (!pkg) {
  75. debugBuild.DEBUG_BUILD && utils.logger.error('Apollo Integration was unable to require apollo-server-core package.');
  76. return;
  77. }
  78. /**
  79. * Iterate over resolvers of the ApolloServer instance before schemas are constructed.
  80. */
  81. utils.fill(pkg.ApolloServerBase.prototype, 'constructSchema', function (orig) {
  82. return function (
  83. ) {
  84. if (!this.config.resolvers) {
  85. if (debugBuild.DEBUG_BUILD) {
  86. if (this.config.schema) {
  87. utils.logger.warn(
  88. 'Apollo integration is not able to trace `ApolloServer` instances constructed via `schema` property.' +
  89. 'If you are using NestJS with Apollo, please use `Sentry.Integrations.Apollo({ useNestjs: true })` instead.',
  90. );
  91. utils.logger.warn();
  92. } else if (this.config.modules) {
  93. utils.logger.warn(
  94. 'Apollo integration is not able to trace `ApolloServer` instances constructed via `modules` property.',
  95. );
  96. }
  97. utils.logger.error('Skipping tracing as no resolvers found on the `ApolloServer` instance.');
  98. }
  99. return orig.call(this);
  100. }
  101. const resolvers = utils.arrayify(this.config.resolvers);
  102. this.config.resolvers = instrumentResolvers(resolvers, getCurrentHub);
  103. return orig.call(this);
  104. };
  105. });
  106. }
  107. }
  108. }Apollo.__initStatic();
  109. function instrumentResolvers(resolvers, getCurrentHub) {
  110. return resolvers.map(model => {
  111. Object.keys(model).forEach(resolverGroupName => {
  112. Object.keys(model[resolverGroupName]).forEach(resolverName => {
  113. if (typeof model[resolverGroupName][resolverName] !== 'function') {
  114. return;
  115. }
  116. wrapResolver(model, resolverGroupName, resolverName, getCurrentHub);
  117. });
  118. });
  119. return model;
  120. });
  121. }
  122. /**
  123. * Wrap a single resolver which can be a parent of other resolvers and/or db operations.
  124. */
  125. function wrapResolver(
  126. model,
  127. resolverGroupName,
  128. resolverName,
  129. getCurrentHub,
  130. ) {
  131. utils.fill(model[resolverGroupName], resolverName, function (orig) {
  132. return function ( ...args) {
  133. // eslint-disable-next-line deprecation/deprecation
  134. const scope = getCurrentHub().getScope();
  135. // eslint-disable-next-line deprecation/deprecation
  136. const parentSpan = scope.getSpan();
  137. // eslint-disable-next-line deprecation/deprecation
  138. const span = _optionalChain([parentSpan, 'optionalAccess', _2 => _2.startChild, 'call', _3 => _3({
  139. description: `${resolverGroupName}.${resolverName}`,
  140. op: 'graphql.resolve',
  141. origin: 'auto.graphql.apollo',
  142. })]);
  143. const rv = orig.call(this, ...args);
  144. if (utils.isThenable(rv)) {
  145. return rv.then((res) => {
  146. _optionalChain([span, 'optionalAccess', _4 => _4.end, 'call', _5 => _5()]);
  147. return res;
  148. });
  149. }
  150. _optionalChain([span, 'optionalAccess', _6 => _6.end, 'call', _7 => _7()]);
  151. return rv;
  152. };
  153. });
  154. }
  155. exports.Apollo = Apollo;
  156. //# sourceMappingURL=apollo.js.map