# Set Up Crons | Sentry for Zap

Once implemented, it'll allow you to get alerts and metrics to help you solve errors, detect timeouts, and prevent disruptions to your service.

## [Requirements](https://docs.sentry.io/platforms/go/guides/zap/crons.md#requirements)

* Use our [getting started](https://docs.sentry.io/platforms/go/guides/zap.md) guide to install and configure the Sentry Go SDK (version `0.23.0` or newer) for your recurring job.
* [Create and configure](https://sentry.io/issues/alerts/new/crons/) your first Monitor.

## [Check-Ins (Recommended)](https://docs.sentry.io/platforms/go/guides/zap/crons.md#check-ins-recommended)

Check-in monitoring allows you to track a job's progress by completing two check-ins: one at the start of your job and another at the end of your job. This two-step process allows Sentry to notify you if your job didn't start when expected (missed) or if it exceeded its maximum runtime (failed).

```go
// 🟡 Notify Sentry your job is running:
checkinId := sentry.CaptureCheckIn(
	&sentry.CheckIn{
		MonitorSlug: "<monitor-slug>",
		Status:      sentry.CheckInStatusInProgress,
	},
	nil,
)

// Execute your scheduled task here...

// 🟢 Notify Sentry your job has completed successfully:
sentry.CaptureCheckIn(
	&sentry.CheckIn{
		ID:          *checkinId,
		MonitorSlug: "<monitor-slug>",
		Status:      sentry.CheckInStatusOK,
	},
	nil,
)
```

If your job execution fails, you can notify Sentry about the failure:

```go
// 🔴 Notify Sentry your job has failed:
sentry.CaptureCheckIn(
	&sentry.CheckIn{
		ID:          *checkinId,
		MonitorSlug: "<monitor-slug>",
		Status:      sentry.CheckInStatusError,
	},
	nil,
)
```

## [Heartbeat](https://docs.sentry.io/platforms/go/guides/zap/crons.md#heartbeat)

Heartbeat monitoring notifies Sentry of a job's status through one check-in. This setup will only notify you if your job didn't start when expected (missed). If you need to track a job to see if it exceeded its maximum runtime (failed), use check-ins instead.

```go
// Execute your scheduled task...

// 🟢 Notify Sentry your job completed successfully:
sentry.CaptureCheckIn(
	&sentry.CheckIn{
		MonitorSlug: "<monitor-slug>",
		Status:      sentry.CheckInStatusOK,
		// Specify the duration of the job.
		Duration:    time.Second * 10,
	},
	nil,
)
```

If your job execution fails, you can:

```go
// 🔴 Notify Sentry your job has failed:
sentry.CaptureCheckIn(
	&sentry.CheckIn{
		MonitorSlug: "<monitor-slug>",
		Status:      sentry.CheckInStatusError,
		Duration:    time.Second * 10,
	},
	nil,
)
```

## [Upserting Cron Monitors](https://docs.sentry.io/platforms/go/guides/zap/crons.md#upserting-cron-monitors)

You can create and update your Monitors programmatically with code rather than [creating and configuring them in Sentry.io](https://sentry.io/issues/alerts/new/crons/).

```go
// Create a crontab schedule object (every 10 minutes)
monitorSchedule := sentry.CrontabSchedule("*/10 * * * *")

// Or create an interval schedule object (every 10 minutes)
monitorSchedule := sentry.IntervalSchedule(10, sentry.MonitorScheduleUnitMinute)
```

Supported units are:

* `sentry.MonitorScheduleUnitMinute`
* `sentry.MonitorScheduleUnitHour`
* `sentry.MonitorScheduleUnitDay`
* `sentry.MonitorScheduleUnitWeek`
* `sentry.MonitorScheduleUnitMonth`
* `sentry.MonitorScheduleUnitYear`

```go
// Create a monitor config object
monitorConfig := &sentry.MonitorConfig{
	Schedule:      monitorSchedule,
	MaxRuntime:    2,
	CheckInMargin: 1,
	FailureIssueThreshold: 2,
}

// 🟡 Notify Sentry your job is running:
checkinId := sentry.CaptureCheckIn(
	&sentry.CheckIn{
		MonitorSlug: "<monitor-slug>",
		Status:      sentry.CheckInStatusInProgress,
	},
	monitorConfig,
)

// Execute your scheduled task here...

// 🟢 Notify Sentry your job has completed successfully:
sentry.CaptureCheckIn(
	&sentry.CheckIn{
		ID:          *checkinId,
		MonitorSlug: "<monitor-slug>",
		Status:      sentry.CheckInStatusOK,
	},
	monitorConfig,
)
```

A full end-to-end example can be found [in the `sentry-go` repository](https://github.com/getsentry/sentry-go/blob/dde4d360660838f3c2e0ced8205bc8f7a8d312d9/_examples/crons/main.go).

## [Connecting Errors to Cron Monitors](https://docs.sentry.io/platforms/go/guides/zap/crons.md#connecting-errors-to-cron-monitors)

To link any exceptions captured during your job's lifecycle, use [Sentry's context](https://docs.sentry.io/platforms/go/guides/zap/enriching-events/context.md) with your monitor slug.

```go
sentry.ConfigureScope(func(scope *sentry.Scope) {
	scope.SetContext("monitor", sentry.Context{"slug": "<monitor-slug>"})
})
```

## [Alerts](https://docs.sentry.io/platforms/go/guides/zap/crons.md#alerts)

When your recurring job fails to check in (missed), runs beyond its configured maximum runtime (failed), or manually reports a failure, Sentry will create an error event with a tag to your monitor.

To receive alerts about these events:

1. Navigate to **Alerts** in the sidebar.
2. Create a new alert and select "Issues" under "Errors" as the alert type.
3. Configure your alert and define a filter match to use: `The event's tags match {key} {match} {value}`.

Example: `The event's tags match monitor.slug equals my-monitor-slug-here`

Learn more in [Issue Alert Configuration](https://docs.sentry.io/product/alerts/create-alerts/issue-alert-config.md).

## [Rate Limits](https://docs.sentry.io/platforms/go/guides/zap/crons.md#rate-limits)

To prevent abuse and resource overuse, Crons limits check-ins to **6 per minute for each monitor environment**.

For example, if you have a monitor called "database-backup" with two environments:

* `database-backup` in environment `production` can send up to 6 check-ins per minute
* `database-backup` in environment `staging` can also send up to 6 check-ins per minute
* Combined, they can send up to 12 check-ins per minute

You can verify if any check-ins are being dropped by visiting the [Usage Stats](https://docs.sentry.io/product/stats.md#usage-stats) page. To avoid dropped check-ins, ensure your monitors don't exceed the rate limit.
