sdk.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. import { _optionalChain } from '@sentry/utils';
  2. import { inboundFiltersIntegration, functionToStringIntegration, linkedErrorsIntegration, requestDataIntegration, getMainCarrier, getIntegrationsToSetup, initAndBind, getClient, startSession, getIsolationScope, endSession, getCurrentScope } from '@sentry/core';
  3. import { createStackParser, nodeStackLineParser, stackParserFromStackParserOptions, GLOBAL_OBJ, propagationContextFromHeaders } from '@sentry/utils';
  4. import { setNodeAsyncContextStrategy } from './async/index.js';
  5. import { NodeClient } from './client.js';
  6. import { consoleIntegration } from './integrations/console.js';
  7. import { nodeContextIntegration } from './integrations/context.js';
  8. import { contextLinesIntegration } from './integrations/contextlines.js';
  9. import { httpIntegration } from './integrations/http.js';
  10. import { localVariablesIntegration } from './integrations/local-variables/index.js';
  11. import { modulesIntegration } from './integrations/modules.js';
  12. import { onUncaughtExceptionIntegration } from './integrations/onuncaughtexception.js';
  13. import { onUnhandledRejectionIntegration } from './integrations/onunhandledrejection.js';
  14. import { spotlightIntegration } from './integrations/spotlight.js';
  15. import { nativeNodeFetchintegration } from './integrations/undici/index.js';
  16. import { createGetModuleFromFilename } from './module.js';
  17. import { makeNodeTransport } from './transports/http.js';
  18. /* eslint-disable max-lines */
  19. /** @deprecated Use `getDefaultIntegrations(options)` instead. */
  20. const defaultIntegrations = [
  21. // Common
  22. inboundFiltersIntegration(),
  23. functionToStringIntegration(),
  24. linkedErrorsIntegration(),
  25. requestDataIntegration(),
  26. // Native Wrappers
  27. consoleIntegration(),
  28. httpIntegration(),
  29. nativeNodeFetchintegration(),
  30. // Global Handlers
  31. onUncaughtExceptionIntegration(),
  32. onUnhandledRejectionIntegration(),
  33. // Event Info
  34. contextLinesIntegration(),
  35. localVariablesIntegration(),
  36. nodeContextIntegration(),
  37. modulesIntegration(),
  38. ];
  39. /** Get the default integrations for the Node SDK. */
  40. function getDefaultIntegrations(_options) {
  41. const carrier = getMainCarrier();
  42. const autoloadedIntegrations = _optionalChain([carrier, 'access', _ => _.__SENTRY__, 'optionalAccess', _2 => _2.integrations]) || [];
  43. return [
  44. // eslint-disable-next-line deprecation/deprecation
  45. ...defaultIntegrations,
  46. ...autoloadedIntegrations,
  47. ];
  48. }
  49. /**
  50. * The Sentry Node SDK Client.
  51. *
  52. * To use this SDK, call the {@link init} function as early as possible in the
  53. * main entry module. To set context information or send manual events, use the
  54. * provided methods.
  55. *
  56. * @example
  57. * ```
  58. *
  59. * const { init } = require('@sentry/node');
  60. *
  61. * init({
  62. * dsn: '__DSN__',
  63. * // ...
  64. * });
  65. * ```
  66. *
  67. * @example
  68. * ```
  69. *
  70. * const { configureScope } = require('@sentry/node');
  71. * configureScope((scope: Scope) => {
  72. * scope.setExtra({ battery: 0.7 });
  73. * scope.setTag({ user_mode: 'admin' });
  74. * scope.setUser({ id: '4711' });
  75. * });
  76. * ```
  77. *
  78. * @example
  79. * ```
  80. *
  81. * const { addBreadcrumb } = require('@sentry/node');
  82. * addBreadcrumb({
  83. * message: 'My Breadcrumb',
  84. * // ...
  85. * });
  86. * ```
  87. *
  88. * @example
  89. * ```
  90. *
  91. * const Sentry = require('@sentry/node');
  92. * Sentry.captureMessage('Hello, world!');
  93. * Sentry.captureException(new Error('Good bye'));
  94. * Sentry.captureEvent({
  95. * message: 'Manual',
  96. * stacktrace: [
  97. * // ...
  98. * ],
  99. * });
  100. * ```
  101. *
  102. * @see {@link NodeOptions} for documentation on configuration options.
  103. */
  104. // eslint-disable-next-line complexity
  105. function init(options = {}) {
  106. setNodeAsyncContextStrategy();
  107. if (options.defaultIntegrations === undefined) {
  108. options.defaultIntegrations = getDefaultIntegrations();
  109. }
  110. if (options.dsn === undefined && process.env.SENTRY_DSN) {
  111. options.dsn = process.env.SENTRY_DSN;
  112. }
  113. const sentryTracesSampleRate = process.env.SENTRY_TRACES_SAMPLE_RATE;
  114. if (options.tracesSampleRate === undefined && sentryTracesSampleRate) {
  115. const tracesSampleRate = parseFloat(sentryTracesSampleRate);
  116. if (isFinite(tracesSampleRate)) {
  117. options.tracesSampleRate = tracesSampleRate;
  118. }
  119. }
  120. if (options.release === undefined) {
  121. const detectedRelease = getSentryRelease();
  122. if (detectedRelease !== undefined) {
  123. options.release = detectedRelease;
  124. } else {
  125. // If release is not provided, then we should disable autoSessionTracking
  126. options.autoSessionTracking = false;
  127. }
  128. }
  129. if (options.environment === undefined && process.env.SENTRY_ENVIRONMENT) {
  130. options.environment = process.env.SENTRY_ENVIRONMENT;
  131. }
  132. if (options.autoSessionTracking === undefined && options.dsn !== undefined) {
  133. options.autoSessionTracking = true;
  134. }
  135. if (options.instrumenter === undefined) {
  136. options.instrumenter = 'sentry';
  137. }
  138. // TODO(v7): Refactor this to reduce the logic above
  139. const clientOptions = {
  140. ...options,
  141. stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),
  142. integrations: getIntegrationsToSetup(options),
  143. transport: options.transport || makeNodeTransport,
  144. };
  145. initAndBind(options.clientClass || NodeClient, clientOptions);
  146. if (options.autoSessionTracking) {
  147. startSessionTracking();
  148. }
  149. updateScopeFromEnvVariables();
  150. if (options.spotlight) {
  151. const client = getClient();
  152. if (client && client.addIntegration) {
  153. // force integrations to be setup even if no DSN was set
  154. // If they have already been added before, they will be ignored anyhow
  155. const integrations = client.getOptions().integrations;
  156. for (const integration of integrations) {
  157. client.addIntegration(integration);
  158. }
  159. client.addIntegration(
  160. spotlightIntegration({ sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined }),
  161. );
  162. }
  163. }
  164. }
  165. /**
  166. * Function that takes an instance of NodeClient and checks if autoSessionTracking option is enabled for that client
  167. */
  168. function isAutoSessionTrackingEnabled(client) {
  169. if (client === undefined) {
  170. return false;
  171. }
  172. const clientOptions = client && client.getOptions();
  173. if (clientOptions && clientOptions.autoSessionTracking !== undefined) {
  174. return clientOptions.autoSessionTracking;
  175. }
  176. return false;
  177. }
  178. /**
  179. * Returns a release dynamically from environment variables.
  180. */
  181. function getSentryRelease(fallback) {
  182. // Always read first as Sentry takes this as precedence
  183. if (process.env.SENTRY_RELEASE) {
  184. return process.env.SENTRY_RELEASE;
  185. }
  186. // This supports the variable that sentry-webpack-plugin injects
  187. if (GLOBAL_OBJ.SENTRY_RELEASE && GLOBAL_OBJ.SENTRY_RELEASE.id) {
  188. return GLOBAL_OBJ.SENTRY_RELEASE.id;
  189. }
  190. return (
  191. // GitHub Actions - https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables
  192. process.env.GITHUB_SHA ||
  193. // Netlify - https://docs.netlify.com/configure-builds/environment-variables/#build-metadata
  194. process.env.COMMIT_REF ||
  195. // Vercel - https://vercel.com/docs/v2/build-step#system-environment-variables
  196. process.env.VERCEL_GIT_COMMIT_SHA ||
  197. process.env.VERCEL_GITHUB_COMMIT_SHA ||
  198. process.env.VERCEL_GITLAB_COMMIT_SHA ||
  199. process.env.VERCEL_BITBUCKET_COMMIT_SHA ||
  200. // Zeit (now known as Vercel)
  201. process.env.ZEIT_GITHUB_COMMIT_SHA ||
  202. process.env.ZEIT_GITLAB_COMMIT_SHA ||
  203. process.env.ZEIT_BITBUCKET_COMMIT_SHA ||
  204. // Cloudflare Pages - https://developers.cloudflare.com/pages/platform/build-configuration/#environment-variables
  205. process.env.CF_PAGES_COMMIT_SHA ||
  206. fallback
  207. );
  208. }
  209. /** Node.js stack parser */
  210. const defaultStackParser = createStackParser(nodeStackLineParser(createGetModuleFromFilename()));
  211. /**
  212. * Enable automatic Session Tracking for the node process.
  213. */
  214. function startSessionTracking() {
  215. startSession();
  216. // Emitted in the case of healthy sessions, error of `mechanism.handled: true` and unhandledrejections because
  217. // The 'beforeExit' event is not emitted for conditions causing explicit termination,
  218. // such as calling process.exit() or uncaught exceptions.
  219. // Ref: https://nodejs.org/api/process.html#process_event_beforeexit
  220. process.on('beforeExit', () => {
  221. const session = getIsolationScope().getSession();
  222. const terminalStates = ['exited', 'crashed'];
  223. // Only call endSession, if the Session exists on Scope and SessionStatus is not a
  224. // Terminal Status i.e. Exited or Crashed because
  225. // "When a session is moved away from ok it must not be updated anymore."
  226. // Ref: https://develop.sentry.dev/sdk/sessions/
  227. if (session && !terminalStates.includes(session.status)) {
  228. endSession();
  229. }
  230. });
  231. }
  232. /**
  233. * Update scope and propagation context based on environmental variables.
  234. *
  235. * See https://github.com/getsentry/rfcs/blob/main/text/0071-continue-trace-over-process-boundaries.md
  236. * for more details.
  237. */
  238. function updateScopeFromEnvVariables() {
  239. const sentryUseEnvironment = (process.env.SENTRY_USE_ENVIRONMENT || '').toLowerCase();
  240. if (!['false', 'n', 'no', 'off', '0'].includes(sentryUseEnvironment)) {
  241. const sentryTraceEnv = process.env.SENTRY_TRACE;
  242. const baggageEnv = process.env.SENTRY_BAGGAGE;
  243. const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv);
  244. getCurrentScope().setPropagationContext(propagationContext);
  245. }
  246. }
  247. export { defaultIntegrations, defaultStackParser, getDefaultIntegrations, getSentryRelease, init, isAutoSessionTrackingEnabled };
  248. //# sourceMappingURL=sdk.js.map