Browse Source

feat(crons): Add Ruby quick start for crons (#58231)

Neel Shah 1 year ago
parent
commit
e3af40cdb7

+ 9 - 0
static/app/views/monitors/components/cronsLandingPanel.tsx

@@ -30,6 +30,7 @@ import {
   NodeJsUpsertPlatformGuide,
   PHPUpsertPlatformGuide,
   QuickStartProps,
+  RubyUpsertPlatformGuide,
 } from './quickStartEntries';
 
 enum GuideKey {
@@ -89,6 +90,14 @@ const platformGuides: Record<SupportedPlatform, PlatformGuide[]> = {
     },
   ],
   'java-spring-boot': [],
+  ruby: [
+    {
+      Guide: RubyUpsertPlatformGuide,
+      title: 'Upsert',
+      key: GuideKey.UPSERT,
+    },
+  ],
+  'ruby-rails': [],
 };
 
 export function isValidPlatform(platform?: string | null): platform is SupportedPlatform {

+ 12 - 0
static/app/views/monitors/components/monitorQuickStartGuide.tsx

@@ -22,6 +22,8 @@ import {
   PythonCeleryCronQuickStart,
   PythonCronQuickStart,
   QuickStartProps,
+  RubyCronQuickStart,
+  RubyRailsCronQuickStart,
 } from 'sentry/views/monitors/components/quickStartEntries';
 
 import {Monitor} from '../types';
@@ -108,6 +110,16 @@ const onboardingGuides: Record<string, OnboardingGuide> = {
       'java-spring',
     ]),
   },
+  ruby: {
+    label: 'Ruby',
+    Guide: RubyCronQuickStart,
+    platforms: new Set(['ruby']),
+  },
+  rubyRails: {
+    label: 'Rails',
+    Guide: RubyRailsCronQuickStart,
+    platforms: new Set(['ruby', 'ruby-rails']),
+  },
 };
 
 const guideToSelectOption = ({key, label}) => ({label, value: key});

+ 5 - 1
static/app/views/monitors/components/platformPickerPanel.tsx

@@ -18,7 +18,9 @@ export type SupportedPlatform =
   | 'node'
   | 'go'
   | 'java'
-  | 'java-spring-boot';
+  | 'java-spring-boot'
+  | 'ruby'
+  | 'ruby-rails';
 
 interface SDKPlatformInfo {
   label: string;
@@ -34,6 +36,8 @@ export const CRON_SDK_PLATFORMS: SDKPlatformInfo[] = [
   {platform: 'go', label: 'Go'},
   {platform: 'java', label: 'Java'},
   {platform: 'java-spring-boot', label: 'Spring Boot'},
+  {platform: 'ruby', label: 'Ruby'},
+  {platform: 'ruby-rails', label: 'Rails'},
 ];
 
 interface Props {

+ 123 - 0
static/app/views/monitors/components/quickStartEntries.tsx

@@ -717,3 +717,126 @@ Sentry.captureCheckIn(
     </Fragment>
   );
 }
+
+export function RubyUpsertPlatformGuide() {
+  const configCode = `# Create a config from a crontab schedule (every 10 minutes)
+monitor_config = Sentry::Cron::MonitorConfig.from_crontab(
+  '5 * * * *',
+  checkin_margin: 5, # Optional check-in margin in minutes
+  max_runtime: 15, # Optional max runtime in minutes
+  timezone: 'Europe/Vienna', # Optional timezone
+)
+
+# Create a config from an interval schedule (every 10 minutes)
+monitor_config = Sentry::Cron::MonitorConfig.from_interval(
+  10,
+  :minute,
+  checkin_margin: 5, # Optional check-in margin in minutes
+  max_runtime: 15, # Optional max runtime in minutes
+  timezone: 'Europe/Vienna', # Optional timezone
+)`;
+
+  const upsertCode = `# 🟡 Notify Sentry your job is running:
+check_in_id = Sentry.capture_check_in(
+  '<monitor-slug>',
+  :in_progress,
+  monitor_config: monitor_config
+)
+
+# Execute your scheduled task here...
+
+# 🟢 Notify Sentry your job has completed successfully:
+Sentry.capture_check_in(
+  '<monitor-slug>',
+  :ok,
+  check_in_id: check_in_id,
+  monitor_config: monitor_config
+)`;
+
+  return (
+    <Fragment>
+      <div>
+        {tct(
+          'You can use the [additionalDocs: Ruby SDK] to create and update your Monitors programmatically with code rather than creating them manually.',
+          {
+            additionalDocs: (
+              <ExternalLink href="https://docs.sentry.io/platforms/ruby/crons/#upserting-cron-monitors" />
+            ),
+          }
+        )}
+      </div>
+      <CodeSnippet language="ruby">{configCode}</CodeSnippet>
+      <CodeSnippet language="ruby">{upsertCode}</CodeSnippet>
+    </Fragment>
+  );
+}
+
+export function RubyCronQuickStart(props: QuickStartProps) {
+  const {slug} = withDefaultProps(props);
+
+  const checkInSuccessCode = `# 🟡 Notify Sentry your job is running:
+check_in_id = Sentry.capture_check_in('${slug}', :in_progress)
+
+# Execute your scheduled task here...
+
+# 🟢 Notify Sentry your job has completed successfully:
+Sentry.capture_check_in('${slug}', :ok, check_in_id: check_in_id)`;
+
+  const checkInFailCode = `# 🔴 Notify Sentry your job has failed:
+Sentry.capture_check_in('${slug}', :error, check_in_id: check_in_id)`;
+
+  return (
+    <Fragment>
+      <div>
+        {tct(
+          '[installLink:Install and configure] the Sentry Ruby SDK (min v5.12.0), then instrument your monitor:',
+          {
+            installLink: <ExternalLink href="https://docs.sentry.io/platforms/ruby/" />,
+          }
+        )}
+      </div>
+      <CodeSnippet language="ruby">{checkInSuccessCode}</CodeSnippet>
+      <div>{t('To notify Sentry if your job execution fails')}</div>
+      <CodeSnippet language="ruby">{checkInFailCode}</CodeSnippet>
+    </Fragment>
+  );
+}
+
+export function RubyRailsCronQuickStart(props: QuickStartProps) {
+  const {slug} = withDefaultProps(props);
+
+  const mixinCode = `class ExampleJob < ApplicationJob
+  include Sentry::Cron::MonitorCheckIns
+
+  # slug defaults to the job class name
+  sentry_monitor_check_ins slug: '${slug}'
+
+  def perform(*args)
+    # do stuff
+  end
+end`;
+
+  const customCode = `# define the monitor config with an interval
+sentry_monitor_check_ins slug: '${slug}', monitor_config: Sentry::Cron::MonitorConfig.from_interval(1, :minute)
+
+# define the monitor config with a crontab
+sentry_monitor_check_ins slug: '${slug}', monitor_config: Sentry::Cron::MonitorConfig.from_crontab('5 * * * *')`;
+
+  return (
+    <Fragment>
+      <div>
+        {tct(
+          '[installLink:Install and configure] the Sentry Ruby and Rails SDKs (min v5.12.0), then instrument your job with our mixin module:',
+          {
+            installLink: (
+              <ExternalLink href="https://docs.sentry.io/platforms/ruby/guides/rails/" />
+            ),
+          }
+        )}
+      </div>
+      <CodeSnippet language="ruby">{mixinCode}</CodeSnippet>
+      <div>{t('You can pass in optional attributes as follows:')}</div>
+      <CodeSnippet language="ruby">{customCode}</CodeSnippet>
+    </Fragment>
+  );
+}