quickStartEntries.tsx 28 KB

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