quickStartEntries.tsx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
  1. import {Fragment} from 'react';
  2. import merge from 'lodash/merge';
  3. import {CodeSnippet} from 'sentry/components/codeSnippet';
  4. import ExternalLink from 'sentry/components/links/externalLink';
  5. import {t, tct} from 'sentry/locale';
  6. export interface QuickStartProps {
  7. dsnKey?: string;
  8. orgId?: string;
  9. orgSlug?: string;
  10. projectId?: string;
  11. publicKey?: string;
  12. slug?: string;
  13. }
  14. const VALUE_DEFAULTS = {
  15. dsnKey: '<my-dsn-key>',
  16. orgId: '<my-organziation-id>',
  17. orgSlug: '<my-organization-slug>',
  18. projectId: '<my-project-id>',
  19. publicKey: '<my-dsn-public-key>',
  20. slug: '<my-monitor-slug>',
  21. };
  22. function withDefaultProps(props: QuickStartProps): Required<QuickStartProps> {
  23. return merge(VALUE_DEFAULTS, props);
  24. }
  25. export function PythonCronQuickStart(props: QuickStartProps) {
  26. const {slug} = withDefaultProps(props);
  27. const code = `import sentry_sdk
  28. from sentry_sdk.crons import monitor
  29. # Add this decorator to instrument your python function
  30. @monitor(monitor_slug='${slug}')
  31. def tell_the_world(msg):
  32. print(msg)`;
  33. return (
  34. <Fragment>
  35. <div>
  36. {tct(
  37. '[installLink:Install and configure] the Sentry Python SDK (min v1.17.0), then instrument your monitor:',
  38. {
  39. installLink: <ExternalLink href="https://docs.sentry.io/platforms/python/" />,
  40. }
  41. )}
  42. </div>
  43. <CodeSnippet language="python">{code}</CodeSnippet>
  44. </Fragment>
  45. );
  46. }
  47. export function PythonCeleryCronQuickStart(props: QuickStartProps) {
  48. const {slug, dsnKey} = withDefaultProps(props);
  49. const setupCode = `import sentry_sdk
  50. from sentry_sdk.crons import monitor
  51. from sentry_sdk.integrations.celery import CeleryIntegration
  52. # @signals.celeryd_init.connect
  53. @signals.beat_init.connect
  54. def init_sentry(**kwargs):
  55. sentry_sdk.init(
  56. dsn='${dsnKey}',
  57. integrations=[CeleryIntegration()],
  58. )
  59. `;
  60. const linkTaskCode = `@app.task
  61. @monitor(monitor_slug='${slug}')
  62. def tell_the_world(msg):
  63. print(msg)
  64. `;
  65. return (
  66. <Fragment>
  67. <div>
  68. {tct(
  69. '[installLink:Install and configure] the Sentry Python SDK (min v1.17.0), then initialize Sentry either in [celerydInit:celeryd_init] or [beatInit:beat_init] signal:',
  70. {
  71. celerydInit: <code />,
  72. beatInit: <code />,
  73. installLink: (
  74. <ExternalLink href="https://docs.sentry.io/platforms/python/guides/celery/" />
  75. ),
  76. }
  77. )}
  78. </div>
  79. <CodeSnippet language="python">{setupCode}</CodeSnippet>
  80. <div>{t('Link your Celery task to your Monitor:')}</div>
  81. <CodeSnippet language="python">{linkTaskCode}</CodeSnippet>
  82. </Fragment>
  83. );
  84. }
  85. export function CLICronQuickStart(props: QuickStartProps) {
  86. const {slug, dsnKey} = withDefaultProps(props);
  87. const script = `# Example for a Python script:
  88. export SENTRY_DSN=${dsnKey}
  89. sentry-cli monitors run ${slug} -- python path/to/file`;
  90. return (
  91. <Fragment>
  92. <div>
  93. {tct(
  94. 'Make sure to [installLink:install the Sentry CLI] (min v2.16.1), then instrument your monitor:',
  95. {
  96. installLink: (
  97. <ExternalLink href="https://docs.sentry.io/product/cli/installation/" />
  98. ),
  99. }
  100. )}
  101. </div>
  102. <CodeSnippet language="bash">{script}</CodeSnippet>
  103. </Fragment>
  104. );
  105. }
  106. export function CurlCronQuickStart(props: QuickStartProps) {
  107. const {projectId, orgId, slug, publicKey} = withDefaultProps(props);
  108. const checkInSuccessCode = `SENTRY_INGEST="https://o${orgId}.ingest.sentry.io"
  109. SENTRY_CRONS="\${SENTRY_INGEST}/api/${projectId}/cron/${slug}/${publicKey}/"
  110. # 🟑 Notify Sentry your job is running:
  111. curl "\${SENTRY_CRONS}?status=in_progress"
  112. # Execute your scheduled task here...
  113. # 🟒 Notify Sentry your job has completed successfully:
  114. curl "\${SENTRY_CRONS}?status=ok"`;
  115. const checkInFailCode = `# πŸ”΄ Notify Sentry your job has failed:
  116. curl "\${SENTRY_CRONS}?status=error"`;
  117. return (
  118. <Fragment>
  119. <CodeSnippet language="bash">{checkInSuccessCode}</CodeSnippet>
  120. <div>{t('To notify Sentry if your job execution fails')}</div>
  121. <CodeSnippet language="bash">{checkInFailCode}</CodeSnippet>
  122. </Fragment>
  123. );
  124. }
  125. export function PHPCronQuickStart(props: QuickStartProps) {
  126. const {slug} = withDefaultProps(props);
  127. const checkInSuccessCode = `// 🟑 Notify Sentry your job is running:
  128. $event = Event::createCheckIn();
  129. $checkIn = new CheckIn(
  130. monitorSlug: '${slug}',
  131. status: CheckInStatus::inProgress(),
  132. );
  133. $event->setCheckIn($checkIn);
  134. SentrySdk::getCurrentHub()->captureEvent($event);
  135. // Execute your scheduled task here...
  136. // 🟒 Notify Sentry your job has completed successfully:
  137. $event = Event::createCheckIn();
  138. $event->setCheckIn(new CheckIn(
  139. id: $checkIn->getId(),
  140. monitorSlug: '${slug}',
  141. status: CheckInStatus::ok(),
  142. ));
  143. SentrySdk::getCurrentHub()->captureEvent($event);`;
  144. const checkInFailCode = `// πŸ”΄ Notify Sentry your job has failed:
  145. $event = Event::createCheckIn();
  146. $event->setCheckIn(new CheckIn(
  147. id: $checkIn->getId(),
  148. monitorSlug: '${slug}',
  149. status: CheckInStatus::error(),
  150. ));
  151. SentrySdk::getCurrentHub()->captureEvent($event);`;
  152. return (
  153. <Fragment>
  154. <div>
  155. {tct(
  156. '[installLink:Install and configure] the Sentry PHP SDK (min v3.16.0), then instrument your monitor:',
  157. {
  158. installLink: <ExternalLink href="https://docs.sentry.io/platforms/php/" />,
  159. }
  160. )}
  161. </div>
  162. <CodeSnippet language="php">{checkInSuccessCode}</CodeSnippet>
  163. <div>{t('To notify Sentry if your job execution fails')}</div>
  164. <CodeSnippet language="php">{checkInFailCode}</CodeSnippet>
  165. </Fragment>
  166. );
  167. }
  168. export function PHPLaravelCronQuickStart(props: QuickStartProps) {
  169. const {slug} = withDefaultProps(props);
  170. const code = `protected function schedule(Schedule $schedule)
  171. {
  172. $schedule->command('emails:send')
  173. ->everyHour()
  174. ->sentryMonitor('${slug}'); // add this line
  175. }`;
  176. return (
  177. <Fragment>
  178. <div>
  179. {tct(
  180. '[installLink:Install and configure] the Sentry PHP Laravel SDK (min v3.3.1), then add the [sentryMonitor:sentryMonitor()] call to your scheduled tasks defined in your [kernel:app/Console/Kernel.php] file:',
  181. {
  182. sentryMonitor: <code />,
  183. kernel: <code />,
  184. installLink: (
  185. <ExternalLink href="https://docs.sentry.io/platforms/php/guides/laravel/" />
  186. ),
  187. }
  188. )}
  189. </div>
  190. <CodeSnippet language="php">{code}</CodeSnippet>
  191. </Fragment>
  192. );
  193. }
  194. export function NodeJSCronQuickStart(props: QuickStartProps) {
  195. const {slug} = withDefaultProps(props);
  196. const checkInSuccessCode = `// 🟑 Notify Sentry your job is running:
  197. const checkInId = Sentry.captureCheckIn({
  198. monitorSlug: "${slug}",
  199. status: "in_progress",
  200. });
  201. // Execute your scheduled task here...
  202. // 🟒 Notify Sentry your job has completed successfully:
  203. Sentry.captureCheckIn({
  204. checkInId,
  205. monitorSlug: "${slug}",
  206. status: "ok",
  207. });`;
  208. const checkInFailCode = `// πŸ”΄ Notify Sentry your job has failed:
  209. Sentry.captureCheckIn({
  210. checkInId,
  211. monitorSlug: "${slug}",
  212. status: "error",
  213. });`;
  214. return (
  215. <Fragment>
  216. <div>
  217. {tct(
  218. '[installLink:Install and configure] the Sentry Node SDK (min v7.52), then instrument your monitor:',
  219. {
  220. installLink: <ExternalLink href="https://docs.sentry.io/platforms/node/" />,
  221. }
  222. )}
  223. </div>
  224. <CodeSnippet language="javascript">{checkInSuccessCode}</CodeSnippet>
  225. <div>{t('To notify Sentry if your job execution fails')}</div>
  226. <CodeSnippet language="javascript">{checkInFailCode}</CodeSnippet>
  227. </Fragment>
  228. );
  229. }
  230. export function GoCronQuickStart(props: QuickStartProps) {
  231. const {slug} = withDefaultProps(props);
  232. const checkInSuccessCode = `// 🟑 Notify Sentry your job is running:
  233. checkinId := sentry.CaptureCheckIn(
  234. &sentry.CheckIn{
  235. MonitorSlug: "${slug}",
  236. Status: sentry.CheckInStatusInProgress,
  237. },
  238. nil,
  239. )
  240. // Execute your scheduled task here...
  241. // 🟒 Notify Sentry your job has completed successfully:
  242. sentry.CaptureCheckIn(
  243. &sentry.CheckIn{
  244. ID: *checkinId,
  245. MonitorSlug: "${slug}",
  246. Status: sentry.CheckInStatusOK,
  247. },
  248. nil,
  249. )`;
  250. const checkInFailCode = `// πŸ”΄ Notify Sentry your job has failed:
  251. sentry.CaptureCheckIn(
  252. &sentry.CheckIn{
  253. ID: *checkinId,
  254. MonitorSlug: "${slug}",
  255. Status: sentry.CheckInStatusError,
  256. },
  257. nil,
  258. )`;
  259. return (
  260. <Fragment>
  261. <div>
  262. {tct(
  263. '[installLink:Install and configure] the Sentry Go SDK (min v0.23.0), then instrument your monitor:',
  264. {
  265. installLink: <ExternalLink href="https://docs.sentry.io/platforms/go/" />,
  266. }
  267. )}
  268. </div>
  269. <CodeSnippet language="go">{checkInSuccessCode}</CodeSnippet>
  270. <div>{t('To notify Sentry if your job execution fails')}</div>
  271. <CodeSnippet language="go">{checkInFailCode}</CodeSnippet>
  272. </Fragment>
  273. );
  274. }
  275. export function JavaCronQuickStart(props: QuickStartProps) {
  276. const {slug} = withDefaultProps(props);
  277. const checkInSuccessCode = `import io.sentry.util.CheckInUtils;
  278. String result = CheckInUtils.withCheckIn("${slug}", () -> {
  279. // Execute your scheduled task here...
  280. return "computed result";
  281. });`;
  282. return (
  283. <Fragment>
  284. <div>
  285. {tct(
  286. '[installLink:Install and configure] the Sentry Java SDK (min v6.30.0), then instrument your monitor:',
  287. {
  288. installLink: <ExternalLink href="https://docs.sentry.io/platforms/java/" />,
  289. }
  290. )}
  291. </div>
  292. <CodeSnippet language="java">{checkInSuccessCode}</CodeSnippet>
  293. </Fragment>
  294. );
  295. }
  296. export function JavaSpringBootCronQuickStart(props: QuickStartProps) {
  297. const {slug} = withDefaultProps(props);
  298. const code = `import io.sentry.spring.jakarta.checkin.SentryCheckIn;
  299. @Component
  300. public class CustomJob {
  301. @Scheduled(fixedRate = 3 * 60 * 1000L)
  302. @SentryCheckIn("${slug}") // πŸ‘ˆ
  303. void execute() throws InterruptedException {
  304. // your task code
  305. }
  306. }`;
  307. return (
  308. <Fragment>
  309. <div>
  310. {tct(
  311. '[installLink:Install and configure] the Sentry Spring Boot SDK (min v6.30.0), then instrument your monitor:',
  312. {
  313. installLink: (
  314. <ExternalLink href="https://docs.sentry.io/platforms/java/guides/spring-boot/" />
  315. ),
  316. }
  317. )}
  318. </div>
  319. <CodeSnippet language="java">{code}</CodeSnippet>
  320. </Fragment>
  321. );
  322. }
  323. export function JavaQuartzCronQuickStart(props: QuickStartProps) {
  324. const {slug} = withDefaultProps(props);
  325. const code = `import io.sentry.quartz.SentryJobListener;
  326. // you can set the monitor slug on the job detail
  327. JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
  328. jobDetailFactory.setJobDataAsMap(Collections.singletonMap(SentryJobListener.SENTRY_SLUG_KEY, "${slug}"));
  329. // you can also set the monitor slug on the trigger
  330. SimpleTriggerFactoryBean trigger = new SimpleTriggerFactoryBean();
  331. trigger.setJobDataAsMap(Collections.singletonMap(SENTRY_SLUG_KEY, "${slug}"));`;
  332. return (
  333. <Fragment>
  334. <div>
  335. {tct(
  336. '[installLink:Install and configure] the Sentry Java SDK (min v6.30.0), make sure `SentryJobListener` is [configureLink:configured], then instrument your monitor:',
  337. {
  338. installLink: <ExternalLink href="https://docs.sentry.io/platforms/java/" />,
  339. configureLink: (
  340. <ExternalLink href="https://docs.sentry.io/platforms/java/configuration/integrations/quartz/" />
  341. ),
  342. }
  343. )}
  344. </div>
  345. <CodeSnippet language="java">{code}</CodeSnippet>
  346. </Fragment>
  347. );
  348. }
  349. export function CeleryBeatAutoDiscovery(props: QuickStartProps) {
  350. const {dsnKey} = props;
  351. const code = `# tasks.py
  352. from celery import signals
  353. import sentry_sdk
  354. from sentry_sdk.integrations.celery import CeleryIntegration
  355. @signals.celeryd_init.connect
  356. def init_sentry(**kwargs):
  357. sentry_sdk.init(
  358. dsn='${dsnKey ?? '<PROJECT DSN>'}',
  359. integrations=[CeleryIntegration(monitor_beat_tasks=True)], # πŸ‘ˆ
  360. environment="local.dev.grace",
  361. release="v1.0",
  362. )
  363. `;
  364. return (
  365. <Fragment>
  366. <div>
  367. {tct(
  368. 'Use the [additionalDocs: Celery integration] to monitor your Celery periodic tasks. Initialize Sentry in the celeryd_init or beat_init signal.',
  369. {
  370. additionalDocs: (
  371. <ExternalLink href="https://docs.sentry.io/platforms/python/guides/celery/crons/#celery-beat-auto-discovery" />
  372. ),
  373. }
  374. )}
  375. </div>
  376. <div>{t('Make sure to set monitor_beat_tasks=True in CeleryIntegration:')}</div>
  377. <CodeSnippet language="python">{code}</CodeSnippet>
  378. </Fragment>
  379. );
  380. }
  381. export function PHPUpsertPlatformGuide() {
  382. const scheduleCode = `// Create a crontab schedule object (every 10 minutes)
  383. $monitorSchedule = \\Sentry\\MonitorSchedule::crontab('*/10 * * * *');
  384. // Or create an interval schedule object (every 10 minutes)
  385. $monitorSchedule = \\Sentry\\MonitorSchedule::interval(10, \\Sentry\\MonitorScheduleUnit::minute());`;
  386. const upsertCode = `// Create a config object
  387. $monitorConfig = new \\Sentry\\MonitorConfig(
  388. $monitorSchedule,
  389. checkinMargin: 5, // Optional check-in margin in minutes
  390. maxRuntime: 15, // Optional max runtime in minutes
  391. timezone: 'Europe/Vienna', // Optional timezone
  392. );
  393. // 🟑 Notify Sentry your job is running:
  394. $checkInId = \\Sentry\\captureCheckIn(
  395. slug: '<monitor-slug>',
  396. status: \\Sentry\\CheckInStatus::inProgress(),
  397. monitorConfig: $monitorConfig,
  398. );
  399. // Execute your scheduled task here...
  400. // 🟒 Notify Sentry your job has completed successfully:
  401. \\Sentry\\captureCheckIn(
  402. slug: '<monitor-slug>',
  403. status: \\Sentry\\CheckInStatus::inProgress(),
  404. checkInId: $checkInId,
  405. );`;
  406. return (
  407. <Fragment>
  408. <div>
  409. {tct(
  410. 'You can use the [additionalDocs: PHP SDK] to create and update your Monitors programmatically with code rather than creating them manually.',
  411. {
  412. additionalDocs: (
  413. <ExternalLink href="https://docs.sentry.io/platforms/php/crons/#upserting-cron-monitors" />
  414. ),
  415. }
  416. )}
  417. </div>
  418. <CodeSnippet language="php">{scheduleCode}</CodeSnippet>
  419. <CodeSnippet language="php">{upsertCode}</CodeSnippet>
  420. </Fragment>
  421. );
  422. }
  423. export function LaravelUpsertPlatformGuide() {
  424. const basicConfigCode = `protected function schedule(Schedule $schedule)
  425. {
  426. $schedule->command('emails:send')
  427. ->everyHour()
  428. ->sentryMonitor(); // add this line
  429. }`;
  430. const advancedConfigCode = `protected function schedule(Schedule $schedule)
  431. {
  432. $schedule->command('emails:send')
  433. ->everyHour()
  434. ->sentryMonitor(
  435. // Specify the slug of the job monitor in case of duplicate commands or if the monitor was created in the UI
  436. monitorSlug: null,
  437. // Check-in margin in minutes
  438. checkInMargin: 5,
  439. // Max runtime in minutes
  440. maxRuntime: 15,
  441. // In case you want to configure the job monitor exclusively in the UI, you can turn off sending the monitor config with the check-in.
  442. // Passing a monitor-slug is required in this case.
  443. updateMonitorConfig: false,
  444. )
  445. }`;
  446. return (
  447. <Fragment>
  448. <div>
  449. {tct('Use the [additionalDocs: Laravel SDK] to monitor your scheduled task.', {
  450. additionalDocs: (
  451. <ExternalLink href="https://docs.sentry.io/platforms/php/guides/laravel/crons/#job-monitoring" />
  452. ),
  453. })}
  454. </div>
  455. <div>
  456. {t(
  457. 'To set up, add the "sentryMonitor()" macro to your scheduled tasks defined in your "app/Console/Kernel.php" file:'
  458. )}
  459. </div>
  460. <CodeSnippet language="php">{basicConfigCode}</CodeSnippet>
  461. <div>
  462. {t(
  463. 'By default, the Laravel SDK will infer various parameters of your scheduled task. For greater control, we expose some optional parameters on the sentryMonitor() macro.'
  464. )}
  465. </div>
  466. <CodeSnippet language="php">{advancedConfigCode}</CodeSnippet>
  467. </Fragment>
  468. );
  469. }
  470. export function NodeJsUpsertPlatformGuide() {
  471. const upsertCode = `const checkInId = Sentry.captureCheckIn(
  472. {
  473. monitorSlug: '<monitor-slug>',
  474. status: 'in_progress',
  475. },
  476. {
  477. schedule: { // Specify your schedule options here
  478. type: 'crontab',
  479. value: '* * * * *',
  480. },
  481. checkinMargin: 1,
  482. maxRuntime: 1,
  483. timezone: 'America/Los_Angeles',
  484. });
  485. Sentry.captureCheckIn({
  486. checkInId,
  487. monitorSlug: '<monitor-slug>',
  488. status: 'ok',
  489. });
  490. `;
  491. return (
  492. <Fragment>
  493. <div>
  494. {tct(
  495. 'Use the [additionalDocs:Node SDK] to create and update your Monitors programmatically with code rather than creating them manually.',
  496. {
  497. additionalDocs: (
  498. <ExternalLink href="https://docs.sentry.io/platforms/node/crons/" />
  499. ),
  500. }
  501. )}
  502. </div>
  503. <CodeSnippet language="javascript">{upsertCode}</CodeSnippet>
  504. </Fragment>
  505. );
  506. }
  507. export function GoUpsertPlatformGuide() {
  508. const scheduleCode = `// Create a crontab schedule object (every 10 minutes)
  509. monitorSchedule := sentry.CrontabSchedule("*/10 * * * *")
  510. // Or create an interval schedule object (every 10 minutes)
  511. monitorSchedule := sentry.IntervalSchedule(10, sentry.MonitorScheduleUnitMinute)
  512. `;
  513. const upsertCode = `// Create a monitor config object
  514. monitorConfig := &sentry.MonitorConfig{
  515. Schedule: monitorSchedule,
  516. MaxRuntime: 2,
  517. CheckInMargin: 1,
  518. }
  519. // 🟑 Notify Sentry your job is running:
  520. checkinId := sentry.CaptureCheckIn(
  521. &sentry.CheckIn{
  522. MonitorSlug: "<monitor-slug>",
  523. Status: sentry.CheckInStatusInProgress,
  524. },
  525. monitorConfig,
  526. )
  527. // Execute your scheduled task here...
  528. // 🟒 Notify Sentry your job has completed successfully:
  529. sentry.CaptureCheckIn(
  530. &sentry.CheckIn{
  531. MonitorSlug: "<monitor-slug>",
  532. Status: sentry.CheckInStatusOK,
  533. },
  534. monitorConfig,
  535. )`;
  536. return (
  537. <Fragment>
  538. <div>
  539. {tct(
  540. 'You can use the [additionalDocs: Go SDK] to create and update your Monitors programmatically with code rather than creating them manually.',
  541. {
  542. additionalDocs: (
  543. <ExternalLink href="https://docs.sentry.io/platforms/go/crons/#upserting-cron-monitors" />
  544. ),
  545. }
  546. )}
  547. </div>
  548. <CodeSnippet language="go">{scheduleCode}</CodeSnippet>
  549. <CodeSnippet language="go">{upsertCode}</CodeSnippet>
  550. </Fragment>
  551. );
  552. }
  553. export function JavaUpsertPlatformGuide() {
  554. const scheduleCode = `import io.sentry.MonitorSchedule;
  555. import io.sentry.MonitorScheduleUnit;
  556. // Create a crontab schedule object (every 10 minutes)
  557. MonitorSchedule monitorSchedule = MonitorSchedule.crontab("*/10 * * * *");
  558. // Or create an interval schedule object (every 10 minutes)
  559. MonitorSchedule monitorSchedule = MonitorSchedule.interval(10, MonitorScheduleUnit.MINUTE);`;
  560. const upsertCode = `import io.sentry.MonitorConfig;
  561. import io.sentry.util.CheckInUtils;
  562. // Create a config object
  563. MonitorConfig monitorConfig = new MonitorConfig(monitorSchedule);
  564. monitorConfig.setTimezone("Europe/Vienna"); // Optional timezone
  565. monitorConfig.setCheckinMargin(5L); // Optional check-in margin in minutes
  566. monitorConfig.setMaxRuntime(15L); // Optional max runtime in minutes
  567. String result = CheckInUtils.withCheckIn("<monitor-slug>", monitorConfig, () -> {
  568. // Execute your scheduled task here...
  569. return "computed result";
  570. });`;
  571. return (
  572. <Fragment>
  573. <div>
  574. {tct(
  575. 'You can use the [additionalDocs: Java SDK] to create and update your Monitors programmatically with code rather than creating them manually.',
  576. {
  577. additionalDocs: (
  578. <ExternalLink href="https://docs.sentry.io/platforms/java/crons/#upserting-cron-monitors" />
  579. ),
  580. }
  581. )}
  582. </div>
  583. <CodeSnippet language="java">{scheduleCode}</CodeSnippet>
  584. <CodeSnippet language="java">{upsertCode}</CodeSnippet>
  585. </Fragment>
  586. );
  587. }
  588. export function RubyUpsertPlatformGuide() {
  589. const configCode = `# Create a config from a crontab schedule (every 10 minutes)
  590. monitor_config = Sentry::Cron::MonitorConfig.from_crontab(
  591. '5 * * * *',
  592. checkin_margin: 5, # Optional check-in margin in minutes
  593. max_runtime: 15, # Optional max runtime in minutes
  594. timezone: 'Europe/Vienna', # Optional timezone
  595. )
  596. # Create a config from an interval schedule (every 10 minutes)
  597. monitor_config = Sentry::Cron::MonitorConfig.from_interval(
  598. 10,
  599. :minute,
  600. checkin_margin: 5, # Optional check-in margin in minutes
  601. max_runtime: 15, # Optional max runtime in minutes
  602. timezone: 'Europe/Vienna', # Optional timezone
  603. )`;
  604. const upsertCode = `# 🟑 Notify Sentry your job is running:
  605. check_in_id = Sentry.capture_check_in(
  606. '<monitor-slug>',
  607. :in_progress,
  608. monitor_config: monitor_config
  609. )
  610. # Execute your scheduled task here...
  611. # 🟒 Notify Sentry your job has completed successfully:
  612. Sentry.capture_check_in(
  613. '<monitor-slug>',
  614. :ok,
  615. check_in_id: check_in_id,
  616. monitor_config: monitor_config
  617. )`;
  618. return (
  619. <Fragment>
  620. <div>
  621. {tct(
  622. 'You can use the [additionalDocs: Ruby SDK] to create and update your Monitors programmatically with code rather than creating them manually.',
  623. {
  624. additionalDocs: (
  625. <ExternalLink href="https://docs.sentry.io/platforms/ruby/crons/#upserting-cron-monitors" />
  626. ),
  627. }
  628. )}
  629. </div>
  630. <CodeSnippet language="ruby">{configCode}</CodeSnippet>
  631. <CodeSnippet language="ruby">{upsertCode}</CodeSnippet>
  632. </Fragment>
  633. );
  634. }
  635. export function RubyRailsMixinPlatformGuide() {
  636. const activeJobCode = `class ExampleActiveJob < ApplicationJob
  637. include Sentry::Cron::MonitorCheckIns
  638. # slug defaults to the job class name if not provided
  639. sentry_monitor_check_ins slug: 'custom', monitor_config: Sentry::Cron::MonitorConfig.from_crontab('5 * * * *')
  640. def perform(*args)
  641. # do stuff
  642. end
  643. end`;
  644. const sidekiqJobCode = `class ExampleSidekiqJob
  645. include Sidekiq::Job
  646. include Sentry::Cron::MonitorCheckIns
  647. # slug defaults to the job class name if not provided
  648. sentry_monitor_check_ins slug: 'custom', monitor_config: Sentry::Cron::MonitorConfig.from_crontab('5 * * * *')
  649. def perform(*args)
  650. # do stuff
  651. end
  652. end`;
  653. const customCode = `# define the monitor config with an interval
  654. sentry_monitor_check_ins slug: 'custom', monitor_config: Sentry::Cron::MonitorConfig.from_interval(1, :minute)
  655. # define the monitor config with a crontab
  656. sentry_monitor_check_ins slug: 'custom', monitor_config: Sentry::Cron::MonitorConfig.from_crontab('5 * * * *')`;
  657. return (
  658. <Fragment>
  659. <div>
  660. {tct(
  661. 'You can use the mixin module from the [additionalDocs: Ruby SDK] to automatically capture check-ins from your jobs rather than creating them manually.',
  662. {
  663. additionalDocs: (
  664. <ExternalLink href="https://docs.sentry.io/platforms/ruby/crons/#job-monitoring" />
  665. ),
  666. }
  667. )}
  668. </div>
  669. <div>{t('ActiveJob Example:')}</div>
  670. <CodeSnippet language="ruby">{activeJobCode}</CodeSnippet>
  671. <div>{t('Sidekiq Example:')}</div>
  672. <CodeSnippet language="ruby">{sidekiqJobCode}</CodeSnippet>
  673. <div>
  674. {t(
  675. 'You must pass in the monitor config explicity for upserts or you must create a new monitor explicitly in the UI.'
  676. )}
  677. </div>
  678. <CodeSnippet language="ruby">{customCode}</CodeSnippet>
  679. </Fragment>
  680. );
  681. }
  682. export function RubySidekiqAutoPlatformGuide() {
  683. const sidekiqCronCode = `Sentry.init do |config|
  684. # for sidekiq-cron
  685. config.enabled_patches += [:sidekiq_cron]
  686. # for sidekiq-scheduler
  687. config.enabled_patches += [:sidekiq_scheduler]
  688. end`;
  689. return (
  690. <Fragment>
  691. <div>
  692. {tct(
  693. 'If you use gems such as [sidekiqCronLink:sidekiq-cron] or [sidekiqSchedulerLink:sidekiq-scheduler] to manage your scheduled jobs, Sentry can automatically monitor all of them for you without any additional configuration.',
  694. {
  695. sidekiqCronLink: (
  696. <ExternalLink href="https://github.com/sidekiq-cron/sidekiq-cron" />
  697. ),
  698. sidekiqSchedulerLink: (
  699. <ExternalLink href="https://github.com/sidekiq-scheduler/sidekiq-scheduler" />
  700. ),
  701. }
  702. )}
  703. </div>
  704. <div>
  705. {tct(
  706. '[installLink:Install and configure] the Sentry Ruby and Sidekiq SDKs (min v5.14.0) and turn on the relevant patches:',
  707. {
  708. installLink: (
  709. <ExternalLink href="https://docs.sentry.io/platforms/ruby/guides/sidekiq/" />
  710. ),
  711. }
  712. )}
  713. </div>
  714. <CodeSnippet language="ruby">{sidekiqCronCode}</CodeSnippet>
  715. </Fragment>
  716. );
  717. }
  718. export function RubyCronQuickStart(props: QuickStartProps) {
  719. const {slug} = withDefaultProps(props);
  720. const checkInSuccessCode = `# 🟑 Notify Sentry your job is running:
  721. check_in_id = Sentry.capture_check_in('${slug}', :in_progress)
  722. # Execute your scheduled task here...
  723. # 🟒 Notify Sentry your job has completed successfully:
  724. Sentry.capture_check_in('${slug}', :ok, check_in_id: check_in_id)`;
  725. const checkInFailCode = `# πŸ”΄ Notify Sentry your job has failed:
  726. Sentry.capture_check_in('${slug}', :error, check_in_id: check_in_id)`;
  727. return (
  728. <Fragment>
  729. <div>
  730. {tct(
  731. '[installLink:Install and configure] the Sentry Ruby SDK (min v5.12.0), then instrument your monitor:',
  732. {
  733. installLink: <ExternalLink href="https://docs.sentry.io/platforms/ruby/" />,
  734. }
  735. )}
  736. </div>
  737. <CodeSnippet language="ruby">{checkInSuccessCode}</CodeSnippet>
  738. <div>{t('To notify Sentry if your job execution fails')}</div>
  739. <CodeSnippet language="ruby">{checkInFailCode}</CodeSnippet>
  740. </Fragment>
  741. );
  742. }
  743. export function RubyRailsCronQuickStart(props: QuickStartProps) {
  744. const {slug} = withDefaultProps(props);
  745. const mixinCode = `class ExampleJob < ApplicationJob
  746. include Sentry::Cron::MonitorCheckIns
  747. # slug defaults to the job class name
  748. sentry_monitor_check_ins slug: '${slug}'
  749. def perform(*args)
  750. # do stuff
  751. end
  752. end`;
  753. const customCode = `# define the monitor config with an interval
  754. sentry_monitor_check_ins slug: '${slug}', monitor_config: Sentry::Cron::MonitorConfig.from_interval(1, :minute)
  755. # define the monitor config with a crontab
  756. sentry_monitor_check_ins slug: '${slug}', monitor_config: Sentry::Cron::MonitorConfig.from_crontab('5 * * * *')`;
  757. return (
  758. <Fragment>
  759. <div>
  760. {tct(
  761. '[installLink:Install and configure] the Sentry Ruby and Rails SDKs (min v5.12.0), then instrument your job with our mixin module:',
  762. {
  763. installLink: (
  764. <ExternalLink href="https://docs.sentry.io/platforms/ruby/guides/rails/" />
  765. ),
  766. }
  767. )}
  768. </div>
  769. <CodeSnippet language="ruby">{mixinCode}</CodeSnippet>
  770. <div>{t('You can pass in optional attributes as follows:')}</div>
  771. <CodeSnippet language="ruby">{customCode}</CodeSnippet>
  772. </Fragment>
  773. );
  774. }
  775. export function RubySidekiqCronQuickStart(props: QuickStartProps) {
  776. const {slug} = withDefaultProps(props);
  777. const mixinCode = `class ExampleJob
  778. incude Sidekiq::Job
  779. include Sentry::Cron::MonitorCheckIns
  780. # slug defaults to the job class name
  781. sentry_monitor_check_ins slug: '${slug}'
  782. def perform(*args)
  783. # do stuff
  784. end
  785. end`;
  786. const customCode = `# define the monitor config with an interval
  787. sentry_monitor_check_ins slug: '${slug}', monitor_config: Sentry::Cron::MonitorConfig.from_interval(1, :minute)
  788. # define the monitor config with a crontab
  789. sentry_monitor_check_ins slug: '${slug}', monitor_config: Sentry::Cron::MonitorConfig.from_crontab('5 * * * *')`;
  790. return (
  791. <Fragment>
  792. <div>
  793. {tct(
  794. '[installLink:Install and configure] the Sentry Ruby and Sidekiq SDKs (min v5.12.0), then instrument your job with our mixin module:',
  795. {
  796. installLink: (
  797. <ExternalLink href="https://docs.sentry.io/platforms/ruby/guides/sidekiq/" />
  798. ),
  799. }
  800. )}
  801. </div>
  802. <CodeSnippet language="ruby">{mixinCode}</CodeSnippet>
  803. <div>{t('You can pass in optional attributes as follows:')}</div>
  804. <CodeSnippet language="ruby">{customCode}</CodeSnippet>
  805. </Fragment>
  806. );
  807. }