quickStartEntries.tsx 28 KB

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