Monitors - gonace/Cronitor GitHub Wiki

Create, read, update and delete monitors (Monitor API).

Getting a client

Monitors are managed through an IMonitorsClient: CronitorClient.Monitors on the static class, injected after .ConfigureCronitor(), or created with new MonitorsClient("apiKey"). See Setup for each. The examples below use monitorsClient; CronitorClient.Monitors works the same way.

Methods

Each method has a sync and an async (…Async) version. All of them throw when Cronitor answers with an error.

Method Returns Description
ListAsync(int page = 1) ListMonitorResponse One page of monitors
ListAsync(ListMonitorRequest request) ListMonitorResponse One page of monitors, filtered and sorted
GetAsync(string key) Monitor One monitor
CreateAsync(CreateMonitorRequest request) IEnumerable<Monitor> Creates one or more monitors
UpdateAsync(UpdateMonitorRequest request) IEnumerable<Monitor> Updates one or more monitors
CloneAsync(string key, string name = null) Monitor Copies a monitor
DeleteAsync(string key) Deletes a monitor
PauseAsync(string key, int? hours = null) Pauses alerting, for a number of hours or until unpaused
UnpauseAsync(string key) Resumes alerting
ActivitiesAsync, AlertsAsync, PingsAsync A monitor's history, see Activity

Monitor is Cronitor.Models.Monitor. If your project also imports System.Threading (projects with implicit usings do), Monitor alone is ambiguous with System.Threading.Monitor; use var, as below, or the full name.

Monitor types

Create a monitor from the class for its type, in Cronitor.Models.Monitors:

Class Type Monitors
Job(key) job A job's runs, reported with run and complete or fail telemetry
Heartbeat(key, schedule) event A regular event, reported with tick telemetry
Check(key, request) check A website or API, which Cronitor requests on a schedule
using Cronitor.Assertions;
using Cronitor.Constants;
using Cronitor.Models;
using Cronitor.Models.Monitors;
using Cronitor.Scheduling;

var job = new Job("nightly-backup")
{
    Schedule = Schedule.Cron.Daily(hour: 3)
};

var heartbeat = new Heartbeat("queue-worker", Schedule.Every(5).Minutes);

var check = new Check("homepage", new Request("https://example.com", new[] { Region.Frankfurt, Region.Virginia }))
{
    Schedule = Schedule.Every(1).Minutes,
    Assertions = new[]
    {
        Assertion.Response.Code.Equals(200),
        Assertion.Response.Time.LessThan("2s")
    }
};

Schedule and Assertion are fluent builders; raw strings such as "0 3 * * *" and "response.code = 200" work too. See Schedules and assertions.

A check's Request takes the URL and the regions to request it from (Cronitor.Constants.Region). It also has Method (default GET), Body, Headers, Cookies, TimeoutSeconds (default 10), FollowRedirects and VerifySsl.

Create

using Cronitor.Assertions;
using Cronitor.Models.Monitors;
using Cronitor.Requests;
using Cronitor.Scheduling;

var job = new Job("nightly-backup")
{
    Name = "Nightly backup",
    Schedule = Schedule.Cron.Daily(hour: 3),
    Assertions = new[]
    {
        Assertion.Metric.Duration.LessThan("30m")
    },
    Group = "backups",
    Tags = new[] { "database" },
    Notify = new[] { "devops" },
    Timezone = "Europe/Stockholm",
    GraceSeconds = 300
};

var monitors = await monitorsClient.CreateAsync(new CreateMonitorRequest(job));

CreateMonitorRequest also takes several monitors, which are created in one request. Monitors of different types need an explicitly typed array:

using Cronitor.Requests;

var monitors = await monitorsClient.CreateAsync(new CreateMonitorRequest(new Cronitor.Models.Monitor[] { job, heartbeat, check }));

It returns the monitors as Cronitor stored them. A monitor doesn't have to be created first: the first telemetry event for an unknown key creates it.

Properties

Properties you can set (all optional except the key):

Property Description
Key The monitor's unique key, used by the API and by telemetry. Can't contain /.
Name The display name, used in alerts and in Cronitor.
Schedule / Schedules When to expect telemetry (job, heartbeat) or how often to make requests (check). Schedule sets a single schedule.
Assertions Rules that must hold, such as a maximum duration or a response code.
Group The key of the group the monitor belongs to.
Tags Free-form tags, for filtering.
Notify Keys of the notification lists that receive alerts. Without it, the default list is used.
Environments Keys of the environments the monitor belongs to.
Note Context for whoever handles an alert, sent with it.
Timezone The time zone the schedule is in, e.g. Europe/Stockholm.
GraceSeconds How long to wait after detecting a failure before alerting.
FailureTolerance Jobs and heartbeats: failures allowed before alerting. Checks: consecutive failed requests allowed.
ScheduleTolerance Missed scheduled runs allowed before alerting.
RealertInterval How long to wait before alerting again while the monitor keeps failing, e.g. "every 8 hours".
ConsecutiveAlertThreshold How many alerts are sent in a row before alerting pauses until the monitor recovers (1–1000).
Paused Set to true to create a monitor that starts paused.
StatusPages Keys of the status pages that show the monitor.
Metadata Any JSON-serializable object with extra information about the job.
Platform Where the monitor runs; for a check, the protocol (default http).

Properties Cronitor sets, read from a monitor you get or list: Passing, Paused, Running, Disabled, Initialized, LatestEvent, LatestEvents, LatestIssue, CreatedAt, ExpectedAt, Badges, MetricNames (only from GetAsync) and GroupName. They're never sent back to Cronitor.

Get

var monitor = await monitorsClient.GetAsync("nightly-backup");

if (monitor.Passing == false)
{
    Console.WriteLine($"{monitor.Name} is failing: {monitor.LatestIssue?.Name}");
}

List

ListAsync returns one page of monitors. Items holds the monitors, and Page, PageSize and Total tell you where you are:

var response = await monitorsClient.ListAsync(page: 2);

foreach (var monitor in response.Items)
{
    Console.WriteLine($"{monitor.Key}: {monitor.Name}");
}

To filter and sort, pass a ListMonitorRequest. Filters you don't set aren't sent:

using Cronitor.Constants;
using Cronitor.Requests;

var request = new ListMonitorRequest
{
    PageSize = 100,
    Group = "backups",
    Environment = "production",
    Search = "backup",
    Sort = MonitorSort.NameAscending
};
request.Types.Add(MonitorType.Job);
request.Tags.Add("database");
request.States.Add(MonitorState.Failing);

var response = await monitorsClient.ListAsync(request);
Property Filters by
Page, PageSize The page, and the number of monitors per page
Types Monitor type: MonitorType.Job, .Check, .Heartbeat, .Site
Tags Tag
States State: MonitorState.Failing, .Paused
Group Group key
Environment Environment key
Search Text in the monitor's name or key
Sort MonitorSort.CreatedAscending, .CreatedDescending, .NameAscending, .NameDescending

To read every monitor, request pages until one comes back short:

using System.Linq;
using Cronitor.Requests;

var request = new ListMonitorRequest();

while (true)
{
    var response = await monitorsClient.ListAsync(request);
    foreach (var monitor in response.Items)
    {
        Console.WriteLine(monitor.Key);
    }

    if (response.Items.Count() < response.PageSize)
    {
        break;
    }

    request.Page++;
}

Update

Get the monitor, change it, and send it back:

using Cronitor.Requests;

var monitor = await monitorsClient.GetAsync("nightly-backup");
monitor.Name = "Nightly database backup";
monitor.GraceSeconds = 600;

var monitors = await monitorsClient.UpdateAsync(new UpdateMonitorRequest(monitor));

Like CreateMonitorRequest, UpdateMonitorRequest takes one monitor or several. Properties that are null aren't sent. GraceSeconds is a number rather than a nullable one, so it's always sent: an update built from a new Job("nightly-backup") instead of a monitor you got sends a grace period of 0. Getting the monitor first avoids that.

Clone

Creates a copy of a monitor, optionally with a new name, and returns the copy:

var copy = await monitorsClient.CloneAsync("nightly-backup", "Nightly backup (staging)");

Delete

await monitorsClient.DeleteAsync("nightly-backup");

Pause and unpause

Pausing stops alerts for a monitor. Pause for a number of hours, or until you unpause it:

await monitorsClient.PauseAsync("nightly-backup", hours: 4);
await monitorsClient.PauseAsync("nightly-backup");

await monitorsClient.UnpauseAsync("nightly-backup");
⚠️ **GitHub.com Fallback** ⚠️