quickStartEntries.tsx 28 KB

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