nestjs.tsx 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. import ExternalLink from 'sentry/components/links/externalLink';
  2. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  3. import type {
  4. Docs,
  5. DocsParams,
  6. OnboardingConfig,
  7. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  8. import {getUploadSourceMapsStep} from 'sentry/components/onboarding/gettingStartedDoc/utils';
  9. import {
  10. getCrashReportApiIntroduction,
  11. getCrashReportInstallDescription,
  12. getCrashReportJavaScriptInstallStep,
  13. getCrashReportModalConfigDescription,
  14. getCrashReportModalIntroduction,
  15. } from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
  16. import {getJSServerMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
  17. import {t, tct} from 'sentry/locale';
  18. import {
  19. getImportInstrumentSnippet,
  20. getInstallConfig,
  21. getSdkInitSnippet,
  22. } from 'sentry/utils/gettingStartedDocs/node';
  23. type Params = DocsParams;
  24. const getSdkSetupSnippet = () => `
  25. ${getImportInstrumentSnippet('esm', 'ts')}
  26. // All other imports below
  27. import { NestFactory } from '@nestjs/core';
  28. import { AppModule } from './app.module';
  29. async function bootstrap() {
  30. const app = await NestFactory.create(AppModule);
  31. await app.listen(3000);
  32. }
  33. bootstrap();
  34. `;
  35. const getAppModuleSnippet = () => `
  36. import { Module } from '@nestjs/common';
  37. import { SentryModule } from '@sentry/nestjs/setup';
  38. import { AppController } from './app.controller';
  39. import { AppService } from './app.service';
  40. @Module({
  41. imports: [
  42. SentryModule.forRoot(),
  43. // ...other modules
  44. ],
  45. controllers: [AppController],
  46. providers: [AppService],
  47. })
  48. export class AppModule {}
  49. `;
  50. const getVerifySnippet = () => `
  51. @Get("/debug-sentry")
  52. getError() {
  53. throw new Error("My first Sentry error!");
  54. }
  55. `;
  56. const getDecoratedGlobalFilter =
  57. () => `import { Catch, ExceptionFilter } from '@nestjs/common';
  58. import { WithSentry } from '@sentry/nestjs';
  59. @Catch()
  60. export class YourCatchAllExceptionFilter implements ExceptionFilter {
  61. @WithSentry()
  62. catch(exception, host): void {
  63. // your implementation here
  64. }
  65. }
  66. `;
  67. const getAppModuleSnippetWithSentryGlobalFilter =
  68. () => `import { Module } from '@nestjs/common';
  69. import { APP_FILTER } from '@nestjs/core';
  70. import { SentryGlobalFilter } from '@sentry/nestjs/setup';
  71. @Module({
  72. providers: [
  73. {
  74. provide: APP_FILTER,
  75. useClass: SentryGlobalFilter,
  76. },
  77. // ..other providers
  78. ],
  79. })
  80. export class AppModule {}
  81. `;
  82. const onboarding: OnboardingConfig = {
  83. introduction: () =>
  84. tct('In this quick guide you’ll use [strong:npm] or [strong:yarn] to set up:', {
  85. strong: <strong />,
  86. }),
  87. install: params => [
  88. {
  89. type: StepType.INSTALL,
  90. description: t('Add the Sentry NestJS SDK as a dependency:'),
  91. configurations: getInstallConfig(params, {
  92. basePackage: '@sentry/nestjs',
  93. }),
  94. },
  95. ],
  96. configure: params => [
  97. {
  98. type: StepType.CONFIGURE,
  99. description: t(
  100. "Initialize Sentry as early as possible in your application's lifecycle."
  101. ),
  102. configurations: [
  103. {
  104. description: tct(
  105. 'To initialize the SDK before everything else, create a file called [code:instrument.ts] in your [code:src/] folder.',
  106. {code: <code />}
  107. ),
  108. code: [
  109. {
  110. label: 'TypeScript',
  111. value: 'javascript',
  112. language: 'javascript',
  113. filename: 'instrument.ts',
  114. code: getSdkInitSnippet(params, 'nestjs', 'esm'),
  115. },
  116. ],
  117. },
  118. {
  119. description: tct(
  120. 'Make sure to import [code:instrument.ts] at the top of your [code:main.ts] file:',
  121. {
  122. code: <code />,
  123. docs: (
  124. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/nestjs/install/" />
  125. ),
  126. }
  127. ),
  128. code: [
  129. {
  130. label: 'TypeScript',
  131. value: 'javascript',
  132. language: 'javascript',
  133. filename: 'main.ts',
  134. code: getSdkSetupSnippet(),
  135. },
  136. ],
  137. },
  138. {
  139. description: tct(
  140. 'Add the [code:SentryModule] as a root module to your main module:',
  141. {
  142. code: <code />,
  143. docs: (
  144. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/nestjs/install/" />
  145. ),
  146. }
  147. ),
  148. code: [
  149. {
  150. label: 'TypeScript',
  151. value: 'javascript',
  152. language: 'javascript',
  153. filename: 'app.module.ts',
  154. code: getAppModuleSnippet(),
  155. },
  156. ],
  157. },
  158. {
  159. description: tct(
  160. 'If you are using a global catch-all exception filter add a [code:@WithSentry()] decorator to the [code:catch()] method of this global error filter. This will report all unhandled errors to Sentry',
  161. {
  162. code: <code />,
  163. }
  164. ),
  165. code: [
  166. {
  167. label: 'TypeScript',
  168. value: 'javascript',
  169. language: 'javascript',
  170. filename: 'global.filter.ts',
  171. code: getDecoratedGlobalFilter(),
  172. },
  173. ],
  174. },
  175. {
  176. description: tct(
  177. 'Alternatively, add the [code:SentryGlobalFilter] (or [code:SentryGlobalGraphQLFilter] if you are using GraphQL) before any other exception filters to the providers of your main module.',
  178. {
  179. code: <code />,
  180. }
  181. ),
  182. code: [
  183. {
  184. label: 'TypeScript',
  185. value: 'javascript',
  186. language: 'javascript',
  187. filename: 'app.module.ts',
  188. code: getAppModuleSnippetWithSentryGlobalFilter(),
  189. },
  190. ],
  191. },
  192. ],
  193. },
  194. getUploadSourceMapsStep({
  195. guideLink: 'https://docs.sentry.io/platforms/javascript/guides/nestjs/sourcemaps/',
  196. ...params,
  197. }),
  198. ],
  199. verify: () => [
  200. {
  201. type: StepType.VERIFY,
  202. description: t(
  203. "This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected."
  204. ),
  205. configurations: [
  206. {
  207. language: 'javascript',
  208. code: getVerifySnippet(),
  209. },
  210. ],
  211. },
  212. ],
  213. };
  214. const feedbackOnboardingNode: OnboardingConfig = {
  215. introduction: () => getCrashReportApiIntroduction(),
  216. install: () => [
  217. {
  218. type: StepType.INSTALL,
  219. description: getCrashReportInstallDescription(),
  220. configurations: [
  221. {
  222. code: [
  223. {
  224. label: 'TypeScript',
  225. value: 'javascript',
  226. language: 'javascript',
  227. code: `import * as Sentry from "@sentry/node";
  228. const eventId = Sentry.captureMessage("User Feedback");
  229. // OR: const eventId = Sentry.lastEventId();
  230. const userFeedback = {
  231. event_id: eventId,
  232. name: "John Doe",
  233. email: "john@doe.com",
  234. comments: "I really like your App, thanks!",
  235. };
  236. Sentry.captureUserFeedback(userFeedback);
  237. `,
  238. },
  239. ],
  240. },
  241. ],
  242. },
  243. ],
  244. configure: () => [],
  245. verify: () => [],
  246. nextSteps: () => [],
  247. };
  248. const crashReportOnboarding: OnboardingConfig = {
  249. introduction: () => getCrashReportModalIntroduction(),
  250. install: (params: Params) => getCrashReportJavaScriptInstallStep(params),
  251. configure: () => [
  252. {
  253. type: StepType.CONFIGURE,
  254. description: getCrashReportModalConfigDescription({
  255. link: 'https://docs.sentry.io/platforms/javascript/guides/nestjs/user-feedback/configuration/#crash-report-modal',
  256. }),
  257. },
  258. ],
  259. verify: () => [],
  260. nextSteps: () => [],
  261. };
  262. const profilingOnboarding: OnboardingConfig = {
  263. ...onboarding,
  264. introduction: () => null,
  265. };
  266. const docs: Docs = {
  267. onboarding,
  268. feedbackOnboardingCrashApi: feedbackOnboardingNode,
  269. customMetricsOnboarding: getJSServerMetricsOnboarding(),
  270. crashReportOnboarding,
  271. profilingOnboarding,
  272. };
  273. export default docs;